First attempt at replacing placement rules

This commit is contained in:
TheMode 2021-08-31 19:37:27 +02:00
parent 2c0cd4ff7a
commit 540ddd8daf
6 changed files with 116 additions and 85 deletions

View File

@ -0,0 +1,59 @@
package net.minestom.server.event.generic;
import net.minestom.server.coordinate.Point;
import net.minestom.server.event.trait.BlockEvent;
import net.minestom.server.event.trait.CancellableEvent;
import net.minestom.server.event.trait.RecursiveEvent;
import net.minestom.server.instance.block.Block;
import net.minestom.server.instance.block.BlockHandler;
import org.jetbrains.annotations.NotNull;
public class BlockPlaceEvent implements RecursiveEvent, BlockEvent, CancellableEvent {
private final BlockHandler.Placement placement;
public BlockPlaceEvent(BlockHandler.Placement placement) {
this.placement = placement;
}
public BlockHandler.Placement getPlacement() {
return placement;
}
/**
* Gets the block which will be placed.
*
* @return the block to place
*/
@Override
public @NotNull Block getBlock() {
return placement.getBlock();
}
/**
* Changes the block to be placed.
*
* @param block the new block
*/
public void setBlock(@NotNull Block block) {
this.placement.setBlock(block);
}
/**
* Gets the block position.
*
* @return the block position
*/
public @NotNull Point getBlockPosition() {
return placement.getBlockPosition();
}
@Override
public boolean isCancelled() {
return placement.isCancelled();
}
@Override
public void setCancelled(boolean cancel) {
this.placement.setCancelled(cancel);
}
}

View File

@ -1,72 +1,34 @@
package net.minestom.server.event.player; package net.minestom.server.event.player;
import net.minestom.server.coordinate.Point;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.event.trait.BlockEvent; import net.minestom.server.event.generic.BlockPlaceEvent;
import net.minestom.server.event.trait.CancellableEvent;
import net.minestom.server.event.trait.PlayerEvent; import net.minestom.server.event.trait.PlayerEvent;
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 org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
* Called when a player tries placing a block. * Called when a player tries placing a block.
*/ */
public class PlayerBlockPlaceEvent implements PlayerEvent, BlockEvent, CancellableEvent { public class PlayerBlockPlaceEvent extends BlockPlaceEvent implements PlayerEvent {
private final Player player; private final Player player;
private Block block;
private final BlockFace blockFace; private final BlockFace blockFace;
private final Point blockPosition;
private final Player.Hand hand; private final Player.Hand hand;
private boolean consumeBlock; private boolean consumeBlock;
private boolean cancelled; public PlayerBlockPlaceEvent(BlockHandler.PlayerPlacement placement) {
super(placement);
public PlayerBlockPlaceEvent(@NotNull Player player, @NotNull Block block, this.player = placement.getPlayer();
@NotNull BlockFace blockFace, this.blockFace = placement.getBlockFace();
@NotNull Point blockPosition, @NotNull Player.Hand hand) { this.hand = placement.getHand();
this.player = player;
this.block = block;
this.blockFace = blockFace;
this.blockPosition = blockPosition;
this.hand = hand;
this.consumeBlock = true;
}
/**
* Gets the block which will be placed.
*
* @return the block to place
*/
@Override
public @NotNull Block getBlock() {
return block;
}
/**
* Changes the block to be placed.
*
* @param block the new block
*/
public void setBlock(@NotNull Block block) {
this.block = block;
} }
public @NotNull BlockFace getBlockFace() { public @NotNull BlockFace getBlockFace() {
return blockFace; return blockFace;
} }
/**
* Gets the block position.
*
* @return the block position
*/
public @NotNull Point getBlockPosition() {
return blockPosition;
}
/** /**
* Gets the hand with which the player is trying to place. * Gets the hand with which the player is trying to place.
* *
@ -94,16 +56,6 @@ public class PlayerBlockPlaceEvent implements PlayerEvent, BlockEvent, Cancellab
return consumeBlock; return consumeBlock;
} }
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
@Override @Override
public @NotNull Player getPlayer() { public @NotNull Player getPlayer() {
return player; return player;

View File

@ -0,0 +1,10 @@
package net.minestom.server.event.server;
import net.minestom.server.event.generic.BlockPlaceEvent;
import net.minestom.server.instance.block.BlockHandler;
public class ServerBlockPlaceEvent extends BlockPlaceEvent {
public ServerBlockPlaceEvent(BlockHandler.Placement placement) {
super(placement);
}
}

View File

@ -5,12 +5,16 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
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.coordinate.Vec;
import net.minestom.server.entity.GameMode;
import net.minestom.server.entity.Player; import net.minestom.server.entity.Player;
import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.GlobalHandles; import net.minestom.server.event.GlobalHandles;
import net.minestom.server.event.generic.BlockPlaceEvent;
import net.minestom.server.event.instance.InstanceChunkLoadEvent; import net.minestom.server.event.instance.InstanceChunkLoadEvent;
import net.minestom.server.event.instance.InstanceChunkUnloadEvent; import net.minestom.server.event.instance.InstanceChunkUnloadEvent;
import net.minestom.server.event.player.PlayerBlockBreakEvent; import net.minestom.server.event.player.PlayerBlockBreakEvent;
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
import net.minestom.server.event.server.ServerBlockPlaceEvent;
import net.minestom.server.instance.batch.ChunkGenerationBatch; import net.minestom.server.instance.batch.ChunkGenerationBatch;
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.instance.block.BlockHandler;
@ -157,6 +161,20 @@ public class InstanceContainer extends Instance {
final Point blockPosition = placement.getBlockPosition(); final Point blockPosition = placement.getBlockPosition();
final Chunk chunk = getChunkAt(blockPosition); final Chunk chunk = getChunkAt(blockPosition);
if (!ChunkUtils.isLoaded(chunk)) return false; if (!ChunkUtils.isLoaded(chunk)) return false;
BlockPlaceEvent event;
if (placement instanceof BlockHandler.PlayerPlacement) {
BlockHandler.PlayerPlacement playerPlacement = (BlockHandler.PlayerPlacement) placement;
Player player = playerPlacement.getPlayer();
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(playerPlacement);
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
event = playerBlockPlaceEvent;
} else {
event = new ServerBlockPlaceEvent(placement);
}
EventDispatcher.call(event);
if (event.isCancelled()) return false;
UNSAFE_setBlock(chunk, blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ(), UNSAFE_setBlock(chunk, blockPosition.blockX(), blockPosition.blockY(), blockPosition.blockZ(),
placement.getBlock(), placement, null); placement.getBlock(), placement, null);
return true; return true;

View File

@ -88,10 +88,12 @@ public interface BlockHandler {
*/ */
@ApiStatus.NonExtendable @ApiStatus.NonExtendable
class Placement { class Placement {
private final Block block; private Block block;
private final Instance instance; private final Instance instance;
private final Point blockPosition; private final Point blockPosition;
private boolean cancelled;
@ApiStatus.Internal @ApiStatus.Internal
public Placement(Block block, Instance instance, Point blockPosition) { public Placement(Block block, Instance instance, Point blockPosition) {
this.block = block; this.block = block;
@ -103,6 +105,10 @@ public interface BlockHandler {
return block; return block;
} }
public void setBlock(@NotNull Block block) {
this.block = block;
}
public @NotNull Instance getInstance() { public @NotNull Instance getInstance() {
return instance; return instance;
} }
@ -110,6 +116,14 @@ public interface BlockHandler {
public @NotNull Point getBlockPosition() { public @NotNull Point getBlockPosition() {
return blockPosition; return blockPosition;
} }
public boolean isCancelled() {
return cancelled;
}
public void setCancelled(boolean cancel) {
this.cancelled = cancel;
}
} }
final class PlayerPlacement extends Placement { final class PlayerPlacement extends Placement {

View File

@ -9,7 +9,6 @@ import net.minestom.server.entity.Player;
import net.minestom.server.entity.metadata.other.ArmorStandMeta; import net.minestom.server.entity.metadata.other.ArmorStandMeta;
import net.minestom.server.event.EventDispatcher; import net.minestom.server.event.EventDispatcher;
import net.minestom.server.event.player.PlayerBlockInteractEvent; import net.minestom.server.event.player.PlayerBlockInteractEvent;
import net.minestom.server.event.player.PlayerBlockPlaceEvent;
import net.minestom.server.event.player.PlayerUseItemOnBlockEvent; import net.minestom.server.event.player.PlayerUseItemOnBlockEvent;
import net.minestom.server.instance.Chunk; import net.minestom.server.instance.Chunk;
import net.minestom.server.instance.Instance; import net.minestom.server.instance.Instance;
@ -17,7 +16,6 @@ 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.block.BlockHandler;
import net.minestom.server.instance.block.BlockManager; import net.minestom.server.instance.block.BlockManager;
import net.minestom.server.instance.block.rule.BlockPlacementRule;
import net.minestom.server.inventory.PlayerInventory; import net.minestom.server.inventory.PlayerInventory;
import net.minestom.server.item.ItemStack; import net.minestom.server.item.ItemStack;
import net.minestom.server.item.Material; import net.minestom.server.item.Material;
@ -136,35 +134,15 @@ public class BlockPlacementListener {
refresh(player, chunk); refresh(player, chunk);
return; return;
} }
// BlockPlaceEvent check
PlayerBlockPlaceEvent playerBlockPlaceEvent = new PlayerBlockPlaceEvent(player, placedBlock, blockFace, placementPosition, packet.hand);
playerBlockPlaceEvent.consumeBlock(player.getGameMode() != GameMode.CREATIVE);
EventDispatcher.call(playerBlockPlaceEvent);
if (playerBlockPlaceEvent.isCancelled()) {
refresh(player, chunk);
return;
}
// BlockPlacementRule check
Block resultBlock = playerBlockPlaceEvent.getBlock();
final BlockPlacementRule blockPlacementRule = BLOCK_MANAGER.getBlockPlacementRule(resultBlock);
if (blockPlacementRule != null) {
// Get id from block placement rule instead of the event
resultBlock = blockPlacementRule.blockPlace(instance, resultBlock, blockFace, blockPosition, player);
}
if (resultBlock == null) {
refresh(player, chunk);
return;
}
// Place the block // Place the block
instance.placeBlock(new BlockHandler.PlayerPlacement(resultBlock, instance, placementPosition, player, hand, blockFace, instance.placeBlock(new BlockHandler.PlayerPlacement(placedBlock, instance, placementPosition, player, hand, blockFace,
packet.cursorPositionX, packet.cursorPositionY, packet.cursorPositionZ)); packet.cursorPositionX, packet.cursorPositionY, packet.cursorPositionZ));
// Block consuming // Block consuming
if (playerBlockPlaceEvent.doesConsumeBlock()) { //if (playerBlockPlaceEvent.doesConsumeBlock()) {
// Consume the block in the player's hand // // Consume the block in the player's hand
final ItemStack newUsedItem = usedItem.getStackingRule().apply(usedItem, usedItem.getAmount() - 1); // final ItemStack newUsedItem = usedItem.getStackingRule().apply(usedItem, usedItem.getAmount() - 1);
playerInventory.setItemInHand(hand, newUsedItem); // playerInventory.setItemInHand(hand, newUsedItem);
} //}
} }
private static void refresh(Player player, Chunk chunk) { private static void refresh(Player player, Chunk chunk) {