Skip to content

Commit

Permalink
feat: random update
Browse files Browse the repository at this point in the history
  • Loading branch information
smartcmd committed Dec 17, 2024
1 parent 64fb6ee commit b6120ba
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,20 @@ default boolean canKeepExisting(BlockStateWithPos current, BlockStateWithPos nei
void onNeighborUpdate(BlockStateWithPos current, BlockStateWithPos neighbor, BlockFace face);

/**
* Called when the block encounters random tick update.
* Called when the block encounters random update.
*
* @param blockState the block.
* @param blockStateWithPos the block that encountered the random update.
*/
void onRandomUpdate(BlockStateWithPos blockState);
default void onRandomUpdate(BlockStateWithPos blockStateWithPos) {}

/**
* Check if the block can receive random updates.
*
* @return {@code true} if the block can receive random updates, {@code false} otherwise.
*/
default boolean canRandomUpdate() {
return false;
}

/**
* Try to place a block.
Expand Down Expand Up @@ -116,22 +125,27 @@ default boolean canKeepExisting(BlockStateWithPos current, BlockStateWithPos nei
* 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.
* @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.
*
* @param blockState The block that was broken.
* @param usedItem The item that was used to break the block, can be {@code null}.
* @param entity The player who broke the block, can be {@code null}.
* @param blockState the block that was broken.
* @param usedItem the item that was used to break the block, can be {@code null}.
* @param entity the player who broke the block, can be {@code null}.
*/
void onBreak(BlockStateWithPos blockState, ItemStack usedItem, Entity entity);

void onScheduledUpdate(BlockStateWithPos blockState);
/**
* Called when a block receives a scheduled update.
*
* @param blockStateWithPos the block that received the scheduled update.
*/
default void onScheduledUpdate(BlockStateWithPos blockStateWithPos) {}

/**
* Get the block's drops when it is broke by item normally.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package org.allaymc.api.eventbus.event.block;

import org.allaymc.api.block.dto.BlockStateWithPos;
import org.allaymc.api.eventbus.event.CancellableEvent;

/**
* @author daoge_cmd
*/
public class BlockRandomUpdateEvent extends BlockEvent implements CancellableEvent {
public BlockRandomUpdateEvent(BlockStateWithPos block) {
super(block);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,6 @@ public void onNeighborUpdate(BlockStateWithPos current, BlockStateWithPos neighb
}
}

@Override
public void onRandomUpdate(BlockStateWithPos blockState) {}

@Override
public void onScheduledUpdate(BlockStateWithPos blockState) {}

@Override
public Set<ItemStack> getDrops(BlockStateWithPos blockState, ItemStack usedItem, Entity entity) {
var vanillaBlockId = BlockId.fromIdentifier(blockType.getIdentifier());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.allaymc.api.world.DimensionInfo;
import org.allaymc.api.world.biome.BiomeType;
import org.allaymc.api.world.chunk.*;
import org.allaymc.api.world.gamerule.GameRule;
import org.allaymc.api.world.storage.WorldStorage;
import org.allaymc.server.world.service.AllayLightService;
import org.cloudburstmc.nbt.NbtUtils;
Expand All @@ -31,6 +32,7 @@
import org.jetbrains.annotations.UnmodifiableView;

import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.locks.StampedLock;
import java.util.function.Consumer;
import java.util.function.Predicate;
Expand Down Expand Up @@ -79,6 +81,7 @@ public void tick(long currentTick, Dimension dimension, WorldStorage worldStorag
unsafeChunk.getBlockEntitiesUnsafe().values().forEach(blockEntity -> blockEntity.tick(currentTick));
unsafeChunk.getEntitiesUnsafe().values().forEach(entity -> entity.tick(currentTick));
tickScheduledUpdates(dimension);
tickRandomUpdates(dimension);

checkAutoSave(worldStorage);
}
Expand All @@ -104,16 +107,35 @@ protected void tickScheduledUpdates(Dimension dimension) {

var blockState = getBlockState(localX, y, localZ, layer);
var blockStateWithPos = new BlockStateWithPos(blockState, new Position3i(localX + (unsafeChunk.x << 4), y, localZ + (unsafeChunk.z << 4), dimension), layer);
if (!callScheduleUpdateEvent(blockStateWithPos)) {
if (!new BlockScheduleUpdateEvent(blockStateWithPos).call()) {
return;
}

blockState.getBehavior().onScheduledUpdate(blockStateWithPos);
});
}

protected boolean callScheduleUpdateEvent(BlockStateWithPos block) {
return new BlockScheduleUpdateEvent(block).call();
protected void tickRandomUpdates(Dimension dimension) {
int randomTickSpeed = dimension.getWorld().getWorldData().getGameRuleValue(GameRule.RANDOM_TICK_SPEED);
if (randomTickSpeed == 0) {
return;
}

for (var section : unsafeChunk.getSections()) {
int sectionY = section.sectionY();
for (int i = 0; i < randomTickSpeed; i++) {
int n = ThreadLocalRandom.current().nextInt();
int localX = n & 0xF;
int localZ = n >> 8 & 0xF;
int localY = n >> 16 & 0xF;

var blockState = section.getBlockState(localX, localY, localZ, 0);
if (blockState.getBehavior().canRandomUpdate()) {
var blockStateWithPos = new BlockStateWithPos(blockState, new Position3i(localX + (unsafeChunk.x << 4), localY + (sectionY << 4), localZ + (unsafeChunk.z << 4), dimension), 0);
blockState.getBehavior().onRandomUpdate(blockStateWithPos);
}
}
}
}

protected void checkAutoSave(WorldStorage worldStorage) {
Expand Down

0 comments on commit b6120ba

Please sign in to comment.