mirror of
https://github.com/GeyserMC/Geyser.git
synced 2024-08-14 23:57:35 +00:00
Update to latest Protocol changes & cleanup item registry populator
This commit is contained in:
parent
86ebfbbc6e
commit
3f42d68f4e
16 changed files with 307 additions and 208 deletions
|
@ -39,7 +39,7 @@ public class FallingBlockEntity extends Entity {
|
|||
public FallingBlockEntity(GeyserSession session, int entityId, long geyserId, UUID uuid, Vector3f position, Vector3f motion, float yaw, float pitch, float headYaw, int javaId) {
|
||||
super(session, entityId, geyserId, uuid, EntityDefinitions.FALLING_BLOCK, position, motion, yaw, pitch, headYaw);
|
||||
|
||||
this.dirtyMetadata.put(EntityDataTypes.VARIANT, session.getBlockMappings().getBedrockBlockId(javaId));
|
||||
this.dirtyMetadata.put(EntityDataTypes.BLOCK, session.getBlockMappings().getBedrockBlock(javaId));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -35,6 +35,7 @@ import org.cloudburstmc.math.vector.Vector3f;
|
|||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
|
@ -59,7 +60,7 @@ public class ItemFrameEntity extends Entity {
|
|||
/**
|
||||
* Specific block 'state' we are emulating in Bedrock.
|
||||
*/
|
||||
private final int bedrockRuntimeId;
|
||||
private final BlockDefinition blockDefinition;
|
||||
/**
|
||||
* Rotation of item in frame.
|
||||
*/
|
||||
|
@ -90,7 +91,7 @@ public class ItemFrameEntity extends Entity {
|
|||
.putByte("item_frame_photo_bit", (byte) 0);
|
||||
blockBuilder.put("states", statesBuilder.build());
|
||||
|
||||
bedrockRuntimeId = session.getBlockMappings().getItemFrame(blockBuilder.build());
|
||||
blockDefinition = session.getBlockMappings().getItemFrame(blockBuilder.build());
|
||||
bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ());
|
||||
|
||||
session.getItemFrameCache().put(bedrockPosition, this);
|
||||
|
@ -152,7 +153,7 @@ public class ItemFrameEntity extends Entity {
|
|||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(bedrockPosition);
|
||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockAir().getRuntimeId()); //TODO maybe set this to the world block or another item frame?
|
||||
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockAir()); //TODO maybe set this to the world block or another item frame?
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||
|
@ -190,7 +191,7 @@ public class ItemFrameEntity extends Entity {
|
|||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(bedrockPosition);
|
||||
updateBlockPacket.setRuntimeId(bedrockRuntimeId);
|
||||
updateBlockPacket.setDefinition(blockDefinition);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||
|
|
|
@ -93,7 +93,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(position);
|
||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState));
|
||||
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(defaultJavaBlockState));
|
||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
inventory.setHolderPosition(position);
|
||||
|
@ -157,7 +157,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(holderPos);
|
||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock));
|
||||
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock));
|
||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,131 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2022 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.geyser.registry.populator;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtUtils;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.geysermc.geyser.GeyserBootstrap;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.type.BlockMappings;
|
||||
import org.geysermc.geyser.registry.type.ItemMappings;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiPredicate;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class CreativeItemRegistryPopulator {
|
||||
private static final List<BiPredicate<String, Integer>> JAVA_ONLY_ITEM_FILTER = List.of(
|
||||
// Just shows an empty texture; either way it doesn't exist in the creative menu on Java
|
||||
(identifier, data) -> identifier.equals("minecraft:debug_stick"),
|
||||
// Bedrock-only as its own item
|
||||
(identifier, data) -> identifier.equals("minecraft:empty_map") && data == 2,
|
||||
// Bedrock-only banner patterns
|
||||
(identifier, data) -> identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern")
|
||||
);
|
||||
|
||||
public static void populate(Map.Entry<String, ItemRegistryPopulator.PaletteVersion> version, Map<String, ItemDefinition> definitions, Consumer<ItemData.Builder> itemConsumer) {
|
||||
GeyserBootstrap bootstrap = GeyserImpl.getInstance().getBootstrap();
|
||||
|
||||
// Load creative items
|
||||
JsonNode creativeItemEntries;
|
||||
try (InputStream stream = bootstrap.getResource(String.format("bedrock/creative_items.%s.json", version.getKey()))) {
|
||||
creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("items");
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load creative items", e);
|
||||
}
|
||||
|
||||
BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(version.getValue().protocolVersion());
|
||||
for (JsonNode itemNode : creativeItemEntries) {
|
||||
ItemData.Builder itemBuilder = createItemData(itemNode, blockMappings, definitions);
|
||||
if (itemBuilder == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
itemConsumer.accept(itemBuilder);
|
||||
}
|
||||
}
|
||||
|
||||
private static ItemData.Builder createItemData(JsonNode itemNode, BlockMappings blockMappings, Map<String, ItemDefinition> definitions) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
String identifier = itemNode.get("id").textValue();
|
||||
for (BiPredicate<String, Integer> predicate : JAVA_ONLY_ITEM_FILTER) {
|
||||
if (predicate.test(identifier, damage)) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
ItemDefinition definition = definitions.get(identifier);
|
||||
if (definition == null) {
|
||||
GeyserImpl.getInstance().getLogger().debug("Unknown item definition with identifier " + identifier + " when loading creative items!");
|
||||
return null;
|
||||
}
|
||||
|
||||
return ItemData.builder()
|
||||
.definition(definition)
|
||||
.damage(damage)
|
||||
.count(count)
|
||||
.tag(tag)
|
||||
.blockDefinition(blockMappings.getBedrockBlock(blockRuntimeId));
|
||||
}
|
||||
}
|
|
@ -25,20 +25,24 @@
|
|||
|
||||
package org.geysermc.geyser.registry.populator;
|
||||
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
||||
import org.geysermc.geyser.api.item.custom.CustomRenderOffsets;
|
||||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
||||
import org.geysermc.geyser.api.util.TriState;
|
||||
import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl;
|
||||
import org.geysermc.geyser.item.GeyserCustomMappingData;
|
||||
import org.geysermc.geyser.item.components.ToolBreakSpeedsUtils;
|
||||
import org.geysermc.geyser.item.components.WearableSlot;
|
||||
import org.geysermc.geyser.item.mappings.MappingsConfigReader;
|
||||
import org.geysermc.geyser.registry.type.GeyserMappingItem;
|
||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
|
||||
|
@ -50,6 +54,51 @@ import java.util.Map;
|
|||
import java.util.OptionalInt;
|
||||
|
||||
public class CustomItemRegistryPopulator {
|
||||
public static void populate(Map<String, GeyserMappingItem> items, Multimap<String, CustomItemData> customItems, List<NonVanillaCustomItemData> nonVanillaCustomItems) {
|
||||
MappingsConfigReader mappingsConfigReader = new MappingsConfigReader();
|
||||
// Load custom items from mappings files
|
||||
mappingsConfigReader.loadMappingsFromJson((key, item) -> {
|
||||
if (CustomItemRegistryPopulator.initialCheck(key, item, items)) {
|
||||
customItems.get(key).add(item);
|
||||
}
|
||||
});
|
||||
|
||||
GeyserImpl.getInstance().eventBus().fire(new GeyserDefineCustomItemsEventImpl(customItems, nonVanillaCustomItems) {
|
||||
@Override
|
||||
public boolean register(@NonNull String identifier, @NonNull CustomItemData customItemData) {
|
||||
if (CustomItemRegistryPopulator.initialCheck(identifier, customItemData, items)) {
|
||||
customItems.get(identifier).add(customItemData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register(@NonNull NonVanillaCustomItemData customItemData) {
|
||||
if (customItemData.identifier().startsWith("minecraft:")) {
|
||||
GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() +
|
||||
" is attempting to masquerade as a vanilla Minecraft item!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (customItemData.javaId() < items.size()) {
|
||||
// Attempting to overwrite an item that already exists in the protocol
|
||||
GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() +
|
||||
" is attempting to overwrite a vanilla Minecraft item!");
|
||||
return false;
|
||||
}
|
||||
|
||||
nonVanillaCustomItems.add(customItemData);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
int customItemCount = customItems.size() + nonVanillaCustomItems.size();
|
||||
if (customItemCount > 0) {
|
||||
GeyserImpl.getInstance().getLogger().info("Registered " + customItemCount + " custom items");
|
||||
}
|
||||
}
|
||||
|
||||
public static GeyserCustomMappingData registerCustomItem(String customItemName, GeyserMappingItem javaItem, CustomItemData customItemData, int bedrockId) {
|
||||
ItemDefinition itemDefinition = new ItemDefinition(customItemName, bedrockId, true);
|
||||
|
||||
|
@ -86,7 +135,7 @@ public class CustomItemRegistryPopulator {
|
|||
.javaId(customItemData.javaId())
|
||||
.bedrockDefinition(new ItemDefinition(customIdentifier, customItemId, true))
|
||||
.bedrockData(0)
|
||||
.bedrockBlockId(0)
|
||||
.bedrockBlockDefinition(null)
|
||||
.stackSize(customItemData.stackSize())
|
||||
.toolType(customItemData.toolType())
|
||||
.toolTier(customItemData.toolTier())
|
||||
|
|
|
@ -26,13 +26,11 @@
|
|||
package org.geysermc.geyser.registry.populator;
|
||||
|
||||
import com.fasterxml.jackson.core.type.TypeReference;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import com.nukkitx.nbt.NbtUtils;
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
|
@ -45,7 +43,6 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
|
|||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v527.Bedrock_v527;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v534.Bedrock_v534;
|
||||
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
|
||||
|
@ -60,10 +57,8 @@ import org.geysermc.geyser.GeyserImpl;
|
|||
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
||||
import org.geysermc.geyser.event.type.GeyserDefineCustomItemsEventImpl;
|
||||
import org.geysermc.geyser.inventory.item.StoredItemMappings;
|
||||
import org.geysermc.geyser.item.GeyserCustomMappingData;
|
||||
import org.geysermc.geyser.item.mappings.MappingsConfigReader;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
import org.geysermc.geyser.registry.Registries;
|
||||
import org.geysermc.geyser.registry.type.BlockMappings;
|
||||
|
@ -75,24 +70,22 @@ import org.geysermc.geyser.registry.type.PaletteItem;
|
|||
import org.geysermc.geyser.util.ItemUtils;
|
||||
import org.geysermc.geyser.util.collection.FixedInt2IntMap;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Base64;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Populates the item registries.
|
||||
*/
|
||||
public class ItemRegistryPopulator {
|
||||
|
||||
private record PaletteVersion(int protocolVersion, Map<String, String> additionalTranslatedItems) {
|
||||
record PaletteVersion(int protocolVersion, Map<String, String> additionalTranslatedItems) {
|
||||
}
|
||||
|
||||
public static void populate() {
|
||||
|
@ -120,48 +113,10 @@ public class ItemRegistryPopulator {
|
|||
// (as of 1.19.2 Java) to replicate some edge cases in Java predicate behavior where it checks from the bottom
|
||||
// of the list first, then ascends.
|
||||
Multimap<String, CustomItemData> customItems = MultimapBuilder.hashKeys().arrayListValues().build();
|
||||
List<NonVanillaCustomItemData> nonVanillaCustomItems;
|
||||
List<NonVanillaCustomItemData> nonVanillaCustomItems = customItemsAllowed ? new ObjectArrayList<>() : Collections.emptyList();
|
||||
|
||||
MappingsConfigReader mappingsConfigReader = new MappingsConfigReader();
|
||||
if (customItemsAllowed) {
|
||||
// Load custom items from mappings files
|
||||
mappingsConfigReader.loadMappingsFromJson((key, item) -> {
|
||||
if (CustomItemRegistryPopulator.initialCheck(key, item, items)) {
|
||||
customItems.get(key).add(item);
|
||||
}
|
||||
});
|
||||
|
||||
nonVanillaCustomItems = new ObjectArrayList<>();
|
||||
GeyserImpl.getInstance().eventBus().fire(new GeyserDefineCustomItemsEventImpl(customItems, nonVanillaCustomItems) {
|
||||
@Override
|
||||
public boolean register(@NonNull String identifier, @NonNull CustomItemData customItemData) {
|
||||
if (CustomItemRegistryPopulator.initialCheck(identifier, customItemData, items)) {
|
||||
customItems.get(identifier).add(customItemData);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean register(@NonNull NonVanillaCustomItemData customItemData) {
|
||||
if (customItemData.identifier().startsWith("minecraft:")) {
|
||||
GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() +
|
||||
" is attempting to masquerade as a vanilla Minecraft item!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (customItemData.javaId() < items.size()) {
|
||||
// Attempting to overwrite an item that already exists in the protocol
|
||||
GeyserImpl.getInstance().getLogger().error("The custom item " + customItemData.identifier() +
|
||||
" is attempting to overwrite a vanilla Minecraft item!");
|
||||
return false;
|
||||
}
|
||||
nonVanillaCustomItems.add(customItemData);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
} else {
|
||||
nonVanillaCustomItems = Collections.emptyList();
|
||||
CustomItemRegistryPopulator.populate(items, customItems, nonVanillaCustomItems);
|
||||
}
|
||||
|
||||
int customItemCount = customItems.size() + nonVanillaCustomItems.size();
|
||||
|
@ -209,15 +164,6 @@ public class ItemRegistryPopulator {
|
|||
Object2IntMap<String> bedrockBlockIdOverrides = new Object2IntOpenHashMap<>();
|
||||
Object2IntMap<String> blacklistedIdentifiers = new Object2IntOpenHashMap<>();
|
||||
|
||||
// Load creative items
|
||||
// We load this before item mappings to get overridden block runtime ID mappings
|
||||
JsonNode creativeItemEntries;
|
||||
try (InputStream stream = bootstrap.getResource(String.format("bedrock/creative_items.%s.json", palette.getKey()))) {
|
||||
creativeItemEntries = GeyserImpl.JSON_MAPPER.readTree(stream).get("items");
|
||||
} catch (Exception e) {
|
||||
throw new AssertionError("Unable to load creative items", e);
|
||||
}
|
||||
|
||||
List<ItemDefinition> boats = new ObjectArrayList<>();
|
||||
List<ItemDefinition> buckets = new ObjectArrayList<>();
|
||||
List<ItemDefinition> spawnEggs = new ObjectArrayList<>();
|
||||
|
@ -225,74 +171,31 @@ public class ItemRegistryPopulator {
|
|||
|
||||
List<ItemMapping> mappings = new ObjectArrayList<>();
|
||||
// Temporary mapping to create stored items
|
||||
Map<String, ItemMapping> identifierToMapping = new Object2ObjectOpenHashMap<>();
|
||||
Map<String, ItemMapping> javaIdentifierToMapping = new Object2ObjectOpenHashMap<>();
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
String identifier = itemNode.get("id").textValue();
|
||||
if (identifier.equals("minecraft:debug_stick")) {
|
||||
// Just shows an empty texture; either way it doesn't exist in the creative menu on Java
|
||||
continue;
|
||||
} else if (identifier.equals("minecraft:empty_map") && damage == 2) {
|
||||
// Bedrock-only as its own item
|
||||
continue;
|
||||
} else if (identifier.equals("minecraft:bordure_indented_banner_pattern") || identifier.equals("minecraft:field_masoned_banner_pattern")) {
|
||||
// Bedrock-only banner patterns
|
||||
continue;
|
||||
}
|
||||
AtomicInteger creativeNetId = new AtomicInteger();
|
||||
CreativeItemRegistryPopulator.populate(palette, definitions, itemBuilder -> {
|
||||
ItemData item = itemBuilder.netId(creativeNetId.getAndIncrement()).build();
|
||||
creativeItems.add(item);
|
||||
|
||||
ItemDefinition definition = definitions.get(identifier);
|
||||
creativeItems.add(ItemData.builder()
|
||||
.definition(definition)
|
||||
.damage(damage)
|
||||
.count(count)
|
||||
.blockRuntimeId(blockRuntimeId)
|
||||
.tag(tag)
|
||||
.netId(netId++)
|
||||
.build());
|
||||
if (item.getBlockDefinition() != null) {
|
||||
String identifier = item.getDefinition().getIdentifier();
|
||||
|
||||
if (blockRuntimeId != 0) {
|
||||
// Add override for item mapping, unless it already exists... then we know multiple states can exist
|
||||
if (!blacklistedIdentifiers.containsKey(identifier)) {
|
||||
if (bedrockBlockIdOverrides.containsKey(identifier)) {
|
||||
bedrockBlockIdOverrides.removeInt(identifier);
|
||||
// Save this as a blacklist, but also as knowledge of what the block state name should be
|
||||
blacklistedIdentifiers.put(identifier, blockRuntimeId);
|
||||
blacklistedIdentifiers.put(identifier, item.getBlockDefinition().getRuntimeId());
|
||||
} else {
|
||||
// Unless there's multiple possibilities for this one state, let this be
|
||||
bedrockBlockIdOverrides.put(identifier, blockRuntimeId);
|
||||
bedrockBlockIdOverrides.put(identifier, item.getBlockDefinition().getRuntimeId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.getValue().protocolVersion());
|
||||
|
||||
|
@ -435,7 +338,7 @@ public class ItemRegistryPopulator {
|
|||
break;
|
||||
}
|
||||
|
||||
NbtMap states = blockMappings.getBedrockBlockPalette().get(itemData.getBlockRuntimeId()).getCompound("states");
|
||||
NbtMap states = blockMappings.getBedrockBlockPalette().get(itemData.getBlockDefinition().getRuntimeId()).getCompound("states");
|
||||
boolean valid = true;
|
||||
for (Map.Entry<String, Object> nbtEntry : requiredBlockStates.entrySet()) {
|
||||
if (!states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) {
|
||||
|
@ -445,7 +348,7 @@ public class ItemRegistryPopulator {
|
|||
}
|
||||
}
|
||||
if (valid) {
|
||||
creativeItems.set(j, itemData.toBuilder().blockRuntimeId(bedrockBlockId).build());
|
||||
creativeItems.set(j, itemData.toBuilder().blockDefinition(blockMappings.getBedrockBlock(bedrockBlockId)).build());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -460,7 +363,7 @@ public class ItemRegistryPopulator {
|
|||
.bedrockIdentifier(bedrockIdentifier.intern())
|
||||
.bedrockDefinition(definition)
|
||||
.bedrockData(mappingItem.getBedrockData())
|
||||
.bedrockBlockId(bedrockBlockId)
|
||||
.bedrockBlockDefinition(blockMappings.getBedrockBlock(bedrockBlockId))
|
||||
.stackSize(stackSize)
|
||||
.maxDamage(mappingItem.getMaxDamage())
|
||||
.hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect());
|
||||
|
@ -534,7 +437,7 @@ public class ItemRegistryPopulator {
|
|||
.definition(definition)
|
||||
.damage(mapping.getBedrockData())
|
||||
.count(1)
|
||||
.blockRuntimeId(mapping.getBedrockBlockId())
|
||||
.blockDefinition(mapping.getBedrockBlockDefinition())
|
||||
.build());
|
||||
} else if (javaIdentifier.startsWith("minecraft:music_disc_")) {
|
||||
// The Java record level event uses the item ID as the "key" to play the record
|
||||
|
@ -545,7 +448,7 @@ public class ItemRegistryPopulator {
|
|||
}
|
||||
|
||||
mappings.add(mapping);
|
||||
identifierToMapping.put(javaIdentifier, mapping);
|
||||
javaIdentifierToMapping.put(javaIdentifier, mapping);
|
||||
|
||||
itemNames.add(javaIdentifier);
|
||||
|
||||
|
@ -570,16 +473,14 @@ public class ItemRegistryPopulator {
|
|||
.javaId(-1)
|
||||
.bedrockDefinition(lodestoneCompass)
|
||||
.bedrockData(0)
|
||||
.bedrockBlockId(-1)
|
||||
.bedrockBlockDefinition(null)
|
||||
.stackSize(1)
|
||||
.customItemOptions(Collections.emptyList())
|
||||
.build();
|
||||
|
||||
if (customItemsAllowed) {
|
||||
// Add the furnace minecart as a custom item
|
||||
int furnaceMinecartId = nextFreeBedrockId++;
|
||||
|
||||
ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", (short) furnaceMinecartId, true);
|
||||
// Add furnace minecart
|
||||
ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", nextFreeBedrockId, true);
|
||||
definitions.put("geysermc:furnace_minecart", definition);
|
||||
registry.add(definition);
|
||||
|
||||
|
@ -589,49 +490,18 @@ public class ItemRegistryPopulator {
|
|||
.javaId(javaFurnaceMinecartId)
|
||||
.bedrockDefinition(definition)
|
||||
.bedrockData(0)
|
||||
.bedrockBlockId(-1)
|
||||
.bedrockBlockDefinition(null)
|
||||
.stackSize(1)
|
||||
.customItemOptions(Collections.emptyList()) // TODO check for custom items with furnace minecart
|
||||
.build());
|
||||
|
||||
creativeItems.add(ItemData.builder()
|
||||
.netId(netId++)
|
||||
.netId(creativeNetId.getAndIncrement())
|
||||
.definition(definition)
|
||||
.count(1).build());
|
||||
|
||||
NbtMapBuilder builder = NbtMap.builder();
|
||||
builder.putString("name", "geysermc:furnace_minecart")
|
||||
.putInt("id", furnaceMinecartId);
|
||||
|
||||
NbtMapBuilder itemProperties = NbtMap.builder();
|
||||
|
||||
NbtMapBuilder componentBuilder = NbtMap.builder();
|
||||
// Conveniently, as of 1.16.200, the furnace minecart has a texture AND translation string already.
|
||||
itemProperties.putCompound("minecraft:icon", NbtMap.builder()
|
||||
.putString("texture", "minecart_furnace")
|
||||
.putString("frame", "0.000000")
|
||||
.putInt("frame_version", 1)
|
||||
.putString("legacy_id", "").build());
|
||||
componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build());
|
||||
|
||||
// Indicate that the arm animation should play on rails
|
||||
List<NbtMap> useOnTag = Collections.singletonList(NbtMap.builder().putString("tags", "q.any_tag('rail')").build());
|
||||
componentBuilder.putCompound("minecraft:entity_placer", NbtMap.builder()
|
||||
.putList("dispense_on", NbtType.COMPOUND, useOnTag)
|
||||
.putString("entity", "minecraft:minecart")
|
||||
.putList("use_on", NbtType.COMPOUND, useOnTag)
|
||||
.count(1)
|
||||
.build());
|
||||
|
||||
// We always want to allow offhand usage when we can - matches Java Edition
|
||||
itemProperties.putBoolean("allow_off_hand", true);
|
||||
itemProperties.putBoolean("hand_equipped", false);
|
||||
itemProperties.putInt("max_stack_size", 1);
|
||||
itemProperties.putString("creative_group", "itemGroup.name.minecart");
|
||||
itemProperties.putInt("creative_category", 4); // 4 - "Items"
|
||||
|
||||
componentBuilder.putCompound("item_properties", itemProperties.build());
|
||||
builder.putCompound("components", componentBuilder.build());
|
||||
componentItemData.add(new ComponentItemData("geysermc:furnace_minecart", builder.build()));
|
||||
registerFurnaceMinecart(nextFreeBedrockId++, componentItemData);
|
||||
|
||||
// Register any completely custom items given to us
|
||||
IntSet registeredJavaIds = new IntOpenHashSet(); // Used to check for duplicate item java ids
|
||||
|
@ -657,8 +527,9 @@ public class ItemRegistryPopulator {
|
|||
if (customItem.creativeGroup() != null || customItem.creativeCategory().isPresent()) {
|
||||
creativeItems.add(ItemData.builder()
|
||||
.definition(registration.mapping().getBedrockDefinition())
|
||||
.netId(netId++)
|
||||
.count(1).build());
|
||||
.netId(creativeNetId.getAndIncrement())
|
||||
.count(1)
|
||||
.build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -669,7 +540,7 @@ public class ItemRegistryPopulator {
|
|||
.definitionRegistry(registry.build())
|
||||
.itemDefinitions(List.copyOf(definitions.values()))
|
||||
.itemNames(itemNames.toArray(new String[0]))
|
||||
.storedItems(new StoredItemMappings(identifierToMapping))
|
||||
.storedItems(new StoredItemMappings(javaIdentifierToMapping))
|
||||
.javaOnlyItems(javaOnlyItems)
|
||||
.buckets(buckets)
|
||||
.boats(boats)
|
||||
|
@ -687,4 +558,40 @@ public class ItemRegistryPopulator {
|
|||
|
||||
ItemUtils.setDyeColors(dyeColors);
|
||||
}
|
||||
|
||||
private static void registerFurnaceMinecart(int nextFreeBedrockId, List<ComponentItemData> componentItemData) {
|
||||
NbtMapBuilder builder = NbtMap.builder();
|
||||
builder.putString("name", "geysermc:furnace_minecart")
|
||||
.putInt("id", nextFreeBedrockId);
|
||||
|
||||
NbtMapBuilder itemProperties = NbtMap.builder();
|
||||
|
||||
NbtMapBuilder componentBuilder = NbtMap.builder();
|
||||
// Conveniently, as of 1.16.200, the furnace minecart has a texture AND translation string already.
|
||||
itemProperties.putCompound("minecraft:icon", NbtMap.builder()
|
||||
.putString("texture", "minecart_furnace")
|
||||
.putString("frame", "0.000000")
|
||||
.putInt("frame_version", 1)
|
||||
.putString("legacy_id", "").build());
|
||||
componentBuilder.putCompound("minecraft:display_name", NbtMap.builder().putString("value", "item.minecartFurnace.name").build());
|
||||
|
||||
// Indicate that the arm animation should play on rails
|
||||
List<NbtMap> useOnTag = Collections.singletonList(NbtMap.builder().putString("tags", "q.any_tag('rail')").build());
|
||||
componentBuilder.putCompound("minecraft:entity_placer", NbtMap.builder()
|
||||
.putList("dispense_on", NbtType.COMPOUND, useOnTag)
|
||||
.putString("entity", "minecraft:minecart")
|
||||
.putList("use_on", NbtType.COMPOUND, useOnTag)
|
||||
.build());
|
||||
|
||||
// We always want to allow offhand usage when we can - matches Java Edition
|
||||
itemProperties.putBoolean("allow_off_hand", true);
|
||||
itemProperties.putBoolean("hand_equipped", false);
|
||||
itemProperties.putInt("max_stack_size", 1);
|
||||
itemProperties.putString("creative_group", "itemGroup.name.minecart");
|
||||
itemProperties.putInt("creative_category", 4); // 4 - "Items"
|
||||
|
||||
componentBuilder.putCompound("item_properties", itemProperties.build());
|
||||
builder.putCompound("components", componentBuilder.build());
|
||||
componentItemData.add(new ComponentItemData("geysermc:furnace_minecart", builder.build()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -232,7 +232,7 @@ public class RecipeRegistryPopulator {
|
|||
.definition(mapping.getBedrockDefinition())
|
||||
.damage(damage)
|
||||
.count(count)
|
||||
.blockRuntimeId(mapping.isBlock() ? mapping.getBedrockBlockId() : 0)
|
||||
.blockDefinition(mapping.getBedrockBlockDefinition())
|
||||
.tag(tag)
|
||||
.build();
|
||||
}
|
||||
|
|
|
@ -73,18 +73,11 @@ public class BlockMappings {
|
|||
return this.javaToBedrockBlocks[state];
|
||||
}
|
||||
|
||||
public int getItemFrame(NbtMap tag) {
|
||||
BlockDefinition definition = this.itemFrames.get(tag);
|
||||
return definition == null ? -1 : definition.getRuntimeId();
|
||||
public BlockDefinition getItemFrame(NbtMap tag) {
|
||||
return this.itemFrames.get(tag);
|
||||
}
|
||||
|
||||
public boolean isItemFrame(int bedrockBlockRuntimeId) {
|
||||
for (Map.Entry<NbtMap, BlockDefinition> entry : this.itemFrames.entrySet()) {
|
||||
if (entry.getValue().getRuntimeId() == bedrockBlockRuntimeId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
public boolean isItemFrame(BlockDefinition definition) {
|
||||
return this.itemFrames.containsKey(definition.getState());
|
||||
}
|
||||
}
|
|
@ -26,11 +26,11 @@
|
|||
package org.geysermc.geyser.registry.type;
|
||||
|
||||
import it.unimi.dsi.fastutil.Pair;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
|
||||
import lombok.Builder;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Value;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
|
||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class ItemMapping {
|
|||
0,
|
||||
ItemDefinition.AIR,
|
||||
0,
|
||||
0, // Air is never sent in full over the network for this to serialize.
|
||||
null, // Air is never sent in full over the network for this to serialize.
|
||||
64,
|
||||
null,
|
||||
null,
|
||||
|
@ -69,7 +69,7 @@ public class ItemMapping {
|
|||
* 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.
|
||||
*/
|
||||
int bedrockBlockId;
|
||||
BlockDefinition bedrockBlockDefinition;
|
||||
int stackSize;
|
||||
|
||||
String toolType;
|
||||
|
@ -92,7 +92,7 @@ public class ItemMapping {
|
|||
* @return if this item is a block
|
||||
*/
|
||||
public boolean isBlock() {
|
||||
return this.bedrockBlockId != -1;
|
||||
return this.bedrockBlockDefinition != null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -127,13 +127,13 @@ public class ItemMappings {
|
|||
return lodestoneCompass;
|
||||
}
|
||||
|
||||
boolean isBlock = data.getBlockRuntimeId() != 0;
|
||||
boolean isBlock = data.getBlockDefinition() != null;
|
||||
boolean hasDamage = data.getDamage() != 0;
|
||||
|
||||
for (ItemMapping mapping : this.items) {
|
||||
if (mapping.getBedrockDefinition().equals(definition)) {
|
||||
if (isBlock && !hasDamage) { // Pre-1.16.220 will not use block runtime IDs at all, so we shouldn't check either
|
||||
if (data.getBlockRuntimeId() != mapping.getBedrockBlockId()) {
|
||||
if (data.getBlockDefinition() != mapping.getBedrockBlockDefinition()) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.inventory.chest;
|
|||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ContainerType;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket;
|
||||
|
@ -82,12 +83,12 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
|
||||
Vector3i position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP);
|
||||
Vector3i pairPosition = position.add(Vector3i.UNIT_X);
|
||||
int bedrockBlockId = session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState);
|
||||
BlockDefinition definition = session.getBlockMappings().getBedrockBlock(defaultJavaBlockState);
|
||||
|
||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(position);
|
||||
blockPacket.setRuntimeId(bedrockBlockId);
|
||||
blockPacket.setDefinition(definition);
|
||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
|
||||
|
@ -107,7 +108,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(pairPosition);
|
||||
blockPacket.setRuntimeId(bedrockBlockId);
|
||||
blockPacket.setDefinition(definition);
|
||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
|
||||
|
@ -154,7 +155,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(holderPos);
|
||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock));
|
||||
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock));
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
|
||||
holderPos = holderPos.add(Vector3i.UNIT_X);
|
||||
|
@ -162,7 +163,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||
blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setBlockPosition(holderPos);
|
||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock));
|
||||
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock));
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,18 +26,30 @@
|
|||
package org.geysermc.geyser.translator.inventory.item;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
||||
import com.github.steveice10.opennbt.tag.builtin.*;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ByteArrayTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ByteTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.DoubleTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.FloatTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntArrayTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ListTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.LongArrayTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.LongTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ShortTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import com.nukkitx.nbt.NbtList;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ItemData;
|
||||
import org.geysermc.geyser.GeyserImpl;
|
||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||
import org.geysermc.geyser.registry.BlockRegistries;
|
||||
|
@ -50,7 +62,11 @@ import org.geysermc.geyser.util.FileUtils;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public abstract class ItemTranslator {
|
||||
|
@ -169,7 +185,7 @@ public abstract class ItemTranslator {
|
|||
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(bedrockItem.getJavaId(), DEFAULT_TRANSLATOR);
|
||||
ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings());
|
||||
if (bedrockItem.isBlock()) {
|
||||
builder.blockRuntimeId(bedrockItem.getBedrockBlockId());
|
||||
builder.blockDefinition(bedrockItem.getBedrockBlockDefinition());
|
||||
}
|
||||
|
||||
if (nbt != null) {
|
||||
|
|
|
@ -80,7 +80,7 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity {
|
|||
BlockEntityUtils.updateBlockEntity(session, tag, position);
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(blockState));
|
||||
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState));
|
||||
updateBlockPacket.setBlockPosition(position);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
|
|
|
@ -598,7 +598,7 @@ public class PistonBlockEntity {
|
|||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
updateBlockPacket.setBlockPosition(newPos);
|
||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockMovingBlock().getRuntimeId());
|
||||
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockMovingBlock());
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
session.sendUpstreamPacket(updateBlockPacket);
|
||||
// Update moving block with correct details
|
||||
|
|
|
@ -195,7 +195,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
}
|
||||
|
||||
// Bedrock sends block interact code for a Java entity so we send entity code back to Java
|
||||
if (session.getBlockMappings().isItemFrame(packet.getBlockRuntimeId())) {
|
||||
if (session.getBlockMappings().isItemFrame(packet.getBlockDefinition())) {
|
||||
Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition());
|
||||
if (itemFrameEntity != null) {
|
||||
processEntityInteraction(session, packet, itemFrameEntity);
|
||||
|
@ -313,7 +313,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
if (packet.getActions().isEmpty()) {
|
||||
if (session.getOpPermissionLevel() >= 2 && session.getGameMode() == GameMode.CREATIVE) {
|
||||
// Otherwise insufficient permissions
|
||||
if (session.getBlockMappings().getJigsawStates().contains(packet.getBlockRuntimeId())) {
|
||||
if (session.getBlockMappings().getJigsawStates().contains(packet.getBlockDefinition())) {
|
||||
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
||||
openPacket.setBlockPosition(packet.getBlockPosition());
|
||||
openPacket.setId((byte) 1);
|
||||
|
@ -539,14 +539,14 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(blockPos);
|
||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(javaBlockState));
|
||||
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(javaBlockState));
|
||||
updateBlockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||
session.sendUpstreamPacket(updateBlockPacket);
|
||||
|
||||
UpdateBlockPacket updateWaterPacket = new UpdateBlockPacket();
|
||||
updateWaterPacket.setDataLayer(1);
|
||||
updateWaterPacket.setBlockPosition(blockPos);
|
||||
updateWaterPacket.setRuntimeId((BlockRegistries.WATERLOGGED.get().contains(javaBlockState) ? session.getBlockMappings().getBedrockWater() : session.getBlockMappings().getBedrockAir()).getRuntimeId());
|
||||
updateWaterPacket.setDefinition(BlockRegistries.WATERLOGGED.get().contains(javaBlockState) ? session.getBlockMappings().getBedrockWater() : session.getBlockMappings().getBedrockAir());
|
||||
updateWaterPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||
session.sendUpstreamPacket(updateWaterPacket);
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.util;
|
|||
|
||||
import org.cloudburstmc.math.vector.Vector2i;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
import org.cloudburstmc.protocol.bedrock.data.defintions.BlockDefinition;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.LevelChunkPacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
|
||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||
|
@ -133,12 +134,12 @@ public class ChunkUtils {
|
|||
// Prevent moving_piston from being placed
|
||||
// It's used for extending piston heads, but it isn't needed on Bedrock and causes pistons to flicker
|
||||
if (!BlockStateValues.isMovingPiston(blockState)) {
|
||||
int blockId = session.getBlockMappings().getBedrockBlockId(blockState);
|
||||
BlockDefinition definition = session.getBlockMappings().getBedrockBlock(blockState);
|
||||
|
||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||
updateBlockPacket.setDataLayer(0);
|
||||
updateBlockPacket.setBlockPosition(position);
|
||||
updateBlockPacket.setRuntimeId(blockId);
|
||||
updateBlockPacket.setDefinition(definition);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||
session.sendUpstreamPacket(updateBlockPacket);
|
||||
|
@ -147,9 +148,9 @@ public class ChunkUtils {
|
|||
waterPacket.setDataLayer(1);
|
||||
waterPacket.setBlockPosition(position);
|
||||
if (BlockRegistries.WATERLOGGED.get().contains(blockState)) {
|
||||
waterPacket.setRuntimeId(session.getBlockMappings().getBedrockWater().getRuntimeId());
|
||||
waterPacket.setDefinition(session.getBlockMappings().getBedrockWater());
|
||||
} else {
|
||||
waterPacket.setRuntimeId(session.getBlockMappings().getBedrockAir().getRuntimeId());
|
||||
waterPacket.setDefinition(session.getBlockMappings().getBedrockAir());
|
||||
}
|
||||
session.sendUpstreamPacket(waterPacket);
|
||||
}
|
||||
|
@ -197,7 +198,7 @@ public class ChunkUtils {
|
|||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||
blockPacket.setBlockPosition(pos);
|
||||
blockPacket.setDataLayer(0);
|
||||
blockPacket.setRuntimeId(1);
|
||||
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(1));
|
||||
session.sendUpstreamPacket(blockPacket);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue