Skip to content

Commit

Permalink
refactor: water
Browse files Browse the repository at this point in the history
  • Loading branch information
smartcmd committed Oct 15, 2024
1 parent ae1f89a commit 0381d42
Show file tree
Hide file tree
Showing 8 changed files with 114 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,18 @@ default boolean canKeepExisting(BlockStateWithPos current, BlockStateWithPos nei
*/
void onReplace(BlockStateWithPos currentBlockState, BlockState newBlockState, PlayerInteractInfo placementInfo);

/**
* Called when a neighbor layer block is replaced.
* <pr>
* For example, if a water block is in layer 1 and layer 0 is replaced with air,
* then the water block's onNeighborLayerReplace() method will be called.
*
* @param currentBlockState The block that is being replaced.
* @param newBlockState The block that is replacing the current block.
* @param placementInfo The player placement info, can be null.
*/
void afterNeighborLayerReplace(BlockStateWithPos currentBlockState, BlockState newBlockState, PlayerInteractInfo placementInfo);

/**
* Called when a block is broken by non-creative game mode player.
*
Expand Down
2 changes: 1 addition & 1 deletion api/src/main/java/org/allaymc/api/world/Dimension.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ static UpdateBlockPacket createUpdateBlockPacket(BlockState newBlockState, int x
updateBlockPacket.setBlockPosition(Vector3i.from(x, y, z));
updateBlockPacket.setDefinition(newBlockState.toNetworkBlockDefinitionRuntime());
updateBlockPacket.setDataLayer(layer);
updateBlockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
updateBlockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL);
return updateBlockPacket;
}

Expand Down
10 changes: 10 additions & 0 deletions server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,14 @@ tasks.create("cleanWorkingDir") {
delete(it)
}
}
}

tasks.create("cleanCachesInWorkingDir") {
description = "Clean caches dir in `.run` directory"
group = "application"
doLast {
rootProject.rootDir.resolve(".run").listFiles { f -> f.name.equals("caches") }?.forEach {
delete(it)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@
import org.allaymc.api.item.enchantment.type.EnchantmentTypes;
import org.allaymc.api.utils.Utils;
import org.allaymc.api.world.Dimension;
import org.allaymc.server.block.component.event.CBlockOnInteractEvent;
import org.allaymc.server.block.component.event.CBlockOnNeighborUpdateEvent;
import org.allaymc.server.block.component.event.CBlockOnPlaceEvent;
import org.allaymc.server.block.component.event.CBlockOnReplaceEvent;
import org.allaymc.server.block.component.event.*;
import org.allaymc.server.block.type.BlockLootTable;
import org.allaymc.server.component.annotation.Identifier;
import org.allaymc.server.component.annotation.Manager;
Expand Down Expand Up @@ -109,6 +106,11 @@ public void onReplace(BlockStateWithPos currentBlockState, BlockState newBlockSt
manager.callEvent(new CBlockOnReplaceEvent(currentBlockState, newBlockState, placementInfo));
}

@Override
public void afterNeighborLayerReplace(BlockStateWithPos currentBlockState, BlockState newBlockState, PlayerInteractInfo placementInfo) {
manager.callEvent(new CBlockAfterNeighborLayerReplaceEvent(currentBlockState, newBlockState, placementInfo));
}

@Override
public void onBreak(BlockStateWithPos blockState, ItemStack usedItem, Entity entity) {
if (!isDroppable(blockState, usedItem, entity)) return;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.allaymc.server.block.component;

import org.allaymc.api.block.BlockBehavior;
import org.allaymc.api.block.dto.BlockStateWithPos;
import org.allaymc.api.block.dto.PlayerInteractInfo;
import org.allaymc.api.block.type.BlockState;
import org.allaymc.api.block.type.BlockType;
import org.allaymc.api.block.type.BlockTypes;

import static org.allaymc.api.block.type.BlockTypes.AIR;

/**
* @author daoge_cmd
*/
public class BlockWaterBaseComponentImpl extends BlockLiquidBaseComponentImpl {
public BlockWaterBaseComponentImpl(BlockType<? extends BlockBehavior> blockType) {
super(blockType);
}

@Override
public void onReplace(BlockStateWithPos currentBlockState, BlockState newBlockState, PlayerInteractInfo placementInfo) {
super.onReplace(currentBlockState, newBlockState, placementInfo);

if (currentBlockState.layer() != 0) {
return;
}

var dim = currentBlockState.pos().dimension();
if (newBlockState.getBlockType() != AIR && newBlockState.getBlockStateData().canContainLiquid()) {
// If the old block is water and the new block can contain liquid,
// we need to move water to layer 1
dim.setBlockState(currentBlockState.pos(), BlockTypes.WATER.getDefaultState(), 1);
}
}

@Override
public void afterNeighborLayerReplace(BlockStateWithPos currentBlockState, BlockState newBlockState, PlayerInteractInfo placementInfo) {
super.afterNeighborLayerReplace(currentBlockState, newBlockState, placementInfo);

if (currentBlockState.layer() != 0 || newBlockState.getBlockType() == BlockTypes.WATER) {
return;
}

var dim = currentBlockState.pos().dimension();
if (newBlockState.getBlockType() == AIR) {
// Move layer 1 water back to layer 0
dim.setBlockState(currentBlockState.pos(), BlockTypes.WATER.getDefaultState(), 0);
dim.setBlockState(currentBlockState.pos(), BlockTypes.AIR.getDefaultState(), 1);
return;
}

if (!newBlockState.getBlockStateData().canContainLiquid()) {
// New layer 0 block cannot contain liquid, remove layer 1 water
dim.setBlockState(currentBlockState.pos(), BlockTypes.AIR.getDefaultState(), 1);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.allaymc.server.block.component.event;

import lombok.AllArgsConstructor;
import lombok.Getter;
import org.allaymc.api.block.dto.BlockStateWithPos;
import org.allaymc.api.block.dto.PlayerInteractInfo;
import org.allaymc.api.block.type.BlockState;
import org.allaymc.api.eventbus.event.Event;

/**
* @author daoge_cmd
*/
@Getter
@AllArgsConstructor
public class CBlockAfterNeighborLayerReplaceEvent extends Event {
protected BlockStateWithPos currentBlockState;
protected BlockState newBlockState;
protected PlayerInteractInfo placementInfo; // Can be null
}
Original file line number Diff line number Diff line change
Expand Up @@ -1024,7 +1024,7 @@ public static void initWater() {
.builder(BlockWaterBehavior.class)
.vanillaBlock(BlockId.WATER)
.setProperties(BlockPropertyTypes.LIQUID_DEPTH)
.setBlockBaseComponentSupplier(BlockLiquidBaseComponentImpl::new)
.setBlockBaseComponentSupplier(BlockWaterBaseComponentImpl::new)
.addComponent(BlockStateDataComponentImpl.ofRedefinedShape(VoxelShapes::buildLiquidShape))
.build();
BlockTypes.FLOWING_WATER = AllayBlockType
Expand Down
21 changes: 8 additions & 13 deletions server/src/main/java/org/allaymc/server/world/AllayDimension.java
Original file line number Diff line number Diff line change
Expand Up @@ -104,21 +104,21 @@ public void setBlockState(int x, int y, int z, BlockState blockState, int layer,
var xIndex = x & 15;
var zIndex = z & 15;
var oldBlockState = chunk.getBlockState(xIndex, y, zIndex, layer);
if (oldBlockState.getBlockType() == BlockTypes.WATER && blockState.getBlockStateData().canContainLiquid()) {
// If the old block is water and the new block can contain liquid,
// we need to move water to layer 1
setBlockState(x, y, z, BlockTypes.WATER.getDefaultState(), 1);
}

var blockPos = new Position3i(x, y, z, this);
var oldBlockStateWithPos = new BlockStateWithPos(oldBlockState, blockPos, layer);
if (callBlockBehavior) {
blockState.getBehavior().onPlace(new BlockStateWithPos(oldBlockState, blockPos, layer), blockState, placementInfo);
oldBlockState.getBehavior().onReplace(new BlockStateWithPos(oldBlockState, blockPos, layer), blockState, placementInfo);
blockState.getBehavior().onPlace(oldBlockStateWithPos, blockState, placementInfo);
oldBlockState.getBehavior().onReplace(oldBlockStateWithPos, blockState, placementInfo);
}
chunk.setBlockState(xIndex, y, zIndex, blockState, layer);

if (update) updateAround(x, y, z);
if (send) chunk.sendChunkPacket(Dimension.createUpdateBlockPacket(blockState, x, y, z, layer));

if (callBlockBehavior) {
chunk.getBlockState(xIndex, y, zIndex, layer == 0 ? 1 : 0).getBehavior().afterNeighborLayerReplace(oldBlockStateWithPos, blockState, placementInfo);
}
}

@Override
Expand Down Expand Up @@ -148,12 +148,7 @@ public boolean breakBlock(int x, int y, int z, ItemStack usedItem, EntityPlayer
usedItem, player
);

if (getBlockState(x, y, z, 1).getBlockType() == BlockTypes.WATER) {
// If layer 1 has water, move it to layer 0
setBlockState(x, y, z, BlockTypes.WATER.getDefaultState());
} else {
setBlockState(x, y, z, AIR.getDefaultState());
}
setBlockState(x, y, z, AIR.getDefaultState());

if (player != null) player.exhaust(0.005f);

Expand Down

0 comments on commit 0381d42

Please sign in to comment.