Merge pull request #243 from DoctorMacc/inventory

Implement bed colors (Closes #222)
This commit is contained in:
Redned 2020-03-27 15:20:00 -05:00 committed by GitHub
commit 00b93c5527
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 1 deletions

View file

@ -48,6 +48,12 @@
<version>8.1.1</version> <version>8.1.1</version>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
<dependency>
<groupId>com.nukkitx.fastutil</groupId>
<artifactId>fastutil-object-byte-maps</artifactId>
<version>8.3.1</version>
<scope>compile</scope>
</dependency>
<dependency> <dependency>
<groupId>com.github.steveice10</groupId> <groupId>com.github.steveice10</groupId>
<artifactId>opennbt</artifactId> <artifactId>opennbt</artifactId>

View file

@ -35,6 +35,7 @@ import com.nukkitx.nbt.tag.ListTag;
import gnu.trove.map.TObjectIntMap; import gnu.trove.map.TObjectIntMap;
import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.map.hash.TObjectIntHashMap;
import it.unimi.dsi.fastutil.ints.*; import it.unimi.dsi.fastutil.ints.*;
import it.unimi.dsi.fastutil.objects.*;
import org.geysermc.connector.GeyserConnector; import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.utils.Toolbox; import org.geysermc.connector.utils.Toolbox;
@ -50,6 +51,7 @@ public class BlockTranslator {
private static final Int2ObjectMap<BlockState> BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>(); private static final Int2ObjectMap<BlockState> BEDROCK_TO_JAVA_BLOCK_MAP = new Int2ObjectOpenHashMap<>();
private static final Map<String, BlockState> JAVA_ID_BLOCK_MAP = new HashMap<>(); private static final Map<String, BlockState> JAVA_ID_BLOCK_MAP = new HashMap<>();
private static final IntSet WATERLOGGED = new IntOpenHashSet(); private static final IntSet WATERLOGGED = new IntOpenHashSet();
private static final Object2ByteOpenHashMap<BlockState> BED_COLORS = new Object2ByteOpenHashMap<>();
private static final Map<BlockState, String> JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>(); private static final Map<BlockState, String> JAVA_ID_TO_BLOCK_ENTITY_MAP = new HashMap<>();
@ -101,6 +103,14 @@ public class BlockTranslator {
JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, javaId); JAVA_ID_TO_BLOCK_ENTITY_MAP.put(javaBlockState, javaId);
} }
// If the Java ID is bed, signal that it needs a tag to show color
// The color is in the namespace ID in Java Edition but it's a tag in Bedrock.
JsonNode bedColor = entry.getValue().get("bed_color");
if (bedColor != null) {
// Converting to byte because the final tag value is a byte. bedColor.binaryValue() returns an array
BED_COLORS.put(javaBlockState, (byte) bedColor.intValue());
}
if ("minecraft:water[level=0]".equals(javaId)) { if ("minecraft:water[level=0]".equals(javaId)) {
waterRuntimeId = bedrockRuntimeId; waterRuntimeId = bedrockRuntimeId;
} }
@ -197,6 +207,13 @@ public class BlockTranslator {
return WATERLOGGED.contains(state.getId()); return WATERLOGGED.contains(state.getId());
} }
public static byte getBedColor(BlockState state) {
if (BED_COLORS.containsKey(state)) {
return BED_COLORS.getByte(state);
}
return -1;
}
public static BlockState getJavaWaterloggedState(int bedrockId) { public static BlockState getJavaWaterloggedState(int bedrockId) {
return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId); return BEDROCK_TO_JAVA_BLOCK_MAP.get(1 << 31 | bedrockId);
} }

View file

@ -0,0 +1,41 @@
package org.geysermc.connector.network.translators.block.entity;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockState;
import com.nukkitx.math.vector.Vector3i;
import com.nukkitx.nbt.CompoundTagBuilder;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.block.BlockTranslator;
import org.geysermc.connector.utils.BlockEntityUtils;
import java.util.concurrent.TimeUnit;
public class BedBlockEntityTranslator {
public static void checkForBedColor(GeyserSession session, BlockState blockState, Vector3i position) {
byte bedcolor = BlockTranslator.getBedColor(blockState);
// If Bed Color is not -1 then it is indeed a bed with a color.
if (bedcolor > -1) {
Position pos = new Position(position.getX(), position.getY(), position.getZ());
com.nukkitx.nbt.tag.CompoundTag finalbedTag = getBedTag(bedcolor, pos);
// Delay needed, otherwise newly placed beds will not get their color
// Delay is not needed for beds already placed on login
session.getConnector().getGeneralThreadPool().schedule(() ->
BlockEntityUtils.updateBlockEntity(session, finalbedTag, pos),
500,
TimeUnit.MILLISECONDS
);
}
}
public static com.nukkitx.nbt.tag.CompoundTag getBedTag(byte bedcolor, Position pos) {
CompoundTagBuilder tagBuilder = CompoundTagBuilder.builder()
.intTag("x", pos.getX())
.intTag("y", pos.getY())
.intTag("z", pos.getZ())
.stringTag("id", "Bed");
tagBuilder.byteTag("color", bedcolor);
return tagBuilder.buildRootTag();
}
}

View file

@ -105,7 +105,16 @@ public class JavaChunkDataTranslator extends PacketTranslator<ServerChunkDataPac
ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z)); ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z));
} }
for (Int2ObjectMap.Entry<CompoundTag> blockEntityEntry: chunkData.beds.int2ObjectEntrySet()) {
int x = blockEntityEntry.getValue().getInt("x");
int y = blockEntityEntry.getValue().getInt("y");
int z = blockEntityEntry.getValue().getInt("z");
ChunkUtils.updateBlock(session, new BlockState(blockEntityEntry.getIntKey()), new Position(x, y, z));
}
chunkData.signs.clear(); chunkData.signs.clear();
chunkData.beds.clear();
} else { } else {
final int xOffset = packet.getColumn().getX() << 4; final int xOffset = packet.getColumn().getX() << 4;
final int zOffset = packet.getColumn().getZ() << 4; final int zOffset = packet.getColumn().getZ() << 4;

View file

@ -44,6 +44,7 @@ import org.geysermc.connector.network.translators.block.entity.BlockEntityTransl
import org.geysermc.connector.world.chunk.ChunkPosition; import org.geysermc.connector.world.chunk.ChunkPosition;
import org.geysermc.connector.network.translators.block.BlockTranslator; import org.geysermc.connector.network.translators.block.BlockTranslator;
import org.geysermc.connector.world.chunk.ChunkSection; import org.geysermc.connector.world.chunk.ChunkSection;
import org.geysermc.connector.network.translators.block.entity.BedBlockEntityTranslator;
import static org.geysermc.connector.network.translators.block.BlockTranslator.BEDROCK_WATER_ID; import static org.geysermc.connector.network.translators.block.BlockTranslator.BEDROCK_WATER_ID;
@ -72,6 +73,9 @@ public class ChunkUtils {
if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("sign[")) { if (BlockTranslator.getBlockEntityString(blockState) != null && BlockTranslator.getBlockEntityString(blockState).contains("sign[")) {
Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z); Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z);
chunkData.signs.put(blockState.getId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ())); chunkData.signs.put(blockState.getId(), TranslatorsInit.getBlockEntityTranslators().get("Sign").getDefaultBedrockTag("Sign", pos.getX(), pos.getY(), pos.getZ()));
} else if (BlockTranslator.getBedColor(blockState) > -1) {
Position pos = new ChunkPosition(column.getX(), column.getZ()).getBlock(x, (chunkY << 4) + y, z);
chunkData.beds.put(blockState.getId(), BedBlockEntityTranslator.getBedTag(BlockTranslator.getBedColor(blockState), pos));
} else { } else {
section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id); section.getBlockStorageArray()[0].setFullBlock(ChunkSection.blockPosition(x, y, z), id);
} }
@ -128,6 +132,10 @@ public class ChunkUtils {
waterPacket.setRuntimeId(0); waterPacket.setRuntimeId(0);
} }
session.getUpstream().sendPacket(waterPacket); session.getUpstream().sendPacket(waterPacket);
// Since Java stores bed colors as part of the namespaced ID and Bedrock stores it as a tag
// This is the only place I could find that interacts with the Java block state and block updates
BedBlockEntityTranslator.checkForBedColor(session, blockState, position);
} }
public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) { public static void sendEmptyChunks(GeyserSession session, Vector3i position, int radius, boolean forceUpdate) {
@ -160,5 +168,6 @@ public class ChunkUtils {
public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0]; public com.nukkitx.nbt.tag.CompoundTag[] blockEntities = new com.nukkitx.nbt.tag.CompoundTag[0];
public Int2ObjectMap<com.nukkitx.nbt.tag.CompoundTag> signs = new Int2ObjectOpenHashMap<>(); public Int2ObjectMap<com.nukkitx.nbt.tag.CompoundTag> signs = new Int2ObjectOpenHashMap<>();
public Int2ObjectMap<com.nukkitx.nbt.tag.CompoundTag> beds = new Int2ObjectOpenHashMap<>();
} }
} }

@ -1 +1 @@
Subproject commit 278c73449aeeb4064c7513a68f98a49a5f463f0a Subproject commit efc9db6b7d51bdf145230933ac23b321ac1c132d