Skip to content

Commit

Permalink
Implement more fluid data
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexProgrammerDE committed Nov 21, 2024
1 parent 0112b2f commit aae3811
Show file tree
Hide file tree
Showing 27 changed files with 4,984 additions and 1,489 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ public class DataGenerators {
private static final List<IDataGenerator> GENERATORS =
List.of(
new RegistryKeysJavaGenerator(),
new BlockCollisionShapesDataGenerator.BlockShapesGenerator(),
new BlockCollisionShapesDataGenerator.BlockStatesGenerator(),
new BlockShapesDataGenerator.BlockShapesGenerator(),
new BlockShapesDataGenerator.BlockStatesGenerator(),
new BlocksJsonGenerator(),
new BlocksJavaGenerator(),
new FluidsJsonGenerator(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,19 @@
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenCustomHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.EmptyBlockGetter;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.shapes.VoxelShape;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.Collectors;

public class BlockCollisionShapesDataGenerator {
public class BlockShapesDataGenerator {
private static final BlockShapesCache BLOCK_SHAPES_CACHE = new BlockShapesCache();

private static boolean isAllTheSame(IntList list) {
Expand Down Expand Up @@ -68,7 +71,10 @@ private static String voxelShapeToString(VoxelShape voxelShape) {
formatDouble(y2),
formatDouble(z2))));

return String.join("|", list);
return String.join("|", String.join(";", list), Arrays.stream(Direction.values())
.filter(direction -> Block.isFaceFull(voxelShape, direction))
.map(Direction::name)
.collect(Collectors.joining(",")));
}

private static class BlockShapesCache {
Expand All @@ -91,58 +97,76 @@ public boolean equals(VoxelShape voxelShape, VoxelShape k1) {
return voxelShapeToString(voxelShape).equals(voxelShapeToString(k1));
}
});
public final Map<Block, IntList> blockCollisionShapes = new LinkedHashMap<>();
public final Map<Block, ShapesData> blockShapes = new LinkedHashMap<>();
private int lastCollisionShapeId = 0;

{
BuiltInRegistries.BLOCK.forEach(
block -> {
IntList blockCollisionShapes = new IntArrayList();
IntList blockSupportShapes = new IntArrayList();

for (var blockState : block.getStateDefinition().getPossibleStates()) {
var blockShape =
var collisionShape =
blockState.getCollisionShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);
var supportShape =
blockState.getBlockSupportShape(EmptyBlockGetter.INSTANCE, BlockPos.ZERO);

// Revert block offset
var blockShapeCenter = blockState.getOffset(BlockPos.ZERO);
var inverseBlockShapeCenter = blockShapeCenter.reverse();
blockShape =
blockShape.move(
collisionShape =
collisionShape.move(
inverseBlockShapeCenter.x,
inverseBlockShapeCenter.y,
inverseBlockShapeCenter.z);
supportShape =
supportShape.move(
inverseBlockShapeCenter.x,
inverseBlockShapeCenter.y,
inverseBlockShapeCenter.z);

blockCollisionShapes.add(
uniqueBlockShapes.computeIfAbsent(blockShape, k -> lastCollisionShapeId++));
uniqueBlockShapes.computeIfAbsent(collisionShape, k -> lastCollisionShapeId++));
blockSupportShapes.add(
uniqueBlockShapes.computeIfAbsent(supportShape, k -> lastCollisionShapeId++));
}

this.blockCollisionShapes.put(block, blockCollisionShapes);
this.blockShapes.put(block, new ShapesData(
blockCollisionShapes,
blockSupportShapes
));
});
}

public String dumpBlockShapeIndices() {
var resultBuilder = new StringBuilder();

for (var entry : blockCollisionShapes.entrySet()) {
for (var entry : blockShapes.entrySet()) {
resultBuilder.append(BuiltInRegistries.BLOCK.getKey(entry.getKey()));
var blockCollisions = entry.getValue();
if (!blockCollisions.isEmpty()) {
resultBuilder.append("|");

if (isAllTheSame(blockCollisions)) {
resultBuilder.append(blockCollisions.getInt(0));
} else {
resultBuilder.append(String.join(",",
blockCollisions.intStream().mapToObj(String::valueOf).toArray(String[]::new)));
}
}
var blockShapes = entry.getValue();
insertShape(resultBuilder, blockShapes.collisionShapes);
insertShape(resultBuilder, blockShapes.supportShapes);

resultBuilder.append("\n");
}

return resultBuilder.toString();
}

private void insertShape(StringBuilder resultBuilder, IntList supportShapes) {
if (!supportShapes.isEmpty()) {
resultBuilder.append("|");

if (isAllTheSame(supportShapes)) {
resultBuilder.append(supportShapes.getInt(0));
} else {
resultBuilder.append(String.join(",",
supportShapes.intStream().mapToObj(String::valueOf).toArray(String[]::new)));
}
}
}

public String dumpShapesObject() {
var resultBuilder = new StringBuilder();

Expand All @@ -162,7 +186,7 @@ public String dumpShapesObject() {
public static final class BlockShapesGenerator implements IDataGenerator {
@Override
public String getDataName() {
return "data/blockshapes.txt";
return "data/block-shapes.txt";
}

@Override
Expand All @@ -174,12 +198,15 @@ public String generateDataJson() {
public static final class BlockStatesGenerator implements IDataGenerator {
@Override
public String getDataName() {
return "data/blockstates.txt";
return "data/block-states.txt";
}

@Override
public String generateDataJson() {
return BLOCK_SHAPES_CACHE.dumpBlockShapeIndices();
}
}

private record ShapesData(IntList collisionShapes, IntList supportShapes) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.FallingBlock;
import net.minecraft.world.level.block.FenceGateBlock;
import net.minecraft.world.level.block.IceBlock;
import net.minecraft.world.level.block.state.BlockBehaviour;

Expand All @@ -40,6 +41,9 @@ public static JsonObject generateBlock(Block block) {

blockDesc.addProperty("destroyTime", block.defaultDestroyTime());
blockDesc.addProperty("explosionResistance", block.getExplosionResistance());
blockDesc.addProperty("friction", block.getFriction());
blockDesc.addProperty("jumpFactor", block.getJumpFactor());
blockDesc.addProperty("speedFactor", block.getSpeedFactor());

var defaultState = block.defaultBlockState();
if (defaultState.isAir()) {
Expand All @@ -51,6 +55,9 @@ public static JsonObject generateBlock(Block block) {
if (block instanceof IceBlock) {
blockDesc.addProperty("iceBlock", true);
}
if (block instanceof FenceGateBlock) {
blockDesc.addProperty("fenceGateBlock", true);
}
if (defaultState.canBeReplaced()) {
blockDesc.addProperty("replaceable", true);
}
Expand Down
4 changes: 4 additions & 0 deletions data-generator/src/main/resources/templates/BlockType.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@ public record BlockType(
Key key,
float destroyTime,
float explosionResistance,
float friction,
float jumpFactor,
float speedFactor,
boolean air,
boolean fallingBlock,
boolean iceBlock,
boolean fenceGateBlock,
boolean replaceable,
boolean requiresCorrectToolForDrops,
List<LootPoolEntry> lootTableData,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class BlockItems {
static {
for (var itemType : ItemType.REGISTRY.values()) {
for (var blockType : BlockType.REGISTRY.values()) {
var blockShapeTypes = BlockState.forDefaultBlockType(blockType).blockShapeGroup();
var blockShapeTypes = BlockState.forDefaultBlockType(blockType).blockCollisionShapeGroup();

// Let's not use bedrock as a building block
if (BlockTypeHelper.isDiggable(blockType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import com.soulfiremc.server.util.SFHelpers;
import com.soulfiremc.server.util.mcstructs.AABB;
import com.soulfiremc.server.util.mcstructs.Direction;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.cloudburstmc.math.vector.Vector3i;
Expand All @@ -27,23 +28,25 @@
import java.util.List;

@SuppressWarnings("unused")
public record BlockShapeGroup(int id, List<AABB> blockShapes, double highestY) {
public record BlockShapeGroup(int id, List<AABB> blockShapes, double highestY, List<Direction> fullFaceDirections) {
public static final Int2ObjectMap<BlockShapeGroup> FROM_ID = new Int2ObjectOpenHashMap<>();
public static final BlockShapeGroup EMPTY;

static {
SFHelpers.getResourceAsString("minecraft/blockshapes.txt")
SFHelpers.getResourceAsString("minecraft/block-shapes.txt")
.lines()
.forEach(
line -> {
var parts = line.split("\\|");
var parts = line.split("\\|", -1);

var id = Integer.parseInt(parts[0]);
var blockShapes = new ArrayList<AABB>();
var fullFaceDirections = new ArrayList<Direction>();

if (parts.length > 1) {
for (var i = 1; i < parts.length; i++) {
var part = parts[i];
var shapeString = parts[1];
if (!shapeString.isEmpty()) {
var shapeParts = shapeString.split(";");
for (var part : shapeParts) {
var subParts = part.split(",");
var shape =
new AABB(
Expand All @@ -57,12 +60,21 @@ public record BlockShapeGroup(int id, List<AABB> blockShapes, double highestY) {
}
}

var faceString = parts[2];
if (!faceString.isEmpty()) {
var fullFaces = faceString.split(",");
for (var face : fullFaces) {
fullFaceDirections.add(Direction.valueOf(face));
}
}

FROM_ID.put(
id,
new BlockShapeGroup(
id,
blockShapes,
blockShapes.stream().mapToDouble(a -> a.maxY).max().orElse(0)));
blockShapes.stream().mapToDouble(a -> a.maxY).max().orElse(0),
fullFaceDirections));
});

EMPTY = getById(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,31 +27,44 @@
import java.util.Map;

public class BlockShapeLoader {
public static final Map<Key, List<BlockShapeGroup>> BLOCK_SHAPES =
public static final Map<Key, List<BlockShapeGroup>> BLOCK_COLLISION_SHAPES =
new Object2ObjectOpenHashMap<>();
public static final Map<Key, List<BlockShapeGroup>> BLOCK_SUPPORT_SHAPES =
new Object2ObjectOpenHashMap<>();

static {
SFHelpers.getResourceAsString("minecraft/blockstates.txt")
SFHelpers.getResourceAsString("minecraft/block-states.txt")
.lines()
.forEach(
line -> {
var parts = line.split("\\|");
@Subst("empty") var keyString = parts[0];
var key = Key.key(keyString);

var blockShapeTypes = new ArrayList<BlockShapeGroup>();
var blockCollisionShapeTypes = new ArrayList<BlockShapeGroup>();
var blockSupportShapeTypes = new ArrayList<BlockShapeGroup>();
if (parts.length > 1) {
var part = parts[1];
{
var subParts = parts[1].split(",");
for (var subPart : subParts) {
var id = Integer.parseInt(subPart);
var blockShapeType = BlockShapeGroup.getById(id);
blockCollisionShapeTypes.add(blockShapeType);
}
}

var subParts = part.split(",");
for (var subPart : subParts) {
var id = Integer.parseInt(subPart);
var blockShapeType = BlockShapeGroup.getById(id);
blockShapeTypes.add(blockShapeType);
{
var subParts = parts[2].split(",");
for (var subPart : subParts) {
var id = Integer.parseInt(subPart);
var blockShapeType = BlockShapeGroup.getById(id);
blockSupportShapeTypes.add(blockShapeType);
}
}
}

BLOCK_SHAPES.put(key, blockShapeTypes);
BLOCK_COLLISION_SHAPES.put(key, blockCollisionShapeTypes);
BLOCK_SUPPORT_SHAPES.put(key, blockSupportShapeTypes);
});
}
}
22 changes: 16 additions & 6 deletions server/src/main/java/com/soulfiremc/server/data/BlockState.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.cloudburstmc.math.vector.Vector3i;

import java.util.List;
import java.util.Map;

public record BlockState(
int id,
Expand All @@ -30,7 +31,8 @@ public record BlockState(
boolean blocksMotion,
FluidState fluidState,
BlockStateProperties properties,
BlockShapeGroup blockShapeGroup) {
BlockShapeGroup blockCollisionShapeGroup,
BlockShapeGroup blockSupportShapeGroup) {
public BlockState(
int id,
boolean defaultState,
Expand All @@ -40,15 +42,23 @@ public BlockState(
BlockType blockType,
Key key,
int stateIndex) {
this(id, blockType, defaultState, blocksMotion, fluidState, properties, getBlockShapeGroup(key, stateIndex));
this(id, blockType, defaultState, blocksMotion, fluidState, properties, getBlockCollisionShapeGroup(key, stateIndex), getBlockSupportShapeGroup(key, stateIndex));
}

public static BlockState forDefaultBlockType(BlockType blockType) {
return blockType.statesData().defaultState();
}

private static BlockShapeGroup getBlockShapeGroup(Key key, int stateIndex) {
var shapeGroups = BlockShapeLoader.BLOCK_SHAPES.get(key);
private static BlockShapeGroup getBlockCollisionShapeGroup(Key key, int stateIndex) {
return getFromBlockShapeGroup(BlockShapeLoader.BLOCK_COLLISION_SHAPES, key, stateIndex);
}

private static BlockShapeGroup getBlockSupportShapeGroup(Key key, int stateIndex) {
return getFromBlockShapeGroup(BlockShapeLoader.BLOCK_SUPPORT_SHAPES, key, stateIndex);
}

private static BlockShapeGroup getFromBlockShapeGroup(Map<Key, List<BlockShapeGroup>> map, Key key, int stateIndex) {
var shapeGroups = map.get(key);
var size = shapeGroups.size();
if (size == 0) {
// This block has no shape stored, this is for example for air or grass
Expand All @@ -62,7 +72,7 @@ private static BlockShapeGroup getBlockShapeGroup(Key key, int stateIndex) {
}

public List<AABB> getCollisionBoxes(Vector3i block) {
return blockShapeGroup.getCollisionBoxes(block, blockType);
return blockCollisionShapeGroup.getCollisionBoxes(block, blockType);
}

@Override
Expand All @@ -86,7 +96,7 @@ public String toString() {
return "BlockState{" +
"id=" + id +
", properties=" + properties +
", blockShapeGroup=" + blockShapeGroup +
", blockCollisionShapeGroup=" + blockCollisionShapeGroup +
'}';
}
}
Loading

0 comments on commit aae3811

Please sign in to comment.