Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-09-08 20:43:04 +02:00
Move all block related code into BlockTranslator
It makes more sense.
Dieser Commit ist enthalten in:
Ursprung
2e46ecf28f
Commit
94851ef4b8
@ -57,6 +57,7 @@ import org.geysermc.connector.entity.PlayerEntity;
|
|||||||
import org.geysermc.connector.inventory.PlayerInventory;
|
import org.geysermc.connector.inventory.PlayerInventory;
|
||||||
import org.geysermc.connector.network.session.cache.*;
|
import org.geysermc.connector.network.session.cache.*;
|
||||||
import org.geysermc.connector.network.translators.Registry;
|
import org.geysermc.connector.network.translators.Registry;
|
||||||
|
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||||
import org.geysermc.connector.utils.ChunkUtils;
|
import org.geysermc.connector.utils.ChunkUtils;
|
||||||
import org.geysermc.connector.utils.Toolbox;
|
import org.geysermc.connector.utils.Toolbox;
|
||||||
|
|
||||||
@ -319,7 +320,7 @@ public class GeyserSession implements Player {
|
|||||||
// startGamePacket.setCurrentTick(0);
|
// startGamePacket.setCurrentTick(0);
|
||||||
startGamePacket.setEnchantmentSeed(0);
|
startGamePacket.setEnchantmentSeed(0);
|
||||||
startGamePacket.setMultiplayerCorrelationId("");
|
startGamePacket.setMultiplayerCorrelationId("");
|
||||||
startGamePacket.setBlockPalette(Toolbox.BLOCKS);
|
startGamePacket.setBlockPalette(BlockTranslator.BLOCKS);
|
||||||
startGamePacket.setItemEntries(Toolbox.ITEMS);
|
startGamePacket.setItemEntries(Toolbox.ITEMS);
|
||||||
startGamePacket.setVanillaVersion("*");
|
startGamePacket.setVanillaVersion("*");
|
||||||
// startGamePacket.setMovementServerAuthoritative(true);
|
// startGamePacket.setMovementServerAuthoritative(true);
|
||||||
|
@ -33,7 +33,7 @@ import com.nukkitx.protocol.bedrock.packet.LevelChunkPacket;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
import org.geysermc.connector.network.translators.block.BlockEntry;
|
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||||
import org.geysermc.connector.world.chunk.ChunkPosition;
|
import org.geysermc.connector.world.chunk.ChunkPosition;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -69,20 +69,19 @@ public class ChunkCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockEntry getBlockAt(Position position) {
|
public BlockState getBlockAt(Position position) {
|
||||||
ChunkPosition chunkPosition = new ChunkPosition(position.getX() >> 4, position.getZ() >> 4);
|
ChunkPosition chunkPosition = new ChunkPosition(position.getX() >> 4, position.getZ() >> 4);
|
||||||
if (!chunks.containsKey(chunkPosition))
|
if (!chunks.containsKey(chunkPosition))
|
||||||
return BlockEntry.AIR;
|
return BlockTranslator.AIR;
|
||||||
|
|
||||||
Column column = chunks.get(chunkPosition);
|
Column column = chunks.get(chunkPosition);
|
||||||
Chunk chunk = column.getChunks()[position.getY() >> 4];
|
Chunk chunk = column.getChunks()[position.getY() >> 4];
|
||||||
Position blockPosition = chunkPosition.getChunkBlock(position.getX(), position.getY(), position.getZ());
|
Position blockPosition = chunkPosition.getChunkBlock(position.getX(), position.getY(), position.getZ());
|
||||||
if (chunk != null) {
|
if (chunk != null) {
|
||||||
BlockState blockState = chunk.get(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
return chunk.get(blockPosition.getX(), blockPosition.getY(), blockPosition.getZ());
|
||||||
return TranslatorsInit.getBlockTranslator().getBlockEntry(blockState);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return BlockEntry.AIR;
|
return BlockTranslator.AIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeChunk(ChunkPosition position) {
|
public void removeChunk(ChunkPosition position) {
|
||||||
|
@ -27,7 +27,10 @@ package org.geysermc.connector.network.translators;
|
|||||||
|
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.*;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.*;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.*;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.*;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.*;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerActionAckPacket;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerHealthPacket;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerPositionRotationPacket;
|
||||||
|
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.player.ServerPlayerSetExperiencePacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.*;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.entity.spawn.*;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerDisplayScoreboardPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerDisplayScoreboardPacket;
|
||||||
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.server.scoreboard.ServerScoreboardObjectivePacket;
|
||||||
@ -70,9 +73,6 @@ public class TranslatorsInit {
|
|||||||
@Getter
|
@Getter
|
||||||
private static ItemTranslator itemTranslator;
|
private static ItemTranslator itemTranslator;
|
||||||
|
|
||||||
@Getter
|
|
||||||
private static BlockTranslator blockTranslator;
|
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private static InventoryTranslator inventoryTranslator = new GenericInventoryTranslator();
|
private static InventoryTranslator inventoryTranslator = new GenericInventoryTranslator();
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ public class TranslatorsInit {
|
|||||||
Registry.registerBedrock(RespawnPacket.class, new BedrockRespawnTranslator());
|
Registry.registerBedrock(RespawnPacket.class, new BedrockRespawnTranslator());
|
||||||
|
|
||||||
itemTranslator = new ItemTranslator();
|
itemTranslator = new ItemTranslator();
|
||||||
blockTranslator = new BlockTranslator();
|
BlockTranslator.init();
|
||||||
|
|
||||||
registerInventoryTranslators();
|
registerInventoryTranslators();
|
||||||
}
|
}
|
||||||
|
@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2019 GeyserMC. http://geysermc.org
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
* THE SOFTWARE.
|
|
||||||
*
|
|
||||||
* @author GeyserMC
|
|
||||||
* @link https://github.com/GeyserMC/Geyser
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.geysermc.connector.network.translators.block;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class BlockEntry {
|
|
||||||
|
|
||||||
public static BlockEntry AIR = new BlockEntry("minecraft:air", 0, 0);
|
|
||||||
|
|
||||||
private final String javaIdentifier;
|
|
||||||
private final int javaId;
|
|
||||||
private final int bedrockRuntimeId;
|
|
||||||
private final boolean waterlogged;
|
|
||||||
|
|
||||||
public BlockEntry(String javaIdentifier, int javaId, int bedrockRuntimeId) {
|
|
||||||
this.javaIdentifier = javaIdentifier;
|
|
||||||
this.javaId = javaId;
|
|
||||||
this.bedrockRuntimeId = bedrockRuntimeId;
|
|
||||||
this.waterlogged = (javaIdentifier.contains("waterlogged=true")
|
|
||||||
|| javaIdentifier.startsWith("minecraft:kelp")
|
|
||||||
|| javaIdentifier.contains("seagrass")
|
|
||||||
|| javaIdentifier.startsWith("minecraft:bubble_column"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
return obj == this || (obj instanceof BlockEntry && ((BlockEntry) obj).getBedrockRuntimeId() == this.getBedrockRuntimeId() && ((BlockEntry) obj).getJavaIdentifier().equals(this.getJavaIdentifier()));
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,20 +1,141 @@
|
|||||||
package org.geysermc.connector.network.translators.block;
|
package org.geysermc.connector.network.translators.block;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
|
import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
|
||||||
|
import com.nukkitx.nbt.CompoundTagBuilder;
|
||||||
|
import com.nukkitx.nbt.NbtUtils;
|
||||||
|
import com.nukkitx.nbt.stream.NBTInputStream;
|
||||||
|
import com.nukkitx.nbt.tag.CompoundTag;
|
||||||
|
import com.nukkitx.nbt.tag.ListTag;
|
||||||
|
import gnu.trove.map.TObjectIntMap;
|
||||||
|
import gnu.trove.map.hash.TObjectIntHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
|
import org.geysermc.connector.console.GeyserLogger;
|
||||||
import org.geysermc.connector.utils.Toolbox;
|
import org.geysermc.connector.utils.Toolbox;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.io.InputStream;
|
||||||
import java.util.Map;
|
import java.util.*;
|
||||||
|
|
||||||
public class BlockTranslator {
|
public class BlockTranslator {
|
||||||
private final Map<String, BlockEntry> javaIdentifierMap = new HashMap<>();
|
public static final ListTag<CompoundTag> BLOCKS;
|
||||||
|
public static final BlockState AIR = new BlockState(0);
|
||||||
|
|
||||||
public BlockEntry getBlockEntry(BlockState state) {
|
private static final Int2IntMap JAVA_TO_BEDROCK_BLOCK_MAP = new Int2IntOpenHashMap();
|
||||||
return Toolbox.BLOCK_ENTRIES.get(state.getId());
|
private static final Int2ObjectMap<BlockState> BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>();
|
||||||
|
private static final Int2IntMap JAVA_TO_BEDROCK_LIQUID_MAP = new Int2IntOpenHashMap();
|
||||||
|
private static final Int2ObjectMap<BlockState> BEDROCK_TO_JAVA_LIQUID_MAP = new Int2ObjectOpenHashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
/* Load block palette */
|
||||||
|
InputStream stream = Toolbox.getResource("bedrock/runtime_block_states.dat");
|
||||||
|
|
||||||
|
ListTag<CompoundTag> blocksTag;
|
||||||
|
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) {
|
||||||
|
blocksTag = (ListTag<CompoundTag>) nbtInputStream.readTag();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new AssertionError("Unable to get blocks from runtime block states", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<CompoundTag, CompoundTag> blockStateMap = new HashMap<>();
|
||||||
|
|
||||||
|
for (CompoundTag tag : blocksTag.getValue()) {
|
||||||
|
if (blockStateMap.putIfAbsent(tag.getAsCompound("block"), tag) != null) {
|
||||||
|
throw new AssertionError("Duplicate block states in Bedrock palette");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream = Toolbox.getResource("mappings/blocks.json");
|
||||||
|
JsonNode blocks;
|
||||||
|
try {
|
||||||
|
blocks = Toolbox.JSON_MAPPER.readTree(stream);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new AssertionError("Unable to load Java block mappings", e);
|
||||||
|
}
|
||||||
|
TObjectIntMap<CompoundTag> addedStatesMap = new TObjectIntHashMap<>(512, 0.5f, -1);
|
||||||
|
List<CompoundTag> paletteList = new ArrayList<>();
|
||||||
|
|
||||||
|
int javaRuntimeId = -1;
|
||||||
|
int bedrockRuntimeId = 0;
|
||||||
|
Iterator<Map.Entry<String, JsonNode>> blocksIterator = blocks.fields();
|
||||||
|
while (blocksIterator.hasNext()) {
|
||||||
|
javaRuntimeId++;
|
||||||
|
Map.Entry<String, JsonNode> entry = blocksIterator.next();
|
||||||
|
String javaId = entry.getKey();
|
||||||
|
CompoundTag blockTag = buildBedrockState(entry.getValue());
|
||||||
|
|
||||||
|
CompoundTag runtimeTag = blockStateMap.remove(blockTag);
|
||||||
|
if (runtimeTag != null) {
|
||||||
|
addedStatesMap.put(blockTag, bedrockRuntimeId);
|
||||||
|
paletteList.add(runtimeTag);
|
||||||
|
} else {
|
||||||
|
int duplicateRuntimeId = addedStatesMap.get(blockTag);
|
||||||
|
if (duplicateRuntimeId == -1) {
|
||||||
|
GeyserLogger.DEFAULT.debug("Mapping " + javaId + " was not found for bedrock edition!");
|
||||||
|
} else {
|
||||||
|
JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, duplicateRuntimeId);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, bedrockRuntimeId);
|
||||||
|
BEDROCK_TO_JAVA_BLOCK_MAP.put(bedrockRuntimeId, new BlockState(javaRuntimeId));
|
||||||
|
|
||||||
|
bedrockRuntimeId++;
|
||||||
|
}
|
||||||
|
|
||||||
|
paletteList.addAll(blockStateMap.values()); // Add any missing mappings that could crash the client
|
||||||
|
|
||||||
|
BLOCKS = new ListTag<>("", CompoundTag.class, paletteList);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockEntry getBlockEntry(String javaIdentifier) {
|
private BlockTranslator() {
|
||||||
return javaIdentifierMap.computeIfAbsent(javaIdentifier, key -> Toolbox.BLOCK_ENTRIES.values()
|
}
|
||||||
.stream().filter(blockEntry -> blockEntry.getJavaIdentifier().equals(key)).findFirst().orElse(null));
|
|
||||||
|
public static void init() {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
private static CompoundTag buildBedrockState(JsonNode node) {
|
||||||
|
CompoundTagBuilder tagBuilder = CompoundTag.builder();
|
||||||
|
tagBuilder.stringTag("name", node.get("bedrock_identifier").textValue());
|
||||||
|
|
||||||
|
// check for states
|
||||||
|
if (node.has("bedrock_states")) {
|
||||||
|
Iterator<Map.Entry<String, JsonNode>> statesIterator = node.get("bedrock_states").fields();
|
||||||
|
|
||||||
|
while (statesIterator.hasNext()) {
|
||||||
|
Map.Entry<String, JsonNode> stateEntry = statesIterator.next();
|
||||||
|
JsonNode stateValue = stateEntry.getValue();
|
||||||
|
switch (stateValue.getNodeType()) {
|
||||||
|
case BOOLEAN:
|
||||||
|
tagBuilder.booleanTag(stateEntry.getKey(), stateValue.booleanValue());
|
||||||
|
continue;
|
||||||
|
case STRING:
|
||||||
|
tagBuilder.stringTag(stateEntry.getKey(), stateValue.textValue());
|
||||||
|
continue;
|
||||||
|
case NUMBER:
|
||||||
|
tagBuilder.intTag(stateEntry.getKey(), stateValue.intValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tagBuilder.build("block");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getBedrockBlockId(BlockState state) {
|
||||||
|
return JAVA_TO_BEDROCK_BLOCK_MAP.get(state.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockState getJavaBlockState(int bedrockId) {
|
||||||
|
return BEDROCK_TO_JAVA_BLOCK_MAP.get(bedrockId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getBedrockWaterLoggedId(BlockState state) {
|
||||||
|
return JAVA_TO_BEDROCK_LIQUID_MAP.getOrDefault(state.getId(), -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static BlockState getJavaLiquidState(int bedrockId) {
|
||||||
|
return BEDROCK_TO_JAVA_LIQUID_MAP.get(bedrockId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ import com.nukkitx.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
|
|||||||
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
import com.nukkitx.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
import org.geysermc.connector.network.session.GeyserSession;
|
import org.geysermc.connector.network.session.GeyserSession;
|
||||||
import org.geysermc.connector.network.translators.TranslatorsInit;
|
import org.geysermc.connector.network.translators.TranslatorsInit;
|
||||||
import org.geysermc.connector.network.translators.block.BlockEntry;
|
import org.geysermc.connector.network.translators.block.BlockTranslator;
|
||||||
import org.geysermc.connector.world.chunk.ChunkSection;
|
import org.geysermc.connector.world.chunk.ChunkSection;
|
||||||
|
|
||||||
public class ChunkUtils {
|
public class ChunkUtils {
|
||||||
@ -34,14 +34,13 @@ public class ChunkUtils {
|
|||||||
for (int y = 0; y < 16; y++) {
|
for (int y = 0; y < 16; y++) {
|
||||||
for (int z = 0; z < 16; z++) {
|
for (int z = 0; z < 16; z++) {
|
||||||
BlockState blockState = chunk.get(x, y, z);
|
BlockState blockState = chunk.get(x, y, z);
|
||||||
BlockEntry block = TranslatorsInit.getBlockTranslator().getBlockEntry(blockState);
|
int id = BlockTranslator.getBedrockBlockId(blockState);
|
||||||
|
|
||||||
section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z),
|
section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id);
|
||||||
block.getBedrockRuntimeId());
|
|
||||||
|
|
||||||
if (block.isWaterlogged()) {
|
int waterloggedId = BlockTranslator.getBedrockWaterLoggedId(blockState);
|
||||||
BlockEntry water = TranslatorsInit.getBlockTranslator().getBlockEntry("minecraft:water[level=0]");
|
if (waterloggedId != -1) {
|
||||||
section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z), water.getBedrockRuntimeId());
|
section.getBlockStorageArray()[1].setFullBlock(ChunkSection.blockPosition(x, y, z), waterloggedId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,22 +50,22 @@ public class ChunkUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static void updateBlock(GeyserSession session, BlockState blockState, Position position) {
|
public static void updateBlock(GeyserSession session, BlockState blockState, Position position) {
|
||||||
BlockEntry blockEntry = TranslatorsInit.getBlockTranslator().getBlockEntry(blockState);
|
int blockId = BlockTranslator.getBedrockBlockId(blockState);
|
||||||
Vector3i pos = Vector3i.from(position.getX(), position.getY(), position.getZ());
|
Vector3i pos = Vector3i.from(position.getX(), position.getY(), position.getZ());
|
||||||
|
|
||||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||||
updateBlockPacket.setDataLayer(0);
|
updateBlockPacket.setDataLayer(0);
|
||||||
updateBlockPacket.setBlockPosition(pos);
|
updateBlockPacket.setBlockPosition(pos);
|
||||||
updateBlockPacket.setRuntimeId(blockEntry.getBedrockRuntimeId());
|
updateBlockPacket.setRuntimeId(blockId);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||||
session.getUpstream().sendPacket(updateBlockPacket);
|
session.getUpstream().sendPacket(updateBlockPacket);
|
||||||
|
|
||||||
UpdateBlockPacket waterPacket = new UpdateBlockPacket();
|
UpdateBlockPacket waterPacket = new UpdateBlockPacket();
|
||||||
waterPacket.setDataLayer(1);
|
waterPacket.setDataLayer(1);
|
||||||
waterPacket.setBlockPosition(pos);
|
waterPacket.setBlockPosition(pos);
|
||||||
if (blockEntry.isWaterlogged()) {
|
int waterloggedId = BlockTranslator.getBedrockWaterLoggedId(blockState);
|
||||||
BlockEntry water = TranslatorsInit.getBlockTranslator().getBlockEntry("minecraft:water[level=0]");
|
if (waterloggedId != -1) {
|
||||||
waterPacket.setRuntimeId(water.getBedrockRuntimeId());
|
waterPacket.setRuntimeId(waterloggedId);
|
||||||
} else {
|
} else {
|
||||||
waterPacket.setRuntimeId(0);
|
waterPacket.setRuntimeId(0);
|
||||||
}
|
}
|
||||||
|
@ -4,20 +4,9 @@ import com.fasterxml.jackson.core.type.TypeReference;
|
|||||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.nukkitx.nbt.CompoundTagBuilder;
|
|
||||||
import com.nukkitx.nbt.NbtUtils;
|
|
||||||
import com.nukkitx.nbt.stream.NBTInputStream;
|
|
||||||
import com.nukkitx.nbt.tag.CompoundTag;
|
|
||||||
import com.nukkitx.nbt.tag.ListTag;
|
|
||||||
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
import com.nukkitx.protocol.bedrock.packet.StartGamePacket;
|
||||||
import gnu.trove.map.TObjectIntMap;
|
|
||||||
import gnu.trove.map.hash.TObjectIntHashMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import org.geysermc.connector.console.GeyserLogger;
|
|
||||||
import org.geysermc.connector.network.translators.block.BlockEntry;
|
|
||||||
import org.geysermc.connector.network.translators.item.ItemEntry;
|
import org.geysermc.connector.network.translators.item.ItemEntry;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
@ -28,74 +17,12 @@ public class Toolbox {
|
|||||||
public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
|
public static final ObjectMapper JSON_MAPPER = new ObjectMapper().disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);
|
||||||
|
|
||||||
public static final Collection<StartGamePacket.ItemEntry> ITEMS = new ArrayList<>();
|
public static final Collection<StartGamePacket.ItemEntry> ITEMS = new ArrayList<>();
|
||||||
public static final ListTag<CompoundTag> BLOCKS;
|
|
||||||
|
|
||||||
public static final Int2ObjectMap<ItemEntry> ITEM_ENTRIES = new Int2ObjectOpenHashMap<>();
|
public static final Int2ObjectMap<ItemEntry> ITEM_ENTRIES = new Int2ObjectOpenHashMap<>();
|
||||||
public static final Int2ObjectMap<BlockEntry> BLOCK_ENTRIES = new Int2ObjectOpenHashMap<>();
|
|
||||||
public static final Int2IntMap JAVA_TO_BEDROCK_BLOCK_MAP = new Int2IntOpenHashMap();
|
|
||||||
public static final Int2IntMap JAVA_TO_BEDROCK_LIQUID_MAP = new Int2IntOpenHashMap();
|
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
||||||
/* Load block palette */
|
|
||||||
InputStream stream = getResource("bedrock/runtime_block_states.dat");
|
|
||||||
|
|
||||||
ListTag<CompoundTag> blocksTag;
|
|
||||||
try (NBTInputStream nbtInputStream = NbtUtils.createNetworkReader(stream)) {
|
|
||||||
blocksTag = (ListTag<CompoundTag>) nbtInputStream.readTag();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new AssertionError("Unable to get blocks from runtime block states", e);
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<CompoundTag, CompoundTag> blockStateMap = new HashMap<>();
|
|
||||||
|
|
||||||
for (CompoundTag tag : blocksTag.getValue()) {
|
|
||||||
if (blockStateMap.putIfAbsent(tag.getAsCompound("block"), tag) != null) {
|
|
||||||
throw new AssertionError("Duplicate block states in Bedrock palette");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stream = getResource("mappings/blocks.json");
|
|
||||||
JsonNode blocks;
|
|
||||||
try {
|
|
||||||
blocks = JSON_MAPPER.readTree(stream);
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new AssertionError("Unable to load Java block mappings", e);
|
|
||||||
}
|
|
||||||
TObjectIntMap<CompoundTag> addedStatesMap = new TObjectIntHashMap<>(512, 0.5f, -1);
|
|
||||||
List<CompoundTag> paletteList = new ArrayList<>();
|
|
||||||
|
|
||||||
int javaRuntimeId = -1;
|
|
||||||
int bedrockRuntimeId = 0;
|
|
||||||
Iterator<Map.Entry<String, JsonNode>> blocksIterator = blocks.fields();
|
|
||||||
while (blocksIterator.hasNext()) {
|
|
||||||
javaRuntimeId++;
|
|
||||||
Map.Entry<String, JsonNode> entry = blocksIterator.next();
|
|
||||||
String javaId = entry.getKey();
|
|
||||||
CompoundTag blockTag = buildBedrockState(entry.getValue());
|
|
||||||
|
|
||||||
CompoundTag runtimeTag = blockStateMap.remove(blockTag);
|
|
||||||
if (runtimeTag != null) {
|
|
||||||
addedStatesMap.put(blockTag, bedrockRuntimeId);
|
|
||||||
paletteList.add(runtimeTag);
|
|
||||||
} else {
|
|
||||||
int duplicateRuntimeId = addedStatesMap.get(blockTag);
|
|
||||||
if (duplicateRuntimeId == -1) {
|
|
||||||
GeyserLogger.DEFAULT.debug("Mapping " + javaId + " was not found for bedrock edition!");
|
|
||||||
} else {
|
|
||||||
JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, duplicateRuntimeId);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, bedrockRuntimeId);
|
|
||||||
|
|
||||||
bedrockRuntimeId++;
|
|
||||||
}
|
|
||||||
|
|
||||||
BLOCKS = new ListTag<>("", CompoundTag.class, paletteList);
|
|
||||||
|
|
||||||
/* Load item palette */
|
/* Load item palette */
|
||||||
stream = getResource("bedrock/items.json");
|
InputStream stream = getResource("bedrock/items.json");
|
||||||
|
|
||||||
TypeReference<List<JsonNode>> itemEntriesType = new TypeReference<List<JsonNode>>() {
|
TypeReference<List<JsonNode>> itemEntriesType = new TypeReference<List<JsonNode>>() {
|
||||||
};
|
};
|
||||||
@ -130,33 +57,7 @@ public class Toolbox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CompoundTag buildBedrockState(JsonNode node) {
|
public static InputStream getResource(String resource) {
|
||||||
CompoundTagBuilder tagBuilder = CompoundTag.builder();
|
|
||||||
tagBuilder.stringTag("name", node.get("bedrock_identifier").textValue());
|
|
||||||
|
|
||||||
// check for states
|
|
||||||
if (node.has("bedrock_states")) {
|
|
||||||
Iterator<Map.Entry<String, JsonNode>> statesIterator = node.get("bedrock_states").fields();
|
|
||||||
|
|
||||||
while (statesIterator.hasNext()) {
|
|
||||||
Map.Entry<String, JsonNode> stateEntry = statesIterator.next();
|
|
||||||
JsonNode stateValue = stateEntry.getValue();
|
|
||||||
switch (stateValue.getNodeType()) {
|
|
||||||
case BOOLEAN:
|
|
||||||
tagBuilder.booleanTag(stateEntry.getKey(), stateValue.booleanValue());
|
|
||||||
continue;
|
|
||||||
case STRING:
|
|
||||||
tagBuilder.stringTag(stateEntry.getKey(), stateValue.textValue());
|
|
||||||
continue;
|
|
||||||
case NUMBER:
|
|
||||||
tagBuilder.intTag(stateEntry.getKey(), stateValue.intValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return tagBuilder.build("block");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static InputStream getResource(String resource) {
|
|
||||||
InputStream stream = Toolbox.class.getClassLoader().getResourceAsStream(resource);
|
InputStream stream = Toolbox.class.getClassLoader().getResourceAsStream(resource);
|
||||||
if (stream == null) {
|
if (stream == null) {
|
||||||
throw new AssertionError("Unable to find resource: " + resource);
|
throw new AssertionError("Unable to find resource: " + resource);
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren