Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-19 22:40:18 +01:00
Merge branch 'master' into feature/viaproxy-platform
Dieser Commit ist enthalten in:
Commit
9ba51de0ed
@ -1,5 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
`java-library`
|
`java-library`
|
||||||
|
// Ensure AP works in eclipse (no effect on other IDEs)
|
||||||
|
`eclipse`
|
||||||
id("geyser.build-logic")
|
id("geyser.build-logic")
|
||||||
id("io.freefair.lombok") version "6.3.0" apply false
|
id("io.freefair.lombok") version "6.3.0" apply false
|
||||||
}
|
}
|
||||||
|
@ -30,18 +30,20 @@ import org.cloudburstmc.protocol.common.util.Preconditions;
|
|||||||
|
|
||||||
public class GeyserChunkSection {
|
public class GeyserChunkSection {
|
||||||
|
|
||||||
// Temporary reversion to v8 as it reduces the frequnecy of https://github.com/GeyserMC/Geyser/issues/4240
|
// As of at least 1.19.80
|
||||||
// This does not fully resolve the issue so a better solution is still needed
|
private static final int CHUNK_SECTION_VERSION = 9;
|
||||||
private static final int CHUNK_SECTION_VERSION = 8;
|
|
||||||
|
|
||||||
private final BlockStorage[] storage;
|
private final BlockStorage[] storage;
|
||||||
|
// Counts up from 00 for y >= 0 and down from FF for y < 0
|
||||||
|
private final int subChunkIndex;
|
||||||
|
|
||||||
public GeyserChunkSection(int airBlockId) {
|
public GeyserChunkSection(int airBlockId, int subChunkIndex) {
|
||||||
this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)});
|
this(new BlockStorage[]{new BlockStorage(airBlockId), new BlockStorage(airBlockId)}, subChunkIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeyserChunkSection(BlockStorage[] storage) {
|
public GeyserChunkSection(BlockStorage[] storage, int subChunkIndex) {
|
||||||
this.storage = storage;
|
this.storage = storage;
|
||||||
|
this.subChunkIndex = subChunkIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getFullBlock(int x, int y, int z, int layer) {
|
public int getFullBlock(int x, int y, int z, int layer) {
|
||||||
@ -60,6 +62,7 @@ public class GeyserChunkSection {
|
|||||||
buffer.writeByte(CHUNK_SECTION_VERSION);
|
buffer.writeByte(CHUNK_SECTION_VERSION);
|
||||||
buffer.writeByte(this.storage.length);
|
buffer.writeByte(this.storage.length);
|
||||||
// Required for chunk version 9+
|
// Required for chunk version 9+
|
||||||
|
buffer.writeByte(this.subChunkIndex);
|
||||||
for (BlockStorage blockStorage : this.storage) {
|
for (BlockStorage blockStorage : this.storage) {
|
||||||
blockStorage.writeToNetwork(buffer);
|
blockStorage.writeToNetwork(buffer);
|
||||||
}
|
}
|
||||||
@ -86,12 +89,12 @@ public class GeyserChunkSection {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeyserChunkSection copy() {
|
public GeyserChunkSection copy(int subChunkIndex) {
|
||||||
BlockStorage[] storage = new BlockStorage[this.storage.length];
|
BlockStorage[] storage = new BlockStorage[this.storage.length];
|
||||||
for (int i = 0; i < storage.length; i++) {
|
for (int i = 0; i < storage.length; i++) {
|
||||||
storage[i] = this.storage[i].copy();
|
storage[i] = this.storage[i].copy();
|
||||||
}
|
}
|
||||||
return new GeyserChunkSection(storage);
|
return new GeyserChunkSection(storage, subChunkIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int blockPosition(int x, int y, int z) {
|
public static int blockPosition(int x, int y, int z) {
|
||||||
|
@ -221,6 +221,7 @@ public final class BlockRegistryPopulator {
|
|||||||
|
|
||||||
GeyserBedrockBlock airDefinition = null;
|
GeyserBedrockBlock airDefinition = null;
|
||||||
BlockDefinition commandBlockDefinition = null;
|
BlockDefinition commandBlockDefinition = null;
|
||||||
|
BlockDefinition mobSpawnerBlockDefinition = null;
|
||||||
BlockDefinition waterDefinition = null;
|
BlockDefinition waterDefinition = null;
|
||||||
BlockDefinition movingBlockDefinition = null;
|
BlockDefinition movingBlockDefinition = null;
|
||||||
Iterator<Map.Entry<String, JsonNode>> blocksIterator = BLOCKS_JSON.fields();
|
Iterator<Map.Entry<String, JsonNode>> blocksIterator = BLOCKS_JSON.fields();
|
||||||
@ -269,6 +270,7 @@ public final class BlockRegistryPopulator {
|
|||||||
case "minecraft:air" -> airDefinition = bedrockDefinition;
|
case "minecraft:air" -> airDefinition = bedrockDefinition;
|
||||||
case "minecraft:water[level=0]" -> waterDefinition = bedrockDefinition;
|
case "minecraft:water[level=0]" -> waterDefinition = bedrockDefinition;
|
||||||
case "minecraft:command_block[conditional=false,facing=north]" -> commandBlockDefinition = bedrockDefinition;
|
case "minecraft:command_block[conditional=false,facing=north]" -> commandBlockDefinition = bedrockDefinition;
|
||||||
|
case "minecraft:spawner" -> mobSpawnerBlockDefinition = bedrockDefinition;
|
||||||
case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition;
|
case "minecraft:moving_piston[facing=north,type=normal]" -> movingBlockDefinition = bedrockDefinition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -298,9 +300,13 @@ public final class BlockRegistryPopulator {
|
|||||||
if (commandBlockDefinition == null) {
|
if (commandBlockDefinition == null) {
|
||||||
throw new AssertionError("Unable to find command block in palette");
|
throw new AssertionError("Unable to find command block in palette");
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.commandBlock(commandBlockDefinition);
|
builder.commandBlock(commandBlockDefinition);
|
||||||
|
|
||||||
|
if (mobSpawnerBlockDefinition == null) {
|
||||||
|
throw new AssertionError("Unable to find mob spawner block in palette");
|
||||||
|
}
|
||||||
|
builder.mobSpawnerBlock(mobSpawnerBlockDefinition);
|
||||||
|
|
||||||
if (waterDefinition == null) {
|
if (waterDefinition == null) {
|
||||||
throw new AssertionError("Unable to find water in palette");
|
throw new AssertionError("Unable to find water in palette");
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,7 @@ public class BlockMappings implements DefinitionRegistry<GeyserBedrockBlock> {
|
|||||||
int[] remappedVanillaIds;
|
int[] remappedVanillaIds;
|
||||||
|
|
||||||
BlockDefinition commandBlock;
|
BlockDefinition commandBlock;
|
||||||
|
BlockDefinition mobSpawnerBlock;
|
||||||
|
|
||||||
Map<NbtMap, BlockDefinition> itemFrames;
|
Map<NbtMap, BlockDefinition> itemFrames;
|
||||||
Map<String, NbtMap> flowerPotBlocks;
|
Map<String, NbtMap> flowerPotBlocks;
|
||||||
|
@ -30,6 +30,7 @@ import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
|||||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||||
import org.cloudburstmc.nbt.NbtMap;
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||||
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
import org.geysermc.geyser.util.BlockEntityUtils;
|
import org.geysermc.geyser.util.BlockEntityUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -41,7 +42,7 @@ public abstract class BlockEntityTranslator {
|
|||||||
|
|
||||||
public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState);
|
public abstract void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState);
|
||||||
|
|
||||||
public NbtMap getBlockEntityTag(BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) {
|
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) {
|
||||||
NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z);
|
NbtMapBuilder tagBuilder = getConstantBedrockTag(BlockEntityUtils.getBedrockBlockEntityId(type), x, y, z);
|
||||||
translateTag(tagBuilder, tag, blockState);
|
translateTag(tagBuilder, tag, blockState);
|
||||||
return tagBuilder.build();
|
return tagBuilder.build();
|
||||||
|
@ -29,12 +29,44 @@ import com.github.steveice10.mc.protocol.data.game.level.block.BlockEntityType;
|
|||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||||
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
|
import org.cloudburstmc.nbt.NbtMap;
|
||||||
import org.cloudburstmc.nbt.NbtMapBuilder;
|
import org.cloudburstmc.nbt.NbtMapBuilder;
|
||||||
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
import org.geysermc.geyser.entity.EntityDefinition;
|
import org.geysermc.geyser.entity.EntityDefinition;
|
||||||
import org.geysermc.geyser.registry.Registries;
|
import org.geysermc.geyser.registry.Registries;
|
||||||
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
|
||||||
@BlockEntity(type = BlockEntityType.MOB_SPAWNER)
|
@BlockEntity(type = BlockEntityType.MOB_SPAWNER)
|
||||||
public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public NbtMap getBlockEntityTag(GeyserSession session, BlockEntityType type, int x, int y, int z, CompoundTag tag, int blockState) {
|
||||||
|
// Sending an empty EntityIdentifier to empty the spawner is ignored by the client, so we send a whole new spawner!
|
||||||
|
// Fixes https://github.com/GeyserMC/Geyser/issues/4214
|
||||||
|
CompoundTag spawnData = tag.get("SpawnData");
|
||||||
|
if (spawnData != null) {
|
||||||
|
CompoundTag entityTag = spawnData.get("entity");
|
||||||
|
if (entityTag.isEmpty()) {
|
||||||
|
Vector3i position = Vector3i.from(x, y, z);
|
||||||
|
// Set to air and back to reset the spawner - "just" updating the spawner doesn't work
|
||||||
|
UpdateBlockPacket emptyBlockPacket = new UpdateBlockPacket();
|
||||||
|
emptyBlockPacket.setDataLayer(0);
|
||||||
|
emptyBlockPacket.setBlockPosition(position);
|
||||||
|
emptyBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir());
|
||||||
|
session.sendUpstreamPacket(emptyBlockPacket);
|
||||||
|
|
||||||
|
UpdateBlockPacket spawnerBlockPacket = new UpdateBlockPacket();
|
||||||
|
spawnerBlockPacket.setDataLayer(0);
|
||||||
|
spawnerBlockPacket.setBlockPosition(position);
|
||||||
|
spawnerBlockPacket.setDefinition(session.getBlockMappings().getMobSpawnerBlock());
|
||||||
|
session.sendUpstreamPacket(spawnerBlockPacket);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.getBlockEntityTag(session, type, x, y, z, tag, blockState);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
|
public void translateTag(NbtMapBuilder builder, CompoundTag tag, int blockState) {
|
||||||
Tag current;
|
Tag current;
|
||||||
@ -69,8 +101,8 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
|||||||
|
|
||||||
CompoundTag spawnData = tag.get("SpawnData");
|
CompoundTag spawnData = tag.get("SpawnData");
|
||||||
if (spawnData != null) {
|
if (spawnData != null) {
|
||||||
StringTag idTag = ((CompoundTag) spawnData.get("entity")).get("id");
|
CompoundTag entityTag = spawnData.get("entity");
|
||||||
if (idTag != null) {
|
if (entityTag.get("id") instanceof StringTag idTag) {
|
||||||
// As of 1.19.3, spawners can be empty
|
// As of 1.19.3, spawners can be empty
|
||||||
String entityId = idTag.getValue();
|
String entityId = idTag.getValue();
|
||||||
builder.put("EntityIdentifier", entityId);
|
builder.put("EntityIdentifier", entityId);
|
||||||
|
@ -337,7 +337,7 @@ public class JavaUpdateRecipesTranslator extends PacketTranslator<ClientboundUpd
|
|||||||
GroupedItem groupedItem = entry.getKey();
|
GroupedItem groupedItem = entry.getKey();
|
||||||
|
|
||||||
String recipeTag = RECIPE_TAGS.get(groupedItem.id.getIdentifier());
|
String recipeTag = RECIPE_TAGS.get(groupedItem.id.getIdentifier());
|
||||||
if (recipeTag != null) {
|
if (recipeTag != null && ingredients.length > 1) {
|
||||||
optionSet.add(new ItemDescriptorWithCount(new ItemTagDescriptor(recipeTag), groupedItem.count));
|
optionSet.add(new ItemDescriptorWithCount(new ItemTagDescriptor(recipeTag), groupedItem.count));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
|||||||
}
|
}
|
||||||
|
|
||||||
Vector3i position = packet.getPosition();
|
Vector3i position = packet.getPosition();
|
||||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(type, position.getX(), position.getY(), position.getZ(),
|
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(session, type, position.getX(), position.getY(), position.getZ(),
|
||||||
packet.getNbt(), blockState), packet.getPosition());
|
packet.getNbt(), blockState), packet.getPosition());
|
||||||
// Check for custom skulls.
|
// Check for custom skulls.
|
||||||
boolean hasCustomHeadBlock = false;
|
boolean hasCustomHeadBlock = false;
|
||||||
@ -80,7 +80,7 @@ public class JavaBlockEntityDataTranslator extends PacketTranslator<ClientboundB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!hasCustomHeadBlock) {
|
if (!hasCustomHeadBlock) {
|
||||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(type, position.getX(), position.getY(), position.getZ(),
|
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(session, type, position.getX(), position.getY(), position.getZ(),
|
||||||
packet.getNbt(), blockState), packet.getPosition());
|
packet.getNbt(), blockState), packet.getPosition());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +78,8 @@ import java.util.BitSet;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.geysermc.geyser.util.ChunkUtils.SERIALIZED_CHUNK_DATA;
|
import static org.geysermc.geyser.util.ChunkUtils.EMPTY_BLOCK_STORAGE;
|
||||||
|
import static org.geysermc.geyser.util.ChunkUtils.EMPTY_CHUNK_SECTION_SIZE;
|
||||||
import static org.geysermc.geyser.util.ChunkUtils.indexYZXtoXZY;
|
import static org.geysermc.geyser.util.ChunkUtils.indexYZXtoXZY;
|
||||||
|
|
||||||
@Translator(packet = ClientboundLevelChunkWithLightPacket.class)
|
@Translator(packet = ClientboundLevelChunkWithLightPacket.class)
|
||||||
@ -127,6 +128,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
boolean thisExtendedCollisionNextSection = false;
|
boolean thisExtendedCollisionNextSection = false;
|
||||||
|
|
||||||
int bedrockSectionY = sectionY + (yOffset - (bedrockDimension.minY() >> 4));
|
int bedrockSectionY = sectionY + (yOffset - (bedrockDimension.minY() >> 4));
|
||||||
|
int subChunkIndex = sectionY + yOffset;
|
||||||
if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) {
|
if (bedrockSectionY < 0 || maxBedrockSectionY < bedrockSectionY) {
|
||||||
// Ignore this chunk section since it goes outside the bounds accepted by the Bedrock client
|
// Ignore this chunk section since it goes outside the bounds accepted by the Bedrock client
|
||||||
if (useExtendedCollisions) {
|
if (useExtendedCollisions) {
|
||||||
@ -154,7 +156,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockStorage[] layers = new BlockStorage[]{ layer0 };
|
BlockStorage[] layers = new BlockStorage[]{ layer0 };
|
||||||
sections[bedrockSectionY] = new GeyserChunkSection(layers);
|
sections[bedrockSectionY] = new GeyserChunkSection(layers, subChunkIndex);
|
||||||
}
|
}
|
||||||
EXTENDED_COLLISIONS_STORAGE.get().clear();
|
EXTENDED_COLLISIONS_STORAGE.get().clear();
|
||||||
extendedCollisionNextSection = false;
|
extendedCollisionNextSection = false;
|
||||||
@ -167,7 +169,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
|
|
||||||
if (javaPalette instanceof GlobalPalette) {
|
if (javaPalette instanceof GlobalPalette) {
|
||||||
// As this is the global palette, simply iterate through the whole chunk section once
|
// As this is the global palette, simply iterate through the whole chunk section once
|
||||||
GeyserChunkSection section = new GeyserChunkSection(session.getBlockMappings().getBedrockAir().getRuntimeId());
|
GeyserChunkSection section = new GeyserChunkSection(session.getBlockMappings().getBedrockAir().getRuntimeId(), subChunkIndex);
|
||||||
for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
|
for (int yzx = 0; yzx < BlockStorage.SIZE; yzx++) {
|
||||||
int javaId = javaData.get(yzx);
|
int javaId = javaData.get(yzx);
|
||||||
int bedrockId = session.getBlockMappings().getBedrockBlockId(javaId);
|
int bedrockId = session.getBlockMappings().getBedrockBlockId(javaId);
|
||||||
@ -217,9 +219,9 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
|
|
||||||
if (BlockRegistries.WATERLOGGED.get().get(javaId)) {
|
if (BlockRegistries.WATERLOGGED.get().get(javaId)) {
|
||||||
BlockStorage waterlogged = new BlockStorage(SingletonBitArray.INSTANCE, IntLists.singleton(session.getBlockMappings().getBedrockWater().getRuntimeId()));
|
BlockStorage waterlogged = new BlockStorage(SingletonBitArray.INSTANCE, IntLists.singleton(session.getBlockMappings().getBedrockWater().getRuntimeId()));
|
||||||
sections[bedrockSectionY] = new GeyserChunkSection(new BlockStorage[] {blockStorage, waterlogged});
|
sections[bedrockSectionY] = new GeyserChunkSection(new BlockStorage[] {blockStorage, waterlogged}, subChunkIndex);
|
||||||
} else {
|
} else {
|
||||||
sections[bedrockSectionY] = new GeyserChunkSection(new BlockStorage[] {blockStorage});
|
sections[bedrockSectionY] = new GeyserChunkSection(new BlockStorage[] {blockStorage}, subChunkIndex);
|
||||||
}
|
}
|
||||||
if (useExtendedCollisions) {
|
if (useExtendedCollisions) {
|
||||||
EXTENDED_COLLISIONS_STORAGE.get().clear();
|
EXTENDED_COLLISIONS_STORAGE.get().clear();
|
||||||
@ -378,7 +380,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) };
|
layers = new BlockStorage[]{ layer0, new BlockStorage(BitArrayVersion.V1.createArray(BlockStorage.SIZE, layer1Data), layer1Palette) };
|
||||||
}
|
}
|
||||||
|
|
||||||
sections[bedrockSectionY] = new GeyserChunkSection(layers);
|
sections[bedrockSectionY] = new GeyserChunkSection(layers, subChunkIndex);
|
||||||
extendedCollisionNextSection = thisExtendedCollisionNextSection;
|
extendedCollisionNextSection = thisExtendedCollisionNextSection;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -419,20 +421,21 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type);
|
BlockEntityTranslator blockEntityTranslator = BlockEntityUtils.getBlockEntityTranslator(type);
|
||||||
bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState));
|
bedrockBlockEntities.add(blockEntityTranslator.getBlockEntityTag(session, type, x + chunkBlockX, y, z + chunkBlockZ, tag, blockState));
|
||||||
|
|
||||||
// Check for custom skulls
|
// Check for custom skulls
|
||||||
if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.contains("SkullOwner")) {
|
if (session.getPreferencesCache().showCustomSkulls() && type == BlockEntityType.SKULL && tag != null && tag.contains("SkullOwner")) {
|
||||||
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState);
|
BlockDefinition blockDefinition = SkullBlockEntityTranslator.translateSkull(session, tag, Vector3i.from(x + chunkBlockX, y, z + chunkBlockZ), blockState);
|
||||||
if (blockDefinition != null) {
|
if (blockDefinition != null) {
|
||||||
int bedrockSectionY = (y >> 4) - (bedrockDimension.minY() >> 4);
|
int bedrockSectionY = (y >> 4) - (bedrockDimension.minY() >> 4);
|
||||||
|
int subChunkIndex = (y >> 4) + (bedrockDimension.minY() >> 4);
|
||||||
if (0 <= bedrockSectionY && bedrockSectionY < maxBedrockSectionY) {
|
if (0 <= bedrockSectionY && bedrockSectionY < maxBedrockSectionY) {
|
||||||
// Custom skull is in a section accepted by Bedrock
|
// Custom skull is in a section accepted by Bedrock
|
||||||
GeyserChunkSection bedrockSection = sections[bedrockSectionY];
|
GeyserChunkSection bedrockSection = sections[bedrockSectionY];
|
||||||
IntList palette = bedrockSection.getBlockStorageArray()[0].getPalette();
|
IntList palette = bedrockSection.getBlockStorageArray()[0].getPalette();
|
||||||
if (palette instanceof IntImmutableList || palette instanceof IntLists.Singleton) {
|
if (palette instanceof IntImmutableList || palette instanceof IntLists.Singleton) {
|
||||||
// TODO there has to be a better way to expand the palette .-.
|
// TODO there has to be a better way to expand the palette .-.
|
||||||
bedrockSection = bedrockSection.copy();
|
bedrockSection = bedrockSection.copy(subChunkIndex);
|
||||||
sections[bedrockSectionY] = bedrockSection;
|
sections[bedrockSectionY] = bedrockSection;
|
||||||
}
|
}
|
||||||
bedrockSection.setFullBlock(x, y & 0xF, z, 0, blockDefinition.getRuntimeId());
|
bedrockSection.setFullBlock(x, y & 0xF, z, 0, blockDefinition.getRuntimeId());
|
||||||
@ -458,7 +461,7 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
if (section != null) {
|
if (section != null) {
|
||||||
size += section.estimateNetworkSize();
|
size += section.estimateNetworkSize();
|
||||||
} else {
|
} else {
|
||||||
size += SERIALIZED_CHUNK_DATA.length;
|
size += EMPTY_CHUNK_SECTION_SIZE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
size += ChunkUtils.EMPTY_BIOME_DATA.length * biomeCount;
|
size += ChunkUtils.EMPTY_BIOME_DATA.length * biomeCount;
|
||||||
@ -472,7 +475,8 @@ public class JavaLevelChunkWithLightTranslator extends PacketTranslator<Clientbo
|
|||||||
if (section != null) {
|
if (section != null) {
|
||||||
section.writeToNetwork(byteBuf);
|
section.writeToNetwork(byteBuf);
|
||||||
} else {
|
} else {
|
||||||
byteBuf.writeBytes(SERIALIZED_CHUNK_DATA);
|
int subChunkIndex = (i + (bedrockDimension.minY() >> 4));
|
||||||
|
new GeyserChunkSection(EMPTY_BLOCK_STORAGE, subChunkIndex).writeToNetwork(byteBuf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,19 +54,27 @@ import static org.geysermc.geyser.level.block.BlockStateValues.JAVA_AIR_ID;
|
|||||||
|
|
||||||
@UtilityClass
|
@UtilityClass
|
||||||
public class ChunkUtils {
|
public class ChunkUtils {
|
||||||
/**
|
|
||||||
* An empty subchunk.
|
|
||||||
*/
|
|
||||||
public static final byte[] SERIALIZED_CHUNK_DATA;
|
|
||||||
public static final byte[] EMPTY_BIOME_DATA;
|
public static final byte[] EMPTY_BIOME_DATA;
|
||||||
|
|
||||||
|
public static final BlockStorage[] EMPTY_BLOCK_STORAGE;
|
||||||
|
|
||||||
|
public static final int EMPTY_CHUNK_SECTION_SIZE;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
EMPTY_BLOCK_STORAGE = new BlockStorage[0];
|
||||||
|
|
||||||
ByteBuf byteBuf = Unpooled.buffer();
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
try {
|
try {
|
||||||
new GeyserChunkSection(new BlockStorage[0])
|
new GeyserChunkSection(EMPTY_BLOCK_STORAGE, 0)
|
||||||
.writeToNetwork(byteBuf);
|
.writeToNetwork(byteBuf);
|
||||||
SERIALIZED_CHUNK_DATA = new byte[byteBuf.readableBytes()];
|
|
||||||
byteBuf.readBytes(SERIALIZED_CHUNK_DATA);
|
byte[] emptyChunkData = new byte[byteBuf.readableBytes()];
|
||||||
|
byteBuf.readBytes(emptyChunkData);
|
||||||
|
|
||||||
|
EMPTY_CHUNK_SECTION_SIZE = emptyChunkData.length;
|
||||||
|
|
||||||
|
emptyChunkData = null;
|
||||||
} finally {
|
} finally {
|
||||||
byteBuf.release();
|
byteBuf.release();
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren