3
0
Mirror von https://github.com/GeyserMC/Geyser.git synchronisiert 2024-10-02 08:00:07 +02:00

Extended collision boxes are much improved

Signed-off-by: Joshua Castle <26531652+Kas-tle@users.noreply.github.com>
Dieser Commit ist enthalten in:
Joshua Castle 2023-03-19 02:20:34 -07:00
Ursprung 9be2ec9d65
Commit eb5e281735
Es konnte kein GPG-Schlüssel zu dieser Signatur gefunden werden
GPG-Schlüssel-ID: F674F38216C35D5D
6 geänderte Dateien mit 105 neuen und 64 gelöschten Zeilen

Datei anzeigen

@ -116,12 +116,7 @@ public class BlockRegistries {
/** /**
* A registry which stores Custom Block Data for extended collision boxes and the Java IDs of blocks that will have said extended collision boxes placed above them. * A registry which stores Custom Block Data for extended collision boxes and the Java IDs of blocks that will have said extended collision boxes placed above them.
*/ */
public static final SimpleMappedRegistry<CustomBlockData, Set<Integer>> EXTENDED_COLLISION_BOXES_DATA = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new)); public static final SimpleMappedRegistry<CustomBlockData, Set<Integer>> EXTENDED_COLLISION_BOXES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
/**
* A registry which stores Java IDs of blocks that will have a custom collision block placed above them and the Bedrock ID of said collision block.
*/
public static final SimpleMappedRegistry<Integer, Integer> EXTENDED_COLLISION_BOXES = SimpleMappedRegistry.create(RegistryLoaders.empty(Object2ObjectOpenHashMap::new));
/** /**
* A registry which stores skin texture hashes to custom skull blocks. * A registry which stores skin texture hashes to custom skull blocks.

Datei anzeigen

@ -33,6 +33,8 @@ import com.nukkitx.protocol.bedrock.data.BlockPropertyData;
import com.nukkitx.protocol.bedrock.v544.Bedrock_v544; import com.nukkitx.protocol.bedrock.v544.Bedrock_v544;
import com.nukkitx.protocol.bedrock.v560.Bedrock_v560; import com.nukkitx.protocol.bedrock.v560.Bedrock_v560;
import com.nukkitx.protocol.bedrock.v567.Bedrock_v567; import com.nukkitx.protocol.bedrock.v567.Bedrock_v567;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
@ -140,16 +142,17 @@ public final class BlockRegistryPopulator {
} }
Object2IntMap<CustomBlockState> customBlockStateIds = Object2IntMaps.emptyMap(); Object2IntMap<CustomBlockState> customBlockStateIds = Object2IntMaps.emptyMap();
Int2IntMap extendedCollisionBoxes = new Int2IntOpenHashMap();
if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) { if (BlockRegistries.CUSTOM_BLOCKS.get().length != 0) {
customBlockStateIds = new Object2IntOpenHashMap<>(customExtBlockStates.size()); customBlockStateIds = new Object2IntOpenHashMap<>(customExtBlockStates.size());
Map<Integer, Integer> extendedCollisionBoxes = new HashMap<>(); //Map<Integer, Integer> extendedCollisionBoxes = new HashMap<>();
for (int i = 0; i < customExtBlockStates.size(); i++) { for (int i = 0; i < customExtBlockStates.size(); i++) {
NbtMap tag = customBlockStates.get(i); NbtMap tag = customBlockStates.get(i);
CustomBlockState blockState = customExtBlockStates.get(i); CustomBlockState blockState = customExtBlockStates.get(i);
int bedrockRuntimeId = blockStateOrderedMap.getOrDefault(tag, -1); int bedrockRuntimeId = blockStateOrderedMap.getOrDefault(tag, -1);
customBlockStateIds.put(blockState, bedrockRuntimeId); customBlockStateIds.put(blockState, bedrockRuntimeId);
Set<Integer> extendedCollisionjavaIds = BlockRegistries.EXTENDED_COLLISION_BOXES_DATA.getOrDefault(blockState.block(), null); Set<Integer> extendedCollisionjavaIds = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(blockState.block(), null);
if (extendedCollisionjavaIds != null) { if (extendedCollisionjavaIds != null) {
for (int javaId : extendedCollisionjavaIds) { for (int javaId : extendedCollisionjavaIds) {
extendedCollisionBoxes.put(javaId, bedrockRuntimeId); extendedCollisionBoxes.put(javaId, bedrockRuntimeId);
@ -157,8 +160,6 @@ public final class BlockRegistryPopulator {
} }
} }
BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes);
remappedVanillaIds = new int[vanillaBlockStates.size()]; remappedVanillaIds = new int[vanillaBlockStates.size()];
for (int i = 0; i < vanillaBlockStates.size(); i++) { for (int i = 0; i < vanillaBlockStates.size(); i++) {
remappedVanillaIds[i] = blockStateOrderedMap.getOrDefault(vanillaBlockStates.get(i), -1); remappedVanillaIds[i] = blockStateOrderedMap.getOrDefault(vanillaBlockStates.get(i), -1);
@ -273,6 +274,7 @@ public final class BlockRegistryPopulator {
.remappedVanillaIds(remappedVanillaIds) .remappedVanillaIds(remappedVanillaIds)
.blockProperties(customBlockProperties) .blockProperties(customBlockProperties)
.customBlockStateIds(customBlockStateIds) .customBlockStateIds(customBlockStateIds)
.extendedCollisionBoxes(extendedCollisionBoxes)
.build()); .build());
} }

Datei anzeigen

@ -8,7 +8,6 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet; import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.Constants;
import org.geysermc.geyser.GeyserImpl; import org.geysermc.geyser.GeyserImpl;
import org.geysermc.geyser.api.block.custom.CustomBlockData; import org.geysermc.geyser.api.block.custom.CustomBlockData;
import org.geysermc.geyser.api.block.custom.CustomBlockPermutation; import org.geysermc.geyser.api.block.custom.CustomBlockPermutation;
@ -131,7 +130,7 @@ public class CustomBlockRegistryPopulator {
BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides); BlockRegistries.CUSTOM_BLOCK_ITEM_OVERRIDES.set(customBlockItemOverrides);
GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides."); GeyserImpl.getInstance().getLogger().info("Registered " + customBlockItemOverrides.size() + " custom block item overrides.");
BlockRegistries.EXTENDED_COLLISION_BOXES_DATA.set(extendedCollisionBoxes); BlockRegistries.EXTENDED_COLLISION_BOXES.set(extendedCollisionBoxes);
GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes."); GeyserImpl.getInstance().getLogger().info("Registered " + extendedCollisionBoxes.size() + " custom block extended collision boxes.");
} }

Datei anzeigen

@ -28,6 +28,7 @@ package org.geysermc.geyser.registry.type;
import com.nukkitx.nbt.NbtList; import com.nukkitx.nbt.NbtList;
import com.nukkitx.nbt.NbtMap; import com.nukkitx.nbt.NbtMap;
import com.nukkitx.protocol.bedrock.data.BlockPropertyData; import com.nukkitx.protocol.bedrock.data.BlockPropertyData;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.IntSet; import it.unimi.dsi.fastutil.ints.IntSet;
import it.unimi.dsi.fastutil.objects.Object2IntMap; import it.unimi.dsi.fastutil.objects.Object2IntMap;
import lombok.Builder; import lombok.Builder;
@ -61,6 +62,7 @@ public class BlockMappings {
List<BlockPropertyData> blockProperties; List<BlockPropertyData> blockProperties;
Object2IntMap<CustomBlockState> customBlockStateIds; Object2IntMap<CustomBlockState> customBlockStateIds;
Int2IntMap extendedCollisionBoxes;
public int getBedrockBlockId(int state) { public int getBedrockBlockId(int state) {
if (state >= this.javaToBedrockBlocks.length) { if (state >= this.javaToBedrockBlocks.length) {

Datei anzeigen

@ -69,7 +69,6 @@ import org.geysermc.geyser.util.BlockEntityUtils;
import org.geysermc.geyser.util.ChunkUtils; import org.geysermc.geyser.util.ChunkUtils;
import java.io.IOException; import java.io.IOException;
import java.util.Arrays;
import java.util.BitSet; import java.util.BitSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -111,10 +110,13 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
try { try {
ByteBuf in = Unpooled.wrappedBuffer(packet.getChunkData()); ByteBuf in = Unpooled.wrappedBuffer(packet.getChunkData());
int runningSectionExtendedCollisions[] = new int[BlockStorage.SIZE]; int runningSectionExtendedCollisions[] = new int[BlockStorage.SIZE];
boolean extendedCollisionNextSection = false;
for (int sectionY = 0; sectionY < chunkSize; sectionY++) { for (int sectionY = 0; sectionY < chunkSize; sectionY++) {
ChunkSection javaSection = session.getCodecHelper().readChunkSection(in, biomeGlobalPalette); ChunkSection javaSection = session.getCodecHelper().readChunkSection(in, biomeGlobalPalette);
javaChunks[sectionY] = javaSection.getChunkData(); javaChunks[sectionY] = javaSection.getChunkData();
javaBiomes[sectionY] = javaSection.getBiomeData(); javaBiomes[sectionY] = javaSection.getBiomeData();
boolean extendedCollision = extendedCollisionNextSection;
boolean thisExtendedCollisionNextSection = false;
int bedrockSectionY = sectionY + (yOffset - (bedrockDimension.minY() >> 4)); int bedrockSectionY = sectionY + (yOffset - (bedrockDimension.minY() >> 4));
if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) { if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) {
@ -144,17 +146,19 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
} }
// Extended collision blocks // Extended collision blocks
switch (yzx) { if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) {
case 0 -> Arrays.fill(runningSectionExtendedCollisions, 256, 4095, 0); if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) {
case 256 -> Arrays.fill(runningSectionExtendedCollisions, 0, 256, 0); section.getBlockStorageArray()[0].setFullBlock(xzy, runningSectionExtendedCollisions[yzx]);
} runningSectionExtendedCollisions[yzx] = 0;
if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) { continue;
section.getBlockStorageArray()[0].setFullBlock(xzy, runningSectionExtendedCollisions[yzx]); }
continue; int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(javaId, -1);
} if (aboveBedrockExtendedCollisionId != -1) {
int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(javaId, -1); runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId;
if (aboveBedrockExtendedCollisionId != -1) { if ((xzy & 0xF) == 15) {
runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; thisExtendedCollisionNextSection = true;
}
}
} }
// Check if block is piston or flower to see if we'll need to create additional block entities, as they're only block entities in Bedrock // Check if block is piston or flower to see if we'll need to create additional block entities, as they're only block entities in Bedrock
@ -185,7 +189,8 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
continue; continue;
} }
IntList bedrockPalette = new IntArrayList(javaPalette.size()); IntList bedrockPalette = new IntArrayList();
int airPaletteId = -1;
waterloggedPaletteIds.clear(); waterloggedPaletteIds.clear();
bedrockOnlyBlockEntityIds.clear(); bedrockOnlyBlockEntityIds.clear();
@ -198,6 +203,17 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
waterloggedPaletteIds.set(i); waterloggedPaletteIds.set(i);
} }
if (javaId == BlockStateValues.JAVA_AIR_ID) {
airPaletteId = i;
}
if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty() && !extendedCollision) {
int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(javaId, -1);
if (aboveBedrockExtendedCollisionId != -1) {
extendedCollision = true;
}
}
// Check if block is piston, flower or cauldron to see if we'll need to create additional block entities, as they're only block entities in Bedrock // Check if block is piston, flower or cauldron to see if we'll need to create additional block entities, as they're only block entities in Bedrock
if (BlockStateValues.getFlowerPotValues().containsKey(javaId) || BlockStateValues.getPistonValues().containsKey(javaId) || BlockStateValues.isNonWaterCauldron(javaId)) { if (BlockStateValues.getFlowerPotValues().containsKey(javaId) || BlockStateValues.getPistonValues().containsKey(javaId) || BlockStateValues.isNonWaterCauldron(javaId)) {
bedrockOnlyBlockEntityIds.set(i); bedrockOnlyBlockEntityIds.set(i);
@ -224,31 +240,17 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
BlockStorage[] layers; BlockStorage[] layers;
// Convert data array from YZX to XZY coordinate order // Convert data array from YZX to XZY coordinate order
if (waterloggedPaletteIds.isEmpty()) { if (waterloggedPaletteIds.isEmpty() && !extendedCollision) {
// No blocks are waterlogged, simply convert coordinate order // No blocks are waterlogged, simply convert coordinate order
// This could probably be optimized further... // This could probably be optimized further...
for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) { for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
int paletteId = javaData.get(yzx); int paletteId = javaData.get(yzx);
int xzy = indexYZXtoXZY(yzx); int xzy = indexYZXtoXZY(yzx);
bedrockData.set(xzy, paletteId); bedrockData.set(xzy, paletteId);
switch (yzx) {
case 0 -> Arrays.fill(runningSectionExtendedCollisions, 256, 4095, 0);
case 256 -> Arrays.fill(runningSectionExtendedCollisions, 0, 256, 0);
}
int javaId = javaPalette.idToState(paletteId);
if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) {
bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx]));
continue;
}
int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(javaId, -1);
if (aboveBedrockExtendedCollisionId != -1) {
runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId;
}
} }
layers = new BlockStorage[]{ layer0 }; layers = new BlockStorage[]{ layer0 };
} else { } else if (!waterloggedPaletteIds.isEmpty() && !extendedCollision) {
// The section contains waterlogged blocks, we need to convert coordinate order AND generate a V1 block storage for // The section contains waterlogged blocks, we need to convert coordinate order AND generate a V1 block storage for
// layer 1 with palette ID 1 indicating water // layer 1 with palette ID 1 indicating water
int[] layer1Data = new int[BlockStorage.SIZE >> 5]; int[] layer1Data = new int[BlockStorage.SIZE >> 5];
@ -260,19 +262,57 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
if (waterloggedPaletteIds.get(paletteId)) { if (waterloggedPaletteIds.get(paletteId)) {
layer1Data[xzy >> 5] |= 1 << (xzy & 0x1F); layer1Data[xzy >> 5] |= 1 << (xzy & 0x1F);
} }
}
// V1 palette
IntList layer1Palette = IntList.of(
session.getBlockMappings().getBedrockAirId(), // Air - see BlockStorage's constructor for more information
session.getBlockMappings().getBedrockWaterId());
switch (yzx) { layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) };
case 0 -> Arrays.fill(runningSectionExtendedCollisions, 256, 4095, 0); } else if (waterloggedPaletteIds.isEmpty() && extendedCollision) {
case 256 -> Arrays.fill(runningSectionExtendedCollisions, 0, 256, 0); for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
} int paletteId = javaData.get(yzx);
int javaId = javaPalette.idToState(paletteId); int xzy = indexYZXtoXZY(yzx);
if (javaId == BlockStateValues.JAVA_AIR_ID && runningSectionExtendedCollisions[yzx] != 0) { bedrockData.set(xzy, paletteId);
if (paletteId == airPaletteId && runningSectionExtendedCollisions[yzx] != 0) {
bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx])); bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx]));
runningSectionExtendedCollisions[yzx] = 0;
continue; continue;
} }
int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(javaId, -1); int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(javaPalette.idToState(paletteId), -1);
if (aboveBedrockExtendedCollisionId != -1) { if (aboveBedrockExtendedCollisionId != -1) {
runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId; runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId;
if ((xzy & 0xF) == 15) {
thisExtendedCollisionNextSection = true;
}
}
}
layers = new BlockStorage[]{ layer0 };
} else {
int[] layer1Data = new int[BlockStorage.SIZE >> 5];
for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
int paletteId = javaData.get(yzx);
int xzy = indexYZXtoXZY(yzx);
bedrockData.set(xzy, paletteId);
if (waterloggedPaletteIds.get(paletteId)) {
layer1Data[xzy >> 5] |= 1 << (xzy & 0x1F);
}
if (paletteId == airPaletteId && runningSectionExtendedCollisions[yzx] != 0) {
bedrockData.set(xzy, layer0.idFor(runningSectionExtendedCollisions[yzx]));
runningSectionExtendedCollisions[yzx] = 0;
continue;
}
int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(javaPalette.idToState(paletteId), -1);
if (aboveBedrockExtendedCollisionId != -1) {
runningSectionExtendedCollisions[((yzx & 0x0ff) | (((yzx >> 8) + ((xzy & 0xF) < 15 ? 1 : -15)) << 8))] = aboveBedrockExtendedCollisionId;
if ((xzy & 0xF) == 15) {
thisExtendedCollisionNextSection = true;
}
} }
} }
@ -285,6 +325,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
} }
sections[bedrockSectionY] = new GeyserChunkSection(layers); sections[bedrockSectionY] = new GeyserChunkSection(layers);
extendedCollisionNextSection = thisExtendedCollisionNextSection;
} }
session.getChunkCache().addToCache(packet.getX(), packet.getZ(), javaChunks); session.getChunkCache().addToCache(packet.getX(), packet.getZ(), javaChunks);

Datei anzeigen

@ -143,22 +143,24 @@ public class ChunkUtils {
} }
// Extended collision boxes for custom blocks // Extended collision boxes for custom blocks
int aboveBedrockExtendedCollisionId = BlockRegistries.EXTENDED_COLLISION_BOXES.getOrDefault(blockState, -1); if (!session.getBlockMappings().getExtendedCollisionBoxes().isEmpty()) {
int aboveBlock = session.getChunkCache().getBlockAt(position.getX(), position.getY() + 1, position.getZ()); int aboveBedrockExtendedCollisionId = session.getBlockMappings().getExtendedCollisionBoxes().getOrDefault(blockState, -1);
if (aboveBedrockExtendedCollisionId != -1) { int aboveBlock = session.getGeyser().getWorldManager().getBlockAt(session, position.getX(), position.getY() + 1, position.getZ());
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); if (aboveBedrockExtendedCollisionId != -1) {
updateBlockPacket.setDataLayer(0); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); updateBlockPacket.setDataLayer(0);
updateBlockPacket.setRuntimeId(aboveBedrockExtendedCollisionId); updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.setRuntimeId(aboveBedrockExtendedCollisionId);
session.sendUpstreamPacket(updateBlockPacket); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
} else if (aboveBlock == BlockStateValues.JAVA_AIR_ID) { session.sendUpstreamPacket(updateBlockPacket);
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket(); } else if (aboveBlock == BlockStateValues.JAVA_AIR_ID) {
updateBlockPacket.setDataLayer(0); UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
updateBlockPacket.setBlockPosition(position.add(0, 1, 0)); updateBlockPacket.setDataLayer(0);
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockAirId()); updateBlockPacket.setBlockPosition(position.add(0, 1, 0));
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK); updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockAirId());
session.sendUpstreamPacket(updateBlockPacket); updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
session.sendUpstreamPacket(updateBlockPacket);
}
} }
// Prevent moving_piston from being placed // Prevent moving_piston from being placed