Skip to content

Commit

Permalink
Fix block update packet order
Browse files Browse the repository at this point in the history
  • Loading branch information
wode490390 committed Feb 29, 2024
1 parent 29a08db commit 9e637c6
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 97 deletions.
8 changes: 8 additions & 0 deletions src/main/java/cn/nukkit/block/Block.java
Original file line number Diff line number Diff line change
Expand Up @@ -1247,6 +1247,10 @@ public boolean is(int id) {
return getId() == id;
}

public boolean is(int id, int damage) {
return getId() == id && getDamage() == damage;
}

public boolean is(Block block) {
return getId() == block.getId();
}
Expand Down Expand Up @@ -1417,6 +1421,10 @@ public boolean isGlass() {
return false;
}

public boolean isCauldron() {
return false;
}

public boolean isWaxed() {
return false;
}
Expand Down
77 changes: 25 additions & 52 deletions src/main/java/cn/nukkit/block/BlockBed.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,28 +93,19 @@ public boolean onActivate(Item item, BlockFace face, Player player) {
return false;
}

Block blockNorth = this.north();
Block blockSouth = this.south();
Block blockEast = this.east();
Block blockWest = this.west();

Block b;
if ((this.getDamage() & 0x08) == 0x08) {
int meta = getDamage();
if ((meta & HEAD_PIECE_BIT) != 0) {
b = this;
} else {
if (blockNorth.getId() == this.getId() && (blockNorth.getDamage() & 0x08) == 0x08) {
b = blockNorth;
} else if (blockSouth.getId() == this.getId() && (blockSouth.getDamage() & 0x08) == 0x08) {
b = blockSouth;
} else if (blockEast.getId() == this.getId() && (blockEast.getDamage() & 0x08) == 0x08) {
b = blockEast;
} else if (blockWest.getId() == this.getId() && (blockWest.getDamage() & 0x08) == 0x08) {
b = blockWest;
int direction = meta & DIRECTION_MASK;
Block pair = getSide(BlockFace.fromHorizontalIndex(direction));
if (pair.getId() == BLOCK_BED && (pair.getDamage() & HEAD_PIECE_BIT) != 0 && (pair.getDamage() & DIRECTION_MASK) == direction) {
b = pair;
} else {
if (player != null) {
player.sendMessage(new TranslationContainer("tile.bed.notValid"));
}

return true;
}
}
Expand All @@ -139,19 +130,18 @@ public boolean onActivate(Item item, BlockFace face, Player player) {

@Override
public boolean place(Item item, Block block, Block target, BlockFace face, double fx, double fy, double fz, Player player) {
Block down = this.down();
if (SupportType.hasFullSupport(down, BlockFace.UP)) {
Block next = this.getSide(player.getDirection());
Block downNext = next.down();
if (SupportType.hasFullSupport(this.down(), BlockFace.UP)) {
BlockFace direction = player.getDirection();
Block head = this.getSide(direction);

if (next.canBeReplaced() && SupportType.hasFullSupport(downNext, BlockFace.UP)) {
int meta = player.getDirection().getHorizontalIndex();
if (head.canBeReplaced() && SupportType.hasFullSupport(head.down(), BlockFace.UP)) {
int meta = direction.getHorizontalIndex();

this.getLevel().setBlock(block, Block.get(this.getId(), meta), true, true);
this.getLevel().setBlock(next, Block.get(this.getId(), meta | 0x08), true, true);
this.getLevel().setBlock(block, Block.get(BLOCK_BED, meta), true, true);
this.getLevel().setBlock(head, Block.get(BLOCK_BED, meta | HEAD_PIECE_BIT), true, true);

createBlockEntity(this, item.getDamage());
createBlockEntity(next, item.getDamage());
createBlockEntity(head, item.getDamage());
return true;
}
}
Expand All @@ -161,36 +151,19 @@ public boolean place(Item item, Block block, Block target, BlockFace face, doubl

@Override
public boolean onBreak(Item item) {
Block blockNorth = this.north(); //Gets the blocks around them
Block blockSouth = this.south();
Block blockEast = this.east();
Block blockWest = this.west();

if ((this.getDamage() & 0x08) == 0x08) { //This is the Top part of bed
if (blockNorth.getId() == BLOCK_BED && (blockNorth.getDamage() & 0x08) != 0x08) { //Checks if the block ID&&meta are right
this.getLevel().setBlock(blockNorth, Block.get(BlockID.AIR), true, true);
} else if (blockSouth.getId() == BLOCK_BED && (blockSouth.getDamage() & 0x08) != 0x08) {
this.getLevel().setBlock(blockSouth, Block.get(BlockID.AIR), true, true);
} else if (blockEast.getId() == BLOCK_BED && (blockEast.getDamage() & 0x08) != 0x08) {
this.getLevel().setBlock(blockEast, Block.get(BlockID.AIR), true, true);
} else if (blockWest.getId() == BLOCK_BED && (blockWest.getDamage() & 0x08) != 0x08) {
this.getLevel().setBlock(blockWest, Block.get(BlockID.AIR), true, true);
}
} else { //Bottom Part of Bed
if (blockNorth.getId() == this.getId() && (blockNorth.getDamage() & 0x08) == 0x08) {
this.getLevel().setBlock(blockNorth, Block.get(BlockID.AIR), true, true);
} else if (blockSouth.getId() == this.getId() && (blockSouth.getDamage() & 0x08) == 0x08) {
this.getLevel().setBlock(blockSouth, Block.get(BlockID.AIR), true, true);
} else if (blockEast.getId() == this.getId() && (blockEast.getDamage() & 0x08) == 0x08) {
this.getLevel().setBlock(blockEast, Block.get(BlockID.AIR), true, true);
} else if (blockWest.getId() == this.getId() && (blockWest.getDamage() & 0x08) == 0x08) {
this.getLevel().setBlock(blockWest, Block.get(BlockID.AIR), true, true);
}
int meta = getDamage();
int direction = meta & DIRECTION_MASK;
BlockFace face = BlockFace.fromHorizontalIndex(direction);
int headPiece = meta & HEAD_PIECE_BIT;
if (headPiece != 0) {
face = face.getOpposite();
}
Block pair = getSide(face);
if (pair.getId() == BLOCK_BED && (pair.getDamage() & DIRECTION_MASK) == direction && (pair.getDamage() & HEAD_PIECE_BIT) != headPiece) {
this.getLevel().setBlock(pair, Block.get(BlockID.AIR), true, false);
}

this.getLevel().setBlock(this, Block.get(BlockID.AIR), true, false); // Do not update both parts to prevent duplication bug if there is two fallable blocks top of the bed

return true;
return super.onBreak(item);
}

private void createBlockEntity(Vector3 pos, int color) {
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/cn/nukkit/block/BlockCauldron.java
Original file line number Diff line number Diff line change
Expand Up @@ -800,4 +800,9 @@ public void setCauldronType(int type) {
public int getLightLevel() {
return isEmpty() ? 0 : getCauldronType() == LIQUID_LAVA ? 15 : 0;
}

@Override
public boolean isCauldron() {
return true;
}
}
11 changes: 7 additions & 4 deletions src/main/java/cn/nukkit/block/BlockFenceGate.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
* Package cn.nukkit.block in project Nukkit .
*/
public class BlockFenceGate extends BlockTransparentMeta implements Faceable {
public static final int DIRECTION_MASK = 0b11;
public static final int OPEN_BIT = 0b100;
public static final int IN_WALL_BIT = 0b1000;

public BlockFenceGate() {
this(0);
Expand Down Expand Up @@ -72,7 +75,7 @@ public int getToolType() {
}

private int getOffsetIndex() {
switch (this.getDamage() & 0x03) {
switch (this.getDamage() & DIRECTION_MASK) {
case 0:
case 2:
return 0;
Expand Down Expand Up @@ -173,13 +176,13 @@ public boolean toggle(Player player) {
}
}

this.setDamage(direction | ((~this.getDamage()) & 0x04));
this.setDamage(direction | ((~this.getDamage()) & OPEN_BIT));
this.level.setBlock(this, this, false, false);
return true;
}

public boolean isOpen() {
return (this.getDamage() & 0x04) > 0;
return (this.getDamage() & OPEN_BIT) > 0;
}

@Override
Expand All @@ -205,7 +208,7 @@ public Item toItem(boolean addUserData) {

@Override
public BlockFace getBlockFace() {
return BlockFace.fromHorizontalIndex(this.getDamage() & 0x07);
return BlockFace.fromHorizontalIndex(this.getDamage() & DIRECTION_MASK);
}

@Override
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/cn/nukkit/blockentity/BlockEntitySkull.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ protected void initBlockEntity() {
if (!namedTag.contains("MouthTickCount")) {
namedTag.putInt("MouthTickCount", 0);
}
if (!namedTag.contains("DoingAnimation")) {
namedTag.putBoolean("DoingAnimation", false);
}

super.initBlockEntity();
}
Expand All @@ -54,7 +57,8 @@ public CompoundTag getSpawnCompound() {
.putByte("SkullType", this.namedTag.getByte("SkullType"))
.putFloat("Rotation", namedTag.getFloat("Rotation"))
.putBoolean("MouthMoving", namedTag.getBoolean("MouthMoving"))
.putInt("MouthTickCount", namedTag.getInt("MouthTickCount"));
.putInt("MouthTickCount", namedTag.getInt("MouthTickCount"))
.putBoolean("DoingAnimation", namedTag.getBoolean("DoingAnimation"));
}

}
67 changes: 27 additions & 40 deletions src/main/java/cn/nukkit/level/Level.java
Original file line number Diff line number Diff line change
Expand Up @@ -1430,55 +1430,42 @@ public void sendBlocks(Player[] target, Vector3[] blocks, int flags) {
this.sendBlocks(target, blocks, flags, 0);
}

public void sendBlocks(Player[] target, Vector3[] blocks, int flags, boolean optimizeRebuilds) {
this.sendBlocks(target, blocks, flags, 0, optimizeRebuilds);
}

public void sendBlocks(Player[] target, Vector3[] blocks, int flags, int dataLayer) {
this.sendBlocks(target, blocks, flags, dataLayer, false);
}

public void sendBlocks(Player[] target, Vector3[] blocks, int flags, int dataLayer, boolean optimizeRebuilds) {
int size = 0;
for (Vector3 block : blocks) {
if (block != null) size++;
}
int packetIndex = 0;
UpdateBlockPacket[] packets = new UpdateBlockPacket[size];
LongSet chunks = null;
if (optimizeRebuilds) {
chunks = new LongOpenHashSet();
public void sendBlocks(Player[] target, Vector3[] blocks, int flags, int layer) {
if (target == null || target.length == 0) {
return;
}

for (Vector3 b : blocks) {
if (b == null) {
continue;
}
boolean first = !optimizeRebuilds;

if (optimizeRebuilds) {
long index = Level.chunkHash((int) b.x >> 4, (int) b.z >> 4);
if (!chunks.contains(index)) {
chunks.add(index);
first = true;
}
int x = (int) b.x;
int y = (int) b.y;
int z = (int) b.z;
int id;
int data;
if (b instanceof Block block) {
id = block.getId();
data = block.getDamage();
} else {
int fullBlock = this.getFullBlock(layer, x, y, z);
id = fullBlock >> Block.BLOCK_META_BITS;
data = fullBlock & Block.BLOCK_META_MASK;
}

UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.x = (int) b.x;
updateBlockPacket.y = (int) b.y;
updateBlockPacket.z = (int) b.z;
updateBlockPacket.flags = first ? flags : UpdateBlockPacket.FLAG_NONE;
if (b instanceof Block) {
updateBlockPacket.blockId = ((Block) b).getId();
updateBlockPacket.blockData = ((Block) b).getDamage();
} else {
int fullBlock = this.getFullBlock(0, (int) b.x, (int) b.y, (int) b.z);
updateBlockPacket.blockId = fullBlock >> Block.BLOCK_META_BITS;
updateBlockPacket.blockData = fullBlock & Block.BLOCK_META_MASK;
updateBlockPacket.x = x;
updateBlockPacket.y = y;
updateBlockPacket.z = z;
updateBlockPacket.flags = flags;
updateBlockPacket.blockId = id;
updateBlockPacket.blockData = data;
updateBlockPacket.dataLayer = layer;
for (Player player : target) {
player.dataPacket(updateBlockPacket);
}
updateBlockPacket.dataLayer = dataLayer;
packets[packetIndex++] = updateBlockPacket;
}
this.server.batchPackets(target, packets);
}

private void tickChunks() {
Expand Down Expand Up @@ -2878,7 +2865,7 @@ public Item useItemOn(Vector3 vector, Item item, BlockFace face, float fx, float
hand.position(block);
}

if (!hand.canPassThrough() && hand.getBoundingBox() != null && (!hand.is(Block.BAMBOO) || target.is(Block.BAMBOO) || target.is(Block.BAMBOO_SAPLING))) {
if (!hand.canPassThrough() && hand.getBoundingBox() != null && !hand.isDoor() && !hand.is(Block.BLOCK_BED) && !hand.is(Block.BLOCK_SKULL) && (!hand.is(Block.BAMBOO) || target.is(Block.BAMBOO) || target.is(Block.BAMBOO_SAPLING))) {
Entity[] entities = this.getCollidingEntities(hand.getBoundingBox());
for (Entity e : entities) {
if (e instanceof EntityProjectile || e instanceof EntityItem || e instanceof EntityXPOrb || e instanceof EntityFirework || e instanceof EntityPainting
Expand Down

0 comments on commit 9e637c6

Please sign in to comment.