hollow-cube/block-handler-in-chunk-setblock

(cherry picked from commit 54e839e58a)
This commit is contained in:
mworzala 2023-07-02 15:34:54 -04:00 committed by Matt Worzala
parent f31b74a386
commit 37f6877b0a
7 changed files with 78 additions and 26 deletions

View File

@ -5,6 +5,7 @@ import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration;
import net.minestom.demo.block.TestBlockHandler;
import net.minestom.demo.commands.*;
import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager;
@ -27,6 +28,7 @@ public class Main {
MinecraftServer minecraftServer = MinecraftServer.init();
BlockManager blockManager = MinecraftServer.getBlockManager();
blockManager.registerHandler(TestBlockHandler.INSTANCE.getNamespaceId(), () -> TestBlockHandler.INSTANCE);
CommandManager commandManager = MinecraftServer.getCommandManager();
commandManager.register(new TestCommand());

View File

@ -0,0 +1,24 @@
package net.minestom.demo.block;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.utils.NamespaceID;
import org.jetbrains.annotations.NotNull;
public class TestBlockHandler implements BlockHandler {
public static final BlockHandler INSTANCE = new TestBlockHandler();
@Override
public @NotNull NamespaceID getNamespaceId() {
return NamespaceID.from("minestom", "test");
}
@Override
public void onPlace(@NotNull Placement placement) {
System.out.println(placement);
}
@Override
public void onDestroy(@NotNull Destroy destroy) {
System.out.println(destroy);
}
}

View File

@ -1,9 +1,11 @@
package net.minestom.demo.commands;
import net.minestom.demo.block.TestBlockHandler;
import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentBlockState;
import net.minestom.server.command.builder.arguments.relative.ArgumentRelativeBlockPosition;
import net.minestom.server.entity.Player;
import net.minestom.server.instance.block.Block;
import static net.minestom.server.command.builder.arguments.ArgumentType.BlockState;
import static net.minestom.server.command.builder.arguments.ArgumentType.RelativeBlockPosition;
@ -17,7 +19,12 @@ public class SetBlockCommand extends Command {
addSyntax((sender, context) -> {
final Player player = (Player) sender;
player.getInstance().setBlock(context.get(position).from(player), context.get(block));
Block blockToPlace = context.get(block);
if (blockToPlace.stateId() == Block.GOLD_BLOCK.stateId())
blockToPlace = blockToPlace.withHandler(TestBlockHandler.INSTANCE);
player.getInstance().setBlock(context.get(position).from(player), blockToPlace);
}, position, block);
}
}

View File

@ -7,6 +7,7 @@ import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.PFColumnarSpace;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.snapshot.Snapshotable;
import net.minestom.server.tag.TagHandler;
@ -15,6 +16,7 @@ import net.minestom.server.utils.chunk.ChunkSupplier;
import net.minestom.server.utils.chunk.ChunkUtils;
import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
import java.util.Set;
@ -85,7 +87,13 @@ public abstract class Chunk implements Block.Getter, Block.Setter, Biome.Getter,
* @param block the block to place
*/
@Override
public abstract void setBlock(int x, int y, int z, @NotNull Block block);
public void setBlock(int x, int y, int z, @NotNull Block block) {
setBlock(x, y, z, block, null, null);
}
protected abstract void setBlock(int x, int y, int z, @NotNull Block block,
@Nullable BlockHandler.Placement placement,
@Nullable BlockHandler.Destroy destroy);
public abstract @NotNull List<Section> getSections();

View File

@ -4,6 +4,7 @@ import com.extollit.gaming.ai.path.model.ColumnarOcclusionFieldList;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.PFBlock;
@ -56,7 +57,9 @@ public class DynamicChunk extends Chunk {
}
@Override
public void setBlock(int x, int y, int z, @NotNull Block block) {
public void setBlock(int x, int y, int z, @NotNull Block block,
@Nullable BlockHandler.Placement placement,
@Nullable BlockHandler.Destroy destroy) {
assertLock();
this.lastChange = System.currentTimeMillis();
this.chunkCache.invalidate();
@ -68,16 +71,21 @@ public class DynamicChunk extends Chunk {
columnarOcclusionFieldList.onBlockChanged(x, y, z, blockDescription, 0);
}
Section section = getSectionAt(y);
section.blockPalette()
.set(toSectionRelativeCoordinate(x), toSectionRelativeCoordinate(y), toSectionRelativeCoordinate(z), block.stateId());
section.blockPalette().set(
toSectionRelativeCoordinate(x),
toSectionRelativeCoordinate(y),
toSectionRelativeCoordinate(z),
block.stateId()
);
final int index = ChunkUtils.getBlockIndex(x, y, z);
// Handler
final BlockHandler handler = block.handler();
final Block lastCachedBlock;
if (handler != null || block.hasNbt() || block.registry().isBlockEntity()) {
this.entries.put(index, block);
lastCachedBlock = this.entries.put(index, block);
} else {
this.entries.remove(index);
lastCachedBlock = this.entries.remove(index);
}
// Block tick
if (handler != null && handler.isTickable()) {
@ -85,6 +93,21 @@ public class DynamicChunk extends Chunk {
} else {
this.tickableMap.remove(index);
}
// Update block handlers
var blockPosition = new Vec(x, y, z);
if (lastCachedBlock != null && lastCachedBlock.handler() != null) {
// Previous destroy
lastCachedBlock.handler().onDestroy(Objects.requireNonNullElseGet(destroy,
() -> new BlockHandler.Destroy(lastCachedBlock, instance, blockPosition)));
}
if (handler != null) {
// New placement
final Block finalBlock = block;
handler.onPlace(Objects.requireNonNullElseGet(placement,
() -> new BlockHandler.Placement(finalBlock, instance, blockPosition)));
}
}
@Override

View File

@ -125,9 +125,6 @@ public class InstanceContainer extends Instance {
}
this.currentlyChangingBlocks.put(blockPosition, block);
final Block previousBlock = chunk.getBlock(blockPosition);
final BlockHandler previousHandler = previousBlock.handler();
// Change id based on neighbors
final BlockPlacementRule blockPlacementRule = MinecraftServer.getBlockManager().getBlockPlacementRule(block);
if (blockPlacementRule != null) {
@ -135,7 +132,7 @@ public class InstanceContainer extends Instance {
}
// Set the block
chunk.setBlock(x, y, z, block);
chunk.setBlock(x, y, z, block, placement, destroy);
// Refresh neighbors since a new block has been placed
executeNeighboursBlockPlacementRule(blockPosition);
@ -149,19 +146,6 @@ public class InstanceContainer extends Instance {
chunk.sendPacketToViewers(new BlockEntityDataPacket(blockPosition, registry.blockEntityId(), data));
}
}
if (previousHandler != null) {
// Previous destroy
previousHandler.onDestroy(Objects.requireNonNullElseGet(destroy,
() -> new BlockHandler.Destroy(previousBlock, this, blockPosition)));
}
final BlockHandler handler = block.handler();
if (handler != null) {
// New placement
final Block finalBlock = block;
handler.onPlace(Objects.requireNonNullElseGet(placement,
() -> new BlockHandler.Placement(finalBlock, this, blockPosition)));
}
}
}

View File

@ -8,6 +8,7 @@ import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockFace;
import net.minestom.server.instance.block.BlockHandler;
import net.minestom.server.instance.light.Light;
import net.minestom.server.network.packet.server.CachedPacket;
import net.minestom.server.network.packet.server.play.data.LightData;
@ -17,6 +18,7 @@ import net.minestom.server.timer.TaskSchedule;
import net.minestom.server.utils.NamespaceID;
import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.concurrent.locks.ReentrantLock;
@ -101,8 +103,10 @@ public class LightingChunk extends DynamicChunk {
}
@Override
public void setBlock(int x, int y, int z, @NotNull Block block) {
super.setBlock(x, y, z, block);
public void setBlock(int x, int y, int z, @NotNull Block block,
@Nullable BlockHandler.Placement placement,
@Nullable BlockHandler.Destroy destroy) {
super.setBlock(x, y, z, block, placement, destroy);
this.heightmap = null;
// Invalidate neighbor chunks, since they can be updated by this block change