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.BlockRegistries;
import org.geysermc.connector.registry.Registries; import org.geysermc.connector.registry.Registries;
import org.geysermc.connector.registry.type.*; import org.geysermc.connector.registry.type.*;
import org.geysermc.connector.utils.BlockUtils;
import org.geysermc.connector.utils.FileUtils; import org.geysermc.connector.utils.FileUtils;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@ -268,11 +267,11 @@ public class ItemRegistryPopulator {
if (bedrockIdentifier == null) { if (bedrockIdentifier == null) {
throw new RuntimeException("Missing Bedrock ID in mappings!: " + bedrockId); throw new RuntimeException("Missing Bedrock ID in mappings!: " + bedrockId);
} }
int stackSize = mappingItem.getStackSize() == null ? 64 : mappingItem.getStackSize(); int stackSize = mappingItem.getStackSize();
int bedrockBlockId = -1; int bedrockBlockId = -1;
Integer blockRuntimeIdNode = entry.getValue().getBlockRuntimeId(); Integer firstBlockRuntimeId = entry.getValue().getFirstBlockRuntimeId();
if (blockRuntimeIdNode != null) { if (firstBlockRuntimeId != null) {
int blockIdOverride = bedrockBlockIdOverrides.getOrDefault(bedrockIdentifier, -1); int blockIdOverride = bedrockBlockIdOverrides.getOrDefault(bedrockIdentifier, -1);
if (blockIdOverride != -1) { if (blockIdOverride != -1) {
// Straight from BDS is our best chance of getting an item that doesn't run into issues // 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); int aValidBedrockBlockId = blacklistedIdentifiers.getOrDefault(bedrockIdentifier, -1);
if (aValidBedrockBlockId == -1) { if (aValidBedrockBlockId == -1) {
// Fallback // Fallback
bedrockBlockId = blockMappings.getBedrockBlockId(blockRuntimeIdNode); bedrockBlockId = blockMappings.getBedrockBlockId(firstBlockRuntimeId);
} else { } else {
// As of 1.16.220, every item requires a block runtime ID attached to it. // 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. // 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 // 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 // as indexed by Bedrock's block palette
// There are exceptions! But, ideally, the block ID override should take care of those. // 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(); NbtMapBuilder requiredBlockStatesBuilder = NbtMap.builder();
String correctBedrockIdentifier = blockMappings.getBedrockBlockStates().get(aValidBedrockBlockId).getString("name"); String correctBedrockIdentifier = blockMappings.getBedrockBlockStates().get(aValidBedrockBlockId).getString("name");
boolean firstPass = true; boolean firstPass = true;
for (Map.Entry<String, Integer> blockEntry : BlockRegistries.JAVA_IDENTIFIERS.get().entrySet()) { // Block states are all grouped together. In the mappings, we store the first block runtime ID in order,
String aBlockIdentifier = BlockUtils.getCleanIdentifier(blockEntry.getKey()); // and the last, if relevant. We then iterate over all those values and get their Bedrock equivalents
if (aBlockIdentifier.equals(javaBlockIdentifier)) { Integer lastBlockRuntimeId = entry.getValue().getLastBlockRuntimeId() == null ? firstBlockRuntimeId : entry.getValue().getLastBlockRuntimeId();
int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(blockEntry.getValue()); for (int i = firstBlockRuntimeId; i <= lastBlockRuntimeId; i++) {
NbtMap blockTag = blockMappings.getBedrockBlockStates().get(bedrockBlockRuntimeId); int bedrockBlockRuntimeId = blockMappings.getBedrockBlockId(i);
String bedrockName = blockTag.getString("name"); NbtMap blockTag = blockMappings.getBedrockBlockStates().get(bedrockBlockRuntimeId);
if (!bedrockName.equals(correctBedrockIdentifier)) { String bedrockName = blockTag.getString("name");
continue; if (!bedrockName.equals(correctBedrockIdentifier)) {
} continue;
NbtMap states = blockTag.getCompound("states"); }
NbtMap states = blockTag.getCompound("states");
if (firstPass) { if (firstPass) {
firstPass = false; firstPass = false;
if (states.size() == 0) { if (states.size() == 0) {
// No need to iterate and find all block states - this is the one, as there can't be any others // No need to iterate and find all block states - this is the one, as there can't be any others
bedrockBlockId = bedrockBlockRuntimeId; 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; 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 { public class GeyserMappingItem {
@JsonProperty("bedrock_identifier") String bedrockIdentifier; @JsonProperty("bedrock_identifier") String bedrockIdentifier;
@JsonProperty("bedrock_data") int bedrockData; @JsonProperty("bedrock_data") int bedrockData;
Integer blockRuntimeId; Integer firstBlockRuntimeId;
@JsonProperty("stack_size") Integer stackSize; Integer lastBlockRuntimeId;
@JsonProperty("stack_size") int stackSize = 64;
@JsonProperty("tool_type") String toolType; @JsonProperty("tool_type") String toolType;
@JsonProperty("tool_tier") String toolTier; @JsonProperty("tool_tier") String toolTier;
} }

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