Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set 1.16.220 as the default Geyser version and fix crafting #2108

Merged
merged 3 commits into from
Apr 8, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public class BedrockProtocol {
* Default Bedrock codec that should act as a fallback. Should represent the latest available
* release of the game that Geyser supports.
*/
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v428.V428_CODEC;
public static final BedrockPacketCodec DEFAULT_BEDROCK_CODEC = Bedrock_v431.V431_CODEC;
/**
* A list of all supported Bedrock versions that can join Geyser
*/
Expand All @@ -55,8 +55,8 @@ public class BedrockProtocol {
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v422.V422_CODEC.toBuilder()
.minecraftVersion("1.16.200/1.16.201")
.build());
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v428.V428_CODEC);
SUPPORTED_BEDROCK_CODECS.add(DEFAULT_BEDROCK_CODEC);
SUPPORTED_BEDROCK_CODECS.add(Bedrock_v431.V431_CODEC);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public class ItemEntry {
private final int bedrockId;
private final int bedrockData;
/**
* The Bedrock block runtime ID to render this item with. The specific state *does* matter in how this item is rendered.
* The Bedrock block runtime ID to render this item with. The specific state *does* matter in how this item is rendered and used as a crafting ingredient.
* Required since 1.16.220.
*/
private final int bedrockBlockId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.translators.world.block.BlockTranslator1_16_210;
Expand Down Expand Up @@ -150,6 +152,85 @@ public static void init() {
}
}

Object2IntMap<String> bedrockBlockIdOverrides = new Object2IntOpenHashMap<>();
Set<String> blacklistedIdentifiers = new ObjectOpenHashSet<>();

// Load creative items
// We load this before item mappings to get overridden block runtime ID mappings
stream = FileUtils.getResource("bedrock/creative_items.json");

JsonNode creativeItemEntries;
try {
creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items");
} catch (Exception e) {
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.creative"), e);
}

int netId = 1;
List<ItemData> creativeItems = new ArrayList<>();
for (JsonNode itemNode : creativeItemEntries) {
int count = 1;
int damage = 0;
int blockRuntimeId = 0;
NbtMap tag = null;
JsonNode damageNode = itemNode.get("damage");
if (damageNode != null) {
damage = damageNode.asInt();
}
JsonNode countNode = itemNode.get("count");
if (countNode != null) {
count = countNode.asInt();
}
JsonNode blockRuntimeIdNode = itemNode.get("blockRuntimeId");
if (blockRuntimeIdNode != null) {
blockRuntimeId = blockRuntimeIdNode.asInt();
}
JsonNode nbtNode = itemNode.get("nbt_b64");
if (nbtNode != null) {
byte[] bytes = Base64.getDecoder().decode(nbtNode.asText());
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
try {
tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag();
} catch (IOException e) {
e.printStackTrace();
rtm516 marked this conversation as resolved.
Show resolved Hide resolved
}
}

String identifier = itemNode.get("id").textValue();
int id = -1;
for (StartGamePacket.ItemEntry itemEntry : ITEMS) {
if (itemEntry.getIdentifier().equals(identifier)) {
id = itemEntry.getId();
break;
}
}
if (id == -1) {
throw new RuntimeException("Unable to find matching Bedrock item for " + identifier);
}

creativeItems.add(ItemData.builder()
.id(id)
.damage(damage)
.count(count)
.blockRuntimeId(blockRuntimeId)
.tag(tag)
.netId(netId++).build());

if (blockRuntimeId != 0) {
// Add override for item mapping, unless it already exists... then we know multiple states can exist
if (!blacklistedIdentifiers.contains(identifier)) {
if (bedrockBlockIdOverrides.containsKey(identifier)) {
bedrockBlockIdOverrides.remove(identifier);
blacklistedIdentifiers.add(identifier);
} else {
// Unless there's multiple possibilities for this one state, let this be
bedrockBlockIdOverrides.put(identifier, blockRuntimeId);
}
}
}
}

// Load item mappings from Java Edition to Bedrock Edition
stream = FileUtils.getResource("mappings/items.json");

JsonNode items;
Expand Down Expand Up @@ -181,7 +262,13 @@ public static void init() {
int bedrockBlockId = -1;
JsonNode blockRuntimeIdNode = entry.getValue().get("blockRuntimeId");
if (blockRuntimeIdNode != null) {
bedrockBlockId = BlockTranslator1_16_210.INSTANCE.getBedrockBlockId(blockRuntimeIdNode.intValue());
int blockIdOverride = bedrockBlockIdOverrides.getOrDefault(bedrockIdentifier, -1);
if (blockIdOverride != -1) {
// Straight from BDS is our best chance of getting an item that doesn't run into issues
bedrockBlockId = blockIdOverride;
} else {
bedrockBlockId = BlockTranslator1_16_210.INSTANCE.getBedrockBlockId(blockRuntimeIdNode.intValue());
}
}

ItemEntry itemEntry;
Expand Down Expand Up @@ -262,38 +349,8 @@ public static void init() {
ITEM_ENTRIES.put(itemIndex, new ItemEntry("minecraft:lodestone_compass", "minecraft:lodestone_compass", itemIndex,
lodestoneCompassId, 0, -1, 1));

/* Load creative items */
stream = FileUtils.getResource("bedrock/creative_items.json");

JsonNode creativeItemEntries;
try {
creativeItemEntries = GeyserConnector.JSON_MAPPER.readTree(stream).get("items");
} catch (Exception e) {
throw new AssertionError(LanguageUtils.getLocaleStringLog("geyser.toolbox.fail.creative"), e);
}

Set<String> javaOnlyItems = new ObjectOpenHashSet<>();
Collections.addAll(javaOnlyItems, "minecraft:spectral_arrow", "minecraft:debug_stick",
"minecraft:knowledge_book", "minecraft:tipped_arrow");
if (!usingFurnaceMinecart) {
javaOnlyItems.add("minecraft:furnace_minecart");
}
JAVA_ONLY_ITEMS = ImmutableSet.copyOf(javaOnlyItems);

int netId = 1;
List<ItemData> creativeItems = new ArrayList<>();
for (JsonNode itemNode : creativeItemEntries) {
ItemData.Builder item = getBedrockItemFromJson(itemNode);
int bedrockRuntimeId = 0;
ItemEntry itemEntry = getItem(item.build()); // please
if (itemEntry.isBlock()) {
bedrockRuntimeId = itemEntry.getBedrockBlockId();
}
creativeItems.add(item.netId(netId++).blockRuntimeId(bedrockRuntimeId).build());
}

if (usingFurnaceMinecart) {
// Add the furnace minecart as an item
// Add the furnace minecart as a custom item
int furnaceMinecartId = ITEMS.size() + 1;

ITEMS.add(new StartGamePacket.ItemEntry("geysermc:furnace_minecart", (short) furnaceMinecartId, true));
Expand Down Expand Up @@ -339,6 +396,14 @@ public static void init() {
CREATIVE_ITEMS = creativeItems.toArray(new ItemData[0]);

ITEM_NAMES = itemNames.toArray(new String[0]);

Set<String> javaOnlyItems = new ObjectOpenHashSet<>();
Collections.addAll(javaOnlyItems, "minecraft:spectral_arrow", "minecraft:debug_stick",
"minecraft:knowledge_book", "minecraft:tipped_arrow");
if (!usingFurnaceMinecart) {
javaOnlyItems.add("minecraft:furnace_minecart");
}
JAVA_ONLY_ITEMS = ImmutableSet.copyOf(javaOnlyItems);
}

/**
Expand Down Expand Up @@ -393,35 +458,4 @@ public static ItemEntry getItemEntry(String javaIdentifier) {
return null;
});
}

/**
* Gets a Bedrock {@link com.nukkitx.protocol.bedrock.data.inventory.ItemData.Builder} from a {@link JsonNode}
* @param itemNode the JSON node that contains ProxyPass-compatible Bedrock item data
* @return
*/
public static ItemData.Builder getBedrockItemFromJson(JsonNode itemNode) {
int count = 1;
short damage = 0;
NbtMap tag = null;
if (itemNode.has("damage")) {
damage = itemNode.get("damage").numberValue().shortValue();
}
if (itemNode.has("count")) {
count = itemNode.get("count").asInt();
}
if (itemNode.has("nbt_b64")) {
byte[] bytes = Base64.getDecoder().decode(itemNode.get("nbt_b64").asText());
ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
try {
tag = (NbtMap) NbtUtils.createReaderLE(bais).readTag();
} catch (IOException e) {
e.printStackTrace();
}
}
return ItemData.builder()
.id(itemNode.get("id").asInt())
.damage(damage)
.count(count)
.tag(tag);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ private static ItemData getBedrockItemFromIdentifierJson(ItemEntry itemEntry, Js
.id(itemEntry.getBedrockId())
.damage(damage)
.count(count)
.blockRuntimeId(itemEntry.isBlock() ? itemEntry.getBedrockBlockId() : 0)
.tag(tag).build();
}

Expand Down
Loading