Refactored BlockPlaceEvent and BlockChangeDelegate. Adds BUKKIT-5558
23 classes have been removed as they are no longer needed using the new capture logic. This should help quite a bit with future MC updates. BlockPlaceEvent Refactor Before calling Item.interactWith, a recording flag is turned on for setTypeAndData to capture a blockstate for each block that attempts to be set. When a block place event is cancelled, the recorded blockstate, stack size, and metadata will revert back to the captured state. If the event is not cancelled, a notification will be sent to clients and block physics will be updated. BlockChangeDelegate Refactor Now that we have the ability to capture blockstates through world, there is no need to modify world gen classes with BlockChangeDelegate. Instead we will simply capture blocks during world generation in order to "replay" all of the captured blockstates to send back to delegates. StructureGrowDelegate and BlockSapling.TreeGenerator have also been removed as part of this change. BlockSapling and BlockMushroom will capture blockstates the same as block placement and revert back any grow events if needed. By: bloodshot <jdroque@gmail.com>
This commit is contained in:
@@ -1,35 +0,0 @@
|
|||||||
package org.bukkit.craftbukkit;
|
|
||||||
|
|
||||||
import net.minecraft.server.Block;
|
|
||||||
import net.minecraft.server.World;
|
|
||||||
|
|
||||||
import org.bukkit.BlockChangeDelegate;
|
|
||||||
|
|
||||||
public class CraftBlockChangeDelegate {
|
|
||||||
private final BlockChangeDelegate delegate;
|
|
||||||
|
|
||||||
public CraftBlockChangeDelegate(BlockChangeDelegate delegate) {
|
|
||||||
this.delegate = delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public BlockChangeDelegate getDelegate() {
|
|
||||||
return delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block getType(int x, int y, int z) {
|
|
||||||
return Block.e(this.delegate.getTypeId(x, y, z));
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setTypeAndData(int x, int y, int z, Block block, int data, int updateFlag) {
|
|
||||||
// Layering violation :(
|
|
||||||
if (delegate instanceof World) {
|
|
||||||
((World) delegate).setTypeAndData(x, y, z, block, data, 2);
|
|
||||||
} else {
|
|
||||||
delegate.setRawTypeIdAndData(x, y, z, Block.b(block), data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isEmpty(int x, int y, int z) {
|
|
||||||
return delegate.isEmpty(x, y, z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -25,10 +25,13 @@ import org.bukkit.World;
|
|||||||
import org.bukkit.block.Biome;
|
import org.bukkit.block.Biome;
|
||||||
import org.bukkit.block.Block;
|
import org.bukkit.block.Block;
|
||||||
import org.bukkit.block.BlockFace;
|
import org.bukkit.block.BlockFace;
|
||||||
|
import org.bukkit.block.BlockState;
|
||||||
import org.bukkit.craftbukkit.block.CraftBlock;
|
import org.bukkit.craftbukkit.block.CraftBlock;
|
||||||
|
import org.bukkit.craftbukkit.block.CraftBlockState;
|
||||||
import org.bukkit.craftbukkit.entity.*;
|
import org.bukkit.craftbukkit.entity.*;
|
||||||
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
||||||
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
|
import org.bukkit.craftbukkit.metadata.BlockMetadataStore;
|
||||||
|
import org.bukkit.craftbukkit.util.CraftMagicNumbers;
|
||||||
import org.bukkit.craftbukkit.util.LongHash;
|
import org.bukkit.craftbukkit.util.LongHash;
|
||||||
import org.bukkit.entity.*;
|
import org.bukkit.entity.*;
|
||||||
import org.bukkit.entity.Entity;
|
import org.bukkit.entity.Entity;
|
||||||
@@ -351,11 +354,7 @@ public class CraftWorld implements World {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean generateTree(Location loc, TreeType type) {
|
public boolean generateTree(Location loc, TreeType type) {
|
||||||
return generateTree(loc, type, world);
|
net.minecraft.server.WorldGenerator gen;
|
||||||
}
|
|
||||||
|
|
||||||
public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) {
|
|
||||||
BlockSapling.TreeGenerator gen;
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case BIG_TREE:
|
case BIG_TREE:
|
||||||
gen = new WorldGenBigTree(true);
|
gen = new WorldGenBigTree(true);
|
||||||
@@ -405,7 +404,34 @@ public class CraftWorld implements World {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return gen.generate(new CraftBlockChangeDelegate(delegate), rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
return gen.a(world, rand, loc.getBlockX(), loc.getBlockY(), loc.getBlockZ());
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean generateTree(Location loc, TreeType type, BlockChangeDelegate delegate) {
|
||||||
|
world.captureTreeGeneration = true;
|
||||||
|
world.captureBlockStates = true;
|
||||||
|
boolean grownTree = generateTree(loc, type);
|
||||||
|
world.captureBlockStates = false;
|
||||||
|
world.captureTreeGeneration = false;
|
||||||
|
if (grownTree) { // Copy block data to delegate
|
||||||
|
for (BlockState blockstate : world.capturedBlockStates) {
|
||||||
|
int x = blockstate.getX();
|
||||||
|
int y = blockstate.getY();
|
||||||
|
int z = blockstate.getZ();
|
||||||
|
net.minecraft.server.Block oldBlock = world.getType(x, y, z);
|
||||||
|
int typeId = blockstate.getTypeId();
|
||||||
|
int data = blockstate.getRawData();
|
||||||
|
int flag = ((CraftBlockState)blockstate).getFlag();
|
||||||
|
delegate.setTypeIdAndData(x, y, z, typeId, data);
|
||||||
|
net.minecraft.server.Block newBlock = world.getType(x, y, z);
|
||||||
|
world.notifyAndUpdatePhysics(x, y, z, null, oldBlock, newBlock, flag);
|
||||||
|
}
|
||||||
|
world.capturedBlockStates.clear();
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
world.capturedBlockStates.clear();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public TileEntity getTileEntityAt(final int x, final int y, final int z) {
|
public TileEntity getTileEntityAt(final int x, final int y, final int z) {
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public class CraftBlockState implements BlockState {
|
|||||||
private final int z;
|
private final int z;
|
||||||
protected int type;
|
protected int type;
|
||||||
protected MaterialData data;
|
protected MaterialData data;
|
||||||
|
protected int flag;
|
||||||
protected final byte light;
|
protected final byte light;
|
||||||
|
|
||||||
public CraftBlockState(final Block block) {
|
public CraftBlockState(final Block block) {
|
||||||
@@ -32,14 +33,24 @@ public class CraftBlockState implements BlockState {
|
|||||||
this.type = block.getTypeId();
|
this.type = block.getTypeId();
|
||||||
this.light = block.getLightLevel();
|
this.light = block.getLightLevel();
|
||||||
this.chunk = (CraftChunk) block.getChunk();
|
this.chunk = (CraftChunk) block.getChunk();
|
||||||
|
this.flag = 3;
|
||||||
|
|
||||||
createData(block.getData());
|
createData(block.getData());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CraftBlockState(final Block block, int flag) {
|
||||||
|
this(block);
|
||||||
|
this.flag = flag;
|
||||||
|
}
|
||||||
|
|
||||||
public static CraftBlockState getBlockState(net.minecraft.server.World world, int x, int y, int z) {
|
public static CraftBlockState getBlockState(net.minecraft.server.World world, int x, int y, int z) {
|
||||||
return new CraftBlockState(world.getWorld().getBlockAt(x, y, z));
|
return new CraftBlockState(world.getWorld().getBlockAt(x, y, z));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static CraftBlockState getBlockState(net.minecraft.server.World world, int x, int y, int z, int flag) {
|
||||||
|
return new CraftBlockState(world.getWorld().getBlockAt(x, y, z), flag);
|
||||||
|
}
|
||||||
|
|
||||||
public World getWorld() {
|
public World getWorld() {
|
||||||
return world;
|
return world;
|
||||||
}
|
}
|
||||||
@@ -96,6 +107,14 @@ public class CraftBlockState implements BlockState {
|
|||||||
return Material.getMaterial(getTypeId());
|
return Material.getMaterial(getTypeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setFlag(int flag) {
|
||||||
|
this.flag = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFlag() {
|
||||||
|
return flag;
|
||||||
|
}
|
||||||
|
|
||||||
public int getTypeId() {
|
public int getTypeId() {
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
@@ -224,4 +243,4 @@ public class CraftBlockState implements BlockState {
|
|||||||
public void removeMetadata(String metadataKey, Plugin owningPlugin) {
|
public void removeMetadata(String metadataKey, Plugin owningPlugin) {
|
||||||
chunk.getCraftWorld().getBlockMetadata().removeMetadata(getBlock(), metadataKey, owningPlugin);
|
chunk.getCraftWorld().getBlockMetadata().removeMetadata(getBlock(), metadataKey, owningPlugin);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,6 +102,27 @@ public class CraftEventFactory {
|
|||||||
/**
|
/**
|
||||||
* Block place methods
|
* Block place methods
|
||||||
*/
|
*/
|
||||||
|
public static BlockMultiPlaceEvent callBlockMultiPlaceEvent(World world, EntityHuman who, List<BlockState> blockStates, int clickedX, int clickedY, int clickedZ) {
|
||||||
|
CraftWorld craftWorld = world.getWorld();
|
||||||
|
CraftServer craftServer = world.getServer();
|
||||||
|
Player player = (who == null) ? null : (Player) who.getBukkitEntity();
|
||||||
|
|
||||||
|
Block blockClicked = craftWorld.getBlockAt(clickedX, clickedY, clickedZ);
|
||||||
|
|
||||||
|
boolean canBuild = true;
|
||||||
|
for (int i = 0; i < blockStates.size(); i++) {
|
||||||
|
if (!canBuild(craftWorld, player, blockStates.get(i).getX(), blockStates.get(i).getZ())) {
|
||||||
|
canBuild = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockMultiPlaceEvent event = new BlockMultiPlaceEvent(blockStates, blockClicked, player.getItemInHand(), player, canBuild);
|
||||||
|
craftServer.getPluginManager().callEvent(event);
|
||||||
|
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
public static BlockPlaceEvent callBlockPlaceEvent(World world, EntityHuman who, BlockState replacedBlockState, int clickedX, int clickedY, int clickedZ) {
|
public static BlockPlaceEvent callBlockPlaceEvent(World world, EntityHuman who, BlockState replacedBlockState, int clickedX, int clickedY, int clickedZ) {
|
||||||
CraftWorld craftWorld = world.getWorld();
|
CraftWorld craftWorld = world.getWorld();
|
||||||
CraftServer craftServer = world.getServer();
|
CraftServer craftServer = world.getServer();
|
||||||
|
|||||||
Reference in New Issue
Block a user