Skip to content

Commit

Permalink
feat: Add support for vertical slabs #79
Browse files Browse the repository at this point in the history
  • Loading branch information
BlayTheNinth committed Feb 23, 2025
1 parent 817c3f2 commit f5e085d
Show file tree
Hide file tree
Showing 17 changed files with 256 additions and 226 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import net.blay09.mods.balm.api.Balm;
import net.blay09.mods.balm.api.event.BreakBlockEvent;
import net.blay09.mods.kleeslabs.converter.SlabConverter;
import net.blay09.mods.kleeslabs.converter.HorizontalSlabConverter;
import net.blay09.mods.kleeslabs.converter.VerticalSlabConverter;
import net.blay09.mods.kleeslabs.registry.SlabRegistry;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.Item;
Expand All @@ -28,30 +30,48 @@ public static void onBreakBlock(BreakBlockEvent event) {
}

BlockHitResult rayTraceResult = rayTrace(event.getPlayer(), Balm.getHooks().getBlockReachDistance(event.getPlayer()));
Vec3 hitVec = rayTraceResult.getType() == BlockHitResult.Type.BLOCK ? rayTraceResult.getLocation() : null;
final var hitSide = rayTraceResult.getDirection();
var hitVec = rayTraceResult.getType() == BlockHitResult.Type.BLOCK ? rayTraceResult.getLocation() : null;

// Relativize the hit vector around the player position
if (hitVec != null) {
hitVec = hitVec.add(-event.getPos().getX(), -event.getPos().getY(), -event.getPos().getZ());
}

BlockState state = event.getState();
SlabConverter slabConverter = SlabRegistry.getSlabConverter(state);
final var slabConverter = SlabRegistry.getSlabConverter(state);
if (slabConverter == null || !slabConverter.isDoubleSlab(state)) {
return;
}


SlabType hit;
SlabType stay;
if (hitVec != null && hitVec.y > 0.5f) {
hit = SlabType.TOP;
stay = SlabType.BOTTOM;
BlockState dropState;
BlockState newState;

if (slabConverter instanceof HorizontalSlabConverter horizontalSlabConverter) {
if (hitVec != null && hitVec.y > 0.5f) {
hit = SlabType.TOP;
stay = SlabType.BOTTOM;
} else {
stay = SlabType.TOP;
hit = SlabType.BOTTOM;
}

dropState = horizontalSlabConverter.getSingleSlab(event.getState(), event.getLevel(), event.getPos(), event.getPlayer(), hit);
newState = horizontalSlabConverter.getSingleSlab(event.getState(), event.getLevel(), event.getPos(), event.getPlayer(), stay);
} else if (slabConverter instanceof VerticalSlabConverter verticalSlabConverter) {
if (hitSide.getAxis() != Direction.Axis.Y) {
dropState = verticalSlabConverter.getSingleSlab(event.getState(), event.getLevel(), event.getPos(), event.getPlayer(), hitSide.getOpposite());
newState = verticalSlabConverter.getSingleSlab(event.getState(), event.getLevel(), event.getPos(), event.getPlayer(), hitSide);
} else {
return;
}
} else {
stay = SlabType.TOP;
hit = SlabType.BOTTOM;
return;
}

BlockState dropState = slabConverter.getSingleSlab(event.getState(), event.getLevel(), event.getPos(), event.getPlayer(), hit);
Level level = event.getLevel();
if (!level.isClientSide() && event.getPlayer().hasCorrectToolForDrops(dropState) && !event.getPlayer().getAbilities().instabuild) {
Item slabItem = Item.byBlock(dropState.getBlock());
Expand All @@ -61,13 +81,16 @@ public static void onBreakBlock(BreakBlockEvent event) {
double xOffset = level.getRandom().nextFloat() * scale + 1f - scale * 0.5;
double yOffset = level.getRandom().nextFloat() * scale + 1f - scale * 0.5;
double zOffset = level.getRandom().nextFloat() * scale + 1f - scale * 0.5;
ItemEntity entityItem = new ItemEntity(level, event.getPos().getX() + xOffset, event.getPos().getY() + yOffset, event.getPos().getZ() + zOffset, itemStack);
ItemEntity entityItem = new ItemEntity(level,
event.getPos().getX() + xOffset,
event.getPos().getY() + yOffset,
event.getPos().getZ() + zOffset,
itemStack);
entityItem.setPickUpDelay(10);
level.addFreshEntity(entityItem);
}
}

BlockState newState = slabConverter.getSingleSlab(event.getState(), event.getLevel(), event.getPos(), event.getPlayer(), stay);
event.getLevel().setBlock(event.getPos(), newState, 1 | 2);
event.setCanceled(true);
}
Expand Down
7 changes: 0 additions & 7 deletions common/src/main/java/net/blay09/mods/kleeslabs/KleeSlabs.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,14 @@
import net.blay09.mods.balm.api.Balm;
import net.blay09.mods.balm.api.event.BreakBlockEvent;
import net.blay09.mods.balm.api.event.PlayerLoginEvent;
import net.blay09.mods.balm.api.event.client.ClientStartedEvent;
import net.blay09.mods.balm.api.event.server.ServerStartedEvent;
import net.blay09.mods.kleeslabs.network.KleeSlabsRegistryMessage;
import net.blay09.mods.kleeslabs.network.ModNetworking;
import net.blay09.mods.kleeslabs.registry.SlabRegistry;
import net.blay09.mods.kleeslabs.registry.SlabRegistryData;
import net.blay09.mods.kleeslabs.registry.json.JsonCompatLoader;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.player.Player;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;

public class KleeSlabs {

public static final String MOD_ID = "kleeslabs";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,31 @@ public static void onServerStarted(ServerStartedEvent event) {
}

public static void dumpSlabs() {
Map<String, List<ResourceLocation>> slabsByMod = BuiltInRegistries.BLOCK.keySet()
final var slabsByMod = BuiltInRegistries.BLOCK.keySet()
.stream()
.filter(itemName -> itemName.getPath().endsWith("_slab") && !itemName.getPath().contains("vertical"))
.collect(Collectors.groupingBy(ResourceLocation::getNamespace));
final var verticalSlabsByMod = BuiltInRegistries.BLOCK.keySet()
.stream()
.filter(itemName -> itemName.getPath().endsWith("_slab") && itemName.getPath().contains("vertical"))
.collect(Collectors.groupingBy(ResourceLocation::getNamespace));

for (Map.Entry<String, List<ResourceLocation>> slabs : slabsByMod.entrySet()) {
String slabsOutput = slabs.getValue().stream()
for (final var slabs : slabsByMod.entrySet()) {
final var slabsOutput = slabs.getValue().stream()
.map(ResourceLocation::getPath)
.map(it -> "\"" + it + "\"")
.sorted()
.collect(Collectors.joining(",\n"));
log.info("Slabs from mod {}:\n{}", slabs.getKey(), slabsOutput);
}

for (final var verticalSlabs : verticalSlabsByMod.entrySet()) {
final var slabsOutput = verticalSlabs.getValue().stream()
.map(ResourceLocation::getPath)
.map(it -> "\"" + it + "\"")
.sorted()
.collect(Collectors.joining(",\n"));
log.info("Vertical slabs from mod {}:\n{}", verticalSlabs.getKey(), slabsOutput);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import net.blay09.mods.balm.api.Balm;
import net.blay09.mods.balm.api.event.client.BlockHighlightDrawEvent;
import net.blay09.mods.kleeslabs.KleeSlabs;
import net.blay09.mods.kleeslabs.converter.SlabConverter;
import net.blay09.mods.kleeslabs.converter.HorizontalSlabConverter;
import net.blay09.mods.kleeslabs.registry.SlabRegistry;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
Expand Down Expand Up @@ -40,8 +40,8 @@ private static void onDrawBlockHighlight(BlockHighlightDrawEvent event) {

BlockPos pos = hitResult.getBlockPos();
BlockState state = player.level().getBlockState(pos);
SlabConverter slabConverter = SlabRegistry.getSlabConverter(state);
if (slabConverter != null && slabConverter.isDoubleSlab(state)) {
final var slabConverter = SlabRegistry.getSlabConverter(state);
if (slabConverter instanceof HorizontalSlabConverter && slabConverter.isDoubleSlab(state)) {
AABB halfAABB = new AABB(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 0.5, pos.getZ() + 1);
if (hitResult.getLocation().y - (double) pos.getY() > 0.5) {
halfAABB = halfAABB.move(0, 0.5, 0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.SlabType;

public class DefaultSlabConverter implements SlabConverter {
public class DefaultSlabConverter implements HorizontalSlabConverter {

public static final SlabConverter INSTANCE = new DefaultSlabConverter();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.blay09.mods.kleeslabs.converter;

import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.SlabType;

public interface HorizontalSlabConverter extends SlabConverter {
BlockState getSingleSlab(BlockState state, Level level, BlockPos pos, Player player, SlabType slabType);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package net.blay09.mods.kleeslabs.converter;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.Property;

import java.util.Optional;

public class QuarkVerticalSlabConverter implements VerticalSlabConverter {

@Override
public BlockState getSingleSlab(BlockState state, Level level, BlockPos pos, Player player, Direction direction) {
if (direction.getAxis() == Direction.Axis.Y) {
return state;
}

return locateProperty(state, "type")
.flatMap(property -> withLocateValue(state, property, direction.getSerializedName()))
.orElse(state);
}

private <T extends Comparable<T>> Optional<BlockState> withLocateValue(BlockState state, Property<T> property, String valueName) {
return property.getValue(valueName).map(value -> state.setValue(property, value));
}

private Optional<Property<?>> locateProperty(BlockState state, String name) {
for (final var property : state.getProperties()) {
if (property.getName().equals(name) && StringRepresentable.class.isAssignableFrom(property.getValueClass())) {
return Optional.of(property);
}
}
return Optional.empty();
}

@Override
public boolean isDoubleSlab(BlockState state) {
return locateProperty(state, "type").map(state::getValue)
.map(value -> ((StringRepresentable) value).getSerializedName())
.map(name -> name.equals("double"))
.orElse(false);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,16 +1,7 @@
package net.blay09.mods.kleeslabs.converter;

import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.SlabType;

public interface SlabConverter {
BlockState getSingleSlab(BlockState state, Level level, BlockPos pos, Player player, SlabType slabType);

default boolean isDoubleSlab(BlockState state) {
return true;
}

boolean isDoubleSlab(BlockState state);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,16 @@
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.Property;
import net.minecraft.world.level.block.state.properties.SlabType;

@Deprecated
public class SmartSlabConverter implements SlabConverter {

private final Block singleSlab;

public SmartSlabConverter(Block singleSlab) {
this.singleSlab = singleSlab;
}

public class SmartSlabConverter implements HorizontalSlabConverter {
@Override
public BlockState getSingleSlab(BlockState state, Level level, BlockPos pos, Player player, SlabType slabType) {
BlockState newState = singleSlab.defaultBlockState();
BlockState newState = state.getBlock().defaultBlockState();
for (Property<?> property : state.getProperties()) {
if (newState.getProperties().contains(property)) {
newState = copyProperty(state, newState, property);
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package net.blay09.mods.kleeslabs.converter;

import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;

public interface VerticalSlabConverter extends SlabConverter {
BlockState getSingleSlab(BlockState state, Level level, BlockPos pos, Player player, Direction direction);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ public static void registerSlabConverter(Block doubleSlab, SlabConverter convert

public static void registerSlab(SlabRegistryData data) {
try {
Constructor<?> constructor = data.getConverterClass().getConstructor(Block.class);
SlabConverter converter = (SlabConverter) constructor.newInstance(data.getSingleSlab());
Constructor<?> constructor = data.getConverterClass().getConstructor();
final var converter = (SlabConverter) constructor.newInstance();
registerSlabConverter(data.getDoubleSlab(), converter);
slabRegistry.add(data);
} catch (NoSuchMethodException e) {
KleeSlabs.logger.error("Slab converter class does not have a constructor that takes a Block argument: {}", data.getConverterClass());
KleeSlabs.logger.error("Slab converter class does not have a no-arg constructor: {}", data.getConverterClass());
} catch (IllegalAccessException | InstantiationException | InvocationTargetException e) {
KleeSlabs.logger.error("Slab converter class constructor invocation failed: {}", data.getConverterClass(), e);
}
Expand Down
Loading

0 comments on commit f5e085d

Please sign in to comment.