Specify the first and last relevant block runtime IDs for items

Improves startup time and processing
This commit is contained in:
Camotoy 2021-07-17 18:09:55 -04:00
parent ff280ef192
commit 697f35f657
No known key found for this signature in database
GPG key ID: 7EEFB66FE798081F
3 changed files with 40 additions and 41 deletions

View file

@ -49,7 +49,6 @@ import org.geysermc.connector.network.translators.item.StoredItemMappings;
import org.geysermc.connector.registry.BlockRegistries;
import org.geysermc.connector.registry.Registries;
import org.geysermc.connector.registry.type.*;
import org.geysermc.connector.utils.BlockUtils;
import org.geysermc.connector.utils.FileUtils;
import java.io.ByteArrayInputStream;
@ -268,11 +267,11 @@ public class ItemRegistryPopulator {
if (bedrockIdentifier == null) {
throw new RuntimeException("Missing Bedrock ID in mappings!: " + bedrockId);
}
int stackSize = mappingItem.getStackSize() == null ? 64 : mappingItem.getStackSize();
int stackSize = mappingItem.getStackSize();
int bedrockBlockId = -1;
Integer blockRuntimeIdNode = entry.getValue().getBlockRuntimeId();
if (blockRuntimeIdNode != null) {
Integer firstBlockRuntimeId = entry.getValue().getFirstBlockRuntimeId();
if (firstBlockRuntimeId != null) {
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
@ -282,52 +281,51 @@ public class ItemRegistryPopulator {
int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, -1);
if (aValidBedrockBlockId == -1) {
// Fallback
bedrockBlockId = blockMappings.getBedrockBlockId(blockRuntimeIdNode);
bedrockBlockId = blockMappings.getBedrockBlockId(firstBlockRuntimeId);
} else {
// As of 1.16.220, every item requires a block runtime ID attached to it.
// This is mostly for identifying different blocks with the same item ID - wool, slabs, some walls.
// However, in order for some visuals and crafting to work, we need to send the first matching block state
// as indexed by Bedrock's block palette
// There are exceptions! But, ideally, the block ID override should take care of those.
String javaBlockIdentifier = BlockRegistries.JAVA_BLOCKS.get(blockRuntimeIdNode).getCleanJavaIdentifier();
NbtMapBuilder requiredBlockStatesBuilder = NbtMap.builder();
String correctBedrockIdentifier = blockMappings.getBedrockBlockStates().get(aValidBedrockBlockId).getString("name");
boolean firstPass = true;
for (Map.Entry<String, Integer> blockEntry : BlockRegistries.JAVA_IDENTIFIERS.get().entrySet()) {
String aBlockIdentifier = BlockUtils.getCleanIdentifier(blockEntry.getKey());
if (aBlockIdentifier.equals(javaBlockIdentifier)) {
int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(blockEntry.getValue());
NbtMap blockTag = blockMappings.getBedrockBlockStates().get(bedrockBlockRuntimeId);
String bedrockName = blockTag.getString("name");
if (!bedrockName.equals(correctBedrockIdentifier)) {
continue;
}
NbtMap states = blockTag.getCompound("states");
// Block states are all grouped together. In the mappings, we store the first block runtime ID in order,
// and the last, if relevant. We then iterate over all those values and get their Bedrock equivalents
Integer lastBlockRuntimeId = entry.getValue().getLastBlockRuntimeId() == null ? firstBlockRuntimeId : entry.getValue().getLastBlockRuntimeId();
for (int i = firstBlockRuntimeId; i <= lastBlockRuntimeId; i++) {
int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(i);
NbtMap blockTag = blockMappings.getBedrockBlockStates().get(bedrockBlockRuntimeId);
String bedrockName = blockTag.getString("name");
if (!bedrockName.equals(correctBedrockIdentifier)) {
continue;
}
NbtMap states = blockTag.getCompound("states");
if (firstPass) {
firstPass = false;
if (states.size() == 0) {
// No need to iterate and find all block states - this is the one, as there can't be any others
bedrockBlockId = bedrockBlockRuntimeId;
break;
}
requiredBlockStatesBuilder.putAll(states);
continue;
}
for (Map.Entry<String, Object> nbtEntry : states.entrySet()) {
Object value = requiredBlockStatesBuilder.get(nbtEntry.getKey());
if (value != null && !nbtEntry.getValue().equals(value)) { // Null means this value has already been removed/deemed as unneeded
// This state can change between different block states, and therefore is not required
// to build a successful block state of this
requiredBlockStatesBuilder.remove(nbtEntry.getKey());
}
}
if (requiredBlockStatesBuilder.size() == 0) {
// There are no required block states
// E.G. there was only a direction property that is no longer in play
// (States that are important include color for glass)
if (firstPass) {
firstPass = false;
if (states.size() == 0) {
// No need to iterate and find all block states - this is the one, as there can't be any others
bedrockBlockId = bedrockBlockRuntimeId;
break;
}
requiredBlockStatesBuilder.putAll(states);
continue;
}
for (Map.Entry<String, Object> nbtEntry : states.entrySet()) {
Object value = requiredBlockStatesBuilder.get(nbtEntry.getKey());
if (value != null && !nbtEntry.getValue().equals(value)) { // Null means this value has already been removed/deemed as unneeded
// This state can change between different block states, and therefore is not required
// to build a successful block state of this
requiredBlockStatesBuilder.remove(nbtEntry.getKey());
}
}
if (requiredBlockStatesBuilder.size() == 0) {
// There are no required block states
// E.G. there was only a direction property that is no longer in play
// (States that are important include color for glass)
break;
}
}

View file

@ -35,8 +35,9 @@ import lombok.Data;
public class GeyserMappingItem {
@JsonProperty("bedrock_identifier") String bedrockIdentifier;
@JsonProperty("bedrock_data") int bedrockData;
Integer blockRuntimeId;
@JsonProperty("stack_size") Integer stackSize;
Integer firstBlockRuntimeId;
Integer lastBlockRuntimeId;
@JsonProperty("stack_size") int stackSize = 64;
@JsonProperty("tool_type") String toolType;
@JsonProperty("tool_tier") String toolTier;
}

@ -1 +1 @@
Subproject commit 7a67fa9ff78496f4fc30b8f72d0eff451f1771e2
Subproject commit c921aa9b12c2a1a471ef5f00aa040924426641dc