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.Style;
import net.kyori.adventure.text.format.TextColor; import net.kyori.adventure.text.format.TextColor;
import net.kyori.adventure.text.format.TextDecoration; import net.kyori.adventure.text.format.TextDecoration;
import net.minestom.demo.block.TestBlockHandler;
import net.minestom.demo.commands.*; import net.minestom.demo.commands.*;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.command.CommandManager; import net.minestom.server.command.CommandManager;
@ -27,6 +28,7 @@ public class Main {
MinecraftServer minecraftServer = MinecraftServer.init(); MinecraftServer minecraftServer = MinecraftServer.init();
BlockManager blockManager = MinecraftServer.getBlockManager(); BlockManager blockManager = MinecraftServer.getBlockManager();
blockManager.registerHandler(TestBlockHandler.INSTANCE.getNamespaceId(), () -> TestBlockHandler.INSTANCE);
CommandManager commandManager = MinecraftServer.getCommandManager(); CommandManager commandManager = MinecraftServer.getCommandManager();
commandManager.register(new TestCommand()); 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; package net.minestom.demo.commands;
import net.minestom.demo.block.TestBlockHandler;
import net.minestom.server.command.builder.Command; import net.minestom.server.command.builder.Command;
import net.minestom.server.command.builder.arguments.minecraft.ArgumentBlockState; import net.minestom.server.command.builder.arguments.minecraft.ArgumentBlockState;
import net.minestom.server.command.builder.arguments.relative.ArgumentRelativeBlockPosition; import net.minestom.server.command.builder.arguments.relative.ArgumentRelativeBlockPosition;
import net.minestom.server.entity.Player; 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.BlockState;
import static net.minestom.server.command.builder.arguments.ArgumentType.RelativeBlockPosition; import static net.minestom.server.command.builder.arguments.ArgumentType.RelativeBlockPosition;
@ -17,7 +19,12 @@ public class SetBlockCommand extends Command {
addSyntax((sender, context) -> { addSyntax((sender, context) -> {
final Player player = (Player) sender; 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); }, 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.Player;
import net.minestom.server.entity.pathfinding.PFColumnarSpace; import net.minestom.server.entity.pathfinding.PFColumnarSpace;
import net.minestom.server.instance.block.Block; 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.network.packet.server.play.ChunkDataPacket;
import net.minestom.server.snapshot.Snapshotable; import net.minestom.server.snapshot.Snapshotable;
import net.minestom.server.tag.TagHandler; 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.utils.chunk.ChunkUtils;
import net.minestom.server.world.biomes.Biome; import net.minestom.server.world.biomes.Biome;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List; import java.util.List;
import java.util.Set; 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 * @param block the block to place
*/ */
@Override @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(); 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 it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minestom.server.MinecraftServer; import net.minestom.server.MinecraftServer;
import net.minestom.server.coordinate.Point; import net.minestom.server.coordinate.Point;
import net.minestom.server.coordinate.Vec;
import net.minestom.server.entity.Entity; import net.minestom.server.entity.Entity;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.entity.pathfinding.PFBlock; import net.minestom.server.entity.pathfinding.PFBlock;
@ -56,7 +57,9 @@ public class DynamicChunk extends Chunk {
} }
@Override @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(); assertLock();
this.lastChange = System.currentTimeMillis(); this.lastChange = System.currentTimeMillis();
this.chunkCache.invalidate(); this.chunkCache.invalidate();
@ -68,16 +71,21 @@ public class DynamicChunk extends Chunk {
columnarOcclusionFieldList.onBlockChanged(x, y, z, blockDescription, 0); columnarOcclusionFieldList.onBlockChanged(x, y, z, blockDescription, 0);
} }
Section section = getSectionAt(y); Section section = getSectionAt(y);
section.blockPalette() section.blockPalette().set(
.set(toSectionRelativeCoordinate(x), toSectionRelativeCoordinate(y), toSectionRelativeCoordinate(z), block.stateId()); toSectionRelativeCoordinate(x),
toSectionRelativeCoordinate(y),
toSectionRelativeCoordinate(z),
block.stateId()
);
final int index = ChunkUtils.getBlockIndex(x, y, z); final int index = ChunkUtils.getBlockIndex(x, y, z);
// Handler // Handler
final BlockHandler handler = block.handler(); final BlockHandler handler = block.handler();
final Block lastCachedBlock;
if (handler != null || block.hasNbt() || block.registry().isBlockEntity()) { if (handler != null || block.hasNbt() || block.registry().isBlockEntity()) {
this.entries.put(index, block); lastCachedBlock = this.entries.put(index, block);
} else { } else {
this.entries.remove(index); lastCachedBlock = this.entries.remove(index);
} }
// Block tick // Block tick
if (handler != null && handler.isTickable()) { if (handler != null && handler.isTickable()) {
@ -85,6 +93,21 @@ public class DynamicChunk extends Chunk {
} else { } else {
this.tickableMap.remove(index); 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 @Override

View File

@ -125,9 +125,6 @@ public class InstanceContainer extends Instance {
} }
this.currentlyChangingBlocks.put(blockPosition, block); this.currentlyChangingBlocks.put(blockPosition, block);
final Block previousBlock = chunk.getBlock(blockPosition);
final BlockHandler previousHandler = previousBlock.handler();
// Change id based on neighbors // Change id based on neighbors
final BlockPlacementRule blockPlacementRule = MinecraftServer.getBlockManager().getBlockPlacementRule(block); final BlockPlacementRule blockPlacementRule = MinecraftServer.getBlockManager().getBlockPlacementRule(block);
if (blockPlacementRule != null) { if (blockPlacementRule != null) {
@ -135,7 +132,7 @@ public class InstanceContainer extends Instance {
} }
// Set the block // 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 // Refresh neighbors since a new block has been placed
executeNeighboursBlockPlacementRule(blockPosition); executeNeighboursBlockPlacementRule(blockPosition);
@ -149,19 +146,6 @@ public class InstanceContainer extends Instance {
chunk.sendPacketToViewers(new BlockEntityDataPacket(blockPosition, registry.blockEntityId(), data)); 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.coordinate.Vec;
import net.minestom.server.instance.block.Block; import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockFace; 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.instance.light.Light;
import net.minestom.server.network.packet.server.CachedPacket; import net.minestom.server.network.packet.server.CachedPacket;
import net.minestom.server.network.packet.server.play.data.LightData; 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.NamespaceID;
import net.minestom.server.utils.chunk.ChunkUtils; import net.minestom.server.utils.chunk.ChunkUtils;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*; import java.util.*;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
@ -101,8 +103,10 @@ public class LightingChunk extends DynamicChunk {
} }
@Override @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,
super.setBlock(x, y, z, block); @Nullable BlockHandler.Placement placement,
@Nullable BlockHandler.Destroy destroy) {
super.setBlock(x, y, z, block, placement, destroy);
this.heightmap = null; this.heightmap = null;
// Invalidate neighbor chunks, since they can be updated by this block change // Invalidate neighbor chunks, since they can be updated by this block change