Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-12-27 08:30:12 +01:00
Update to latest Protocol changes & cleanup item registry populator
Dieser Commit ist enthalten in:
Ursprung
86ebfbbc6e
Commit
3f42d68f4e
@ -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) {
|
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);
|
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
|
@Override
|
||||||
|
@ -35,6 +35,7 @@ import org.cloudburstmc.math.vector.Vector3f;
|
|||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import com.nukkitx.nbt.NbtMap;
|
import com.nukkitx.nbt.NbtMap;
|
||||||
import com.nukkitx.nbt.NbtMapBuilder;
|
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.data.inventory.ItemData;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
@ -59,7 +60,7 @@ public class ItemFrameEntity extends Entity {
|
|||||||
/**
|
/**
|
||||||
* Specific block 'state' we are emulating in Bedrock.
|
* Specific block 'state' we are emulating in Bedrock.
|
||||||
*/
|
*/
|
||||||
private final int bedrockRuntimeId;
|
private final BlockDefinition blockDefinition;
|
||||||
/**
|
/**
|
||||||
* Rotation of item in frame.
|
* Rotation of item in frame.
|
||||||
*/
|
*/
|
||||||
@ -90,7 +91,7 @@ public class ItemFrameEntity extends Entity {
|
|||||||
.putByte("item_frame_photo_bit", (byte) 0);
|
.putByte("item_frame_photo_bit", (byte) 0);
|
||||||
blockBuilder.put("states", statesBuilder.build());
|
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());
|
bedrockPosition = Vector3i.from(position.getFloorX(), position.getFloorY(), position.getFloorZ());
|
||||||
|
|
||||||
session.getItemFrameCache().put(bedrockPosition, this);
|
session.getItemFrameCache().put(bedrockPosition, this);
|
||||||
@ -152,7 +153,7 @@ public class ItemFrameEntity extends Entity {
|
|||||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||||
updateBlockPacket.setDataLayer(0);
|
updateBlockPacket.setDataLayer(0);
|
||||||
updateBlockPacket.setBlockPosition(bedrockPosition);
|
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.PRIORITY);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||||
@ -190,7 +191,7 @@ public class ItemFrameEntity extends Entity {
|
|||||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||||
updateBlockPacket.setDataLayer(0);
|
updateBlockPacket.setDataLayer(0);
|
||||||
updateBlockPacket.setBlockPosition(bedrockPosition);
|
updateBlockPacket.setBlockPosition(bedrockPosition);
|
||||||
updateBlockPacket.setRuntimeId(bedrockRuntimeId);
|
updateBlockPacket.setDefinition(blockDefinition);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.PRIORITY);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||||
|
@ -93,7 +93,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(position);
|
blockPacket.setBlockPosition(position);
|
||||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState));
|
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(defaultJavaBlockState));
|
||||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.sendUpstreamPacket(blockPacket);
|
session.sendUpstreamPacket(blockPacket);
|
||||||
inventory.setHolderPosition(position);
|
inventory.setHolderPosition(position);
|
||||||
@ -157,7 +157,7 @@ public class BlockInventoryHolder extends InventoryHolder {
|
|||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(holderPos);
|
blockPacket.setBlockPosition(holderPos);
|
||||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock));
|
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock));
|
||||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.sendUpstreamPacket(blockPacket);
|
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;
|
package org.geysermc.geyser.registry.populator;
|
||||||
|
|
||||||
|
import com.google.common.collect.Multimap;
|
||||||
import com.nukkitx.nbt.NbtMap;
|
import com.nukkitx.nbt.NbtMap;
|
||||||
import com.nukkitx.nbt.NbtMapBuilder;
|
import com.nukkitx.nbt.NbtMapBuilder;
|
||||||
import com.nukkitx.nbt.NbtType;
|
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.defintions.ItemDefinition;
|
||||||
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
|
import org.cloudburstmc.protocol.bedrock.data.inventory.ComponentItemData;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.StartGamePacket;
|
|
||||||
import org.geysermc.geyser.GeyserImpl;
|
import org.geysermc.geyser.GeyserImpl;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
import org.geysermc.geyser.api.item.custom.CustomItemData;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomRenderOffsets;
|
import org.geysermc.geyser.api.item.custom.CustomRenderOffsets;
|
||||||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
||||||
import org.geysermc.geyser.api.util.TriState;
|
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.GeyserCustomMappingData;
|
||||||
import org.geysermc.geyser.item.components.ToolBreakSpeedsUtils;
|
import org.geysermc.geyser.item.components.ToolBreakSpeedsUtils;
|
||||||
import org.geysermc.geyser.item.components.WearableSlot;
|
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.GeyserMappingItem;
|
||||||
import org.geysermc.geyser.registry.type.ItemMapping;
|
import org.geysermc.geyser.registry.type.ItemMapping;
|
||||||
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
|
import org.geysermc.geyser.registry.type.NonVanillaItemRegistration;
|
||||||
@ -50,6 +54,51 @@ import java.util.Map;
|
|||||||
import java.util.OptionalInt;
|
import java.util.OptionalInt;
|
||||||
|
|
||||||
public class CustomItemRegistryPopulator {
|
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) {
|
public static GeyserCustomMappingData registerCustomItem(String customItemName, GeyserMappingItem javaItem, CustomItemData customItemData, int bedrockId) {
|
||||||
ItemDefinition itemDefinition = new ItemDefinition(customItemName, bedrockId, true);
|
ItemDefinition itemDefinition = new ItemDefinition(customItemName, bedrockId, true);
|
||||||
|
|
||||||
@ -86,7 +135,7 @@ public class CustomItemRegistryPopulator {
|
|||||||
.javaId(customItemData.javaId())
|
.javaId(customItemData.javaId())
|
||||||
.bedrockDefinition(new ItemDefinition(customIdentifier, customItemId, true))
|
.bedrockDefinition(new ItemDefinition(customIdentifier, customItemId, true))
|
||||||
.bedrockData(0)
|
.bedrockData(0)
|
||||||
.bedrockBlockId(0)
|
.bedrockBlockDefinition(null)
|
||||||
.stackSize(customItemData.stackSize())
|
.stackSize(customItemData.stackSize())
|
||||||
.toolType(customItemData.toolType())
|
.toolType(customItemData.toolType())
|
||||||
.toolTier(customItemData.toolTier())
|
.toolTier(customItemData.toolTier())
|
||||||
|
@ -26,13 +26,11 @@
|
|||||||
package org.geysermc.geyser.registry.populator;
|
package org.geysermc.geyser.registry.populator;
|
||||||
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.collect.MultimapBuilder;
|
import com.google.common.collect.MultimapBuilder;
|
||||||
import com.nukkitx.nbt.NbtMap;
|
import com.nukkitx.nbt.NbtMap;
|
||||||
import com.nukkitx.nbt.NbtMapBuilder;
|
import com.nukkitx.nbt.NbtMapBuilder;
|
||||||
import com.nukkitx.nbt.NbtType;
|
import com.nukkitx.nbt.NbtType;
|
||||||
import com.nukkitx.nbt.NbtUtils;
|
|
||||||
import it.unimi.dsi.fastutil.Pair;
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
import it.unimi.dsi.fastutil.ints.Int2IntMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
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.Object2ObjectOpenHashMap;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
|
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.v527.Bedrock_v527;
|
||||||
import org.cloudburstmc.protocol.bedrock.codec.v534.Bedrock_v534;
|
import org.cloudburstmc.protocol.bedrock.codec.v534.Bedrock_v534;
|
||||||
import org.cloudburstmc.protocol.bedrock.codec.v544.Bedrock_v544;
|
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.CustomItemData;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||||
import org.geysermc.geyser.api.item.custom.NonVanillaCustomItemData;
|
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.inventory.item.StoredItemMappings;
|
||||||
import org.geysermc.geyser.item.GeyserCustomMappingData;
|
import org.geysermc.geyser.item.GeyserCustomMappingData;
|
||||||
import org.geysermc.geyser.item.mappings.MappingsConfigReader;
|
|
||||||
import org.geysermc.geyser.registry.BlockRegistries;
|
import org.geysermc.geyser.registry.BlockRegistries;
|
||||||
import org.geysermc.geyser.registry.Registries;
|
import org.geysermc.geyser.registry.Registries;
|
||||||
import org.geysermc.geyser.registry.type.BlockMappings;
|
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.ItemUtils;
|
||||||
import org.geysermc.geyser.util.collection.FixedInt2IntMap;
|
import org.geysermc.geyser.util.collection.FixedInt2IntMap;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Populates the item registries.
|
* Populates the item registries.
|
||||||
*/
|
*/
|
||||||
public class ItemRegistryPopulator {
|
public class ItemRegistryPopulator {
|
||||||
|
|
||||||
private record PaletteVersion(int protocolVersion, Map<String, String> additionalTranslatedItems) {
|
record PaletteVersion(int protocolVersion, Map<String, String> additionalTranslatedItems) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void populate() {
|
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
|
// (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.
|
// of the list first, then ascends.
|
||||||
Multimap<String, CustomItemData> customItems = MultimapBuilder.hashKeys().arrayListValues().build();
|
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) {
|
if (customItemsAllowed) {
|
||||||
// Load custom items from mappings files
|
CustomItemRegistryPopulator.populate(items, customItems, nonVanillaCustomItems);
|
||||||
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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int customItemCount = customItems.size() + nonVanillaCustomItems.size();
|
int customItemCount = customItems.size() + nonVanillaCustomItems.size();
|
||||||
@ -209,15 +164,6 @@ public class ItemRegistryPopulator {
|
|||||||
Object2IntMap<String> bedrockBlockIdOverrides = new Object2IntOpenHashMap<>();
|
Object2IntMap<String> bedrockBlockIdOverrides = new Object2IntOpenHashMap<>();
|
||||||
Object2IntMap<String> blacklistedIdentifiers = 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> boats = new ObjectArrayList<>();
|
||||||
List<ItemDefinition> buckets = new ObjectArrayList<>();
|
List<ItemDefinition> buckets = new ObjectArrayList<>();
|
||||||
List<ItemDefinition> spawnEggs = new ObjectArrayList<>();
|
List<ItemDefinition> spawnEggs = new ObjectArrayList<>();
|
||||||
@ -225,74 +171,31 @@ public class ItemRegistryPopulator {
|
|||||||
|
|
||||||
List<ItemMapping> mappings = new ObjectArrayList<>();
|
List<ItemMapping> mappings = new ObjectArrayList<>();
|
||||||
// Temporary mapping to create stored items
|
// 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<>();
|
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();
|
AtomicInteger creativeNetId = new AtomicInteger();
|
||||||
if (identifier.equals("minecraft:debug_stick")) {
|
CreativeItemRegistryPopulator.populate(palette, definitions, itemBuilder -> {
|
||||||
// Just shows an empty texture; either way it doesn't exist in the creative menu on Java
|
ItemData item = itemBuilder.netId(creativeNetId.getAndIncrement()).build();
|
||||||
continue;
|
creativeItems.add(item);
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
ItemDefinition definition = definitions.get(identifier);
|
if (item.getBlockDefinition() != null) {
|
||||||
creativeItems.add(ItemData.builder()
|
String identifier = item.getDefinition().getIdentifier();
|
||||||
.definition(definition)
|
|
||||||
.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
|
// Add override for item mapping, unless it already exists... then we know multiple states can exist
|
||||||
if (!blacklistedIdentifiers.containsKey(identifier)) {
|
if (!blacklistedIdentifiers.containsKey(identifier)) {
|
||||||
if (bedrockBlockIdOverrides.containsKey(identifier)) {
|
if (bedrockBlockIdOverrides.containsKey(identifier)) {
|
||||||
bedrockBlockIdOverrides.removeInt(identifier);
|
bedrockBlockIdOverrides.removeInt(identifier);
|
||||||
// Save this as a blacklist, but also as knowledge of what the block state name should be
|
// 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 {
|
} else {
|
||||||
// Unless there's multiple possibilities for this one state, let this be
|
// 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());
|
BlockMappings blockMappings = BlockRegistries.BLOCKS.forVersion(palette.getValue().protocolVersion());
|
||||||
|
|
||||||
@ -435,7 +338,7 @@ public class ItemRegistryPopulator {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
NbtMap states = blockMappings.getBedrockBlockPalette().get(itemData.getBlockRuntimeId()).getCompound("states");
|
NbtMap states = blockMappings.getBedrockBlockPalette().get(itemData.getBlockDefinition().getRuntimeId()).getCompound("states");
|
||||||
boolean valid = true;
|
boolean valid = true;
|
||||||
for (Map.Entry<String, Object> nbtEntry : requiredBlockStates.entrySet()) {
|
for (Map.Entry<String, Object> nbtEntry : requiredBlockStates.entrySet()) {
|
||||||
if (!states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) {
|
if (!states.get(nbtEntry.getKey()).equals(nbtEntry.getValue())) {
|
||||||
@ -445,7 +348,7 @@ public class ItemRegistryPopulator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valid) {
|
if (valid) {
|
||||||
creativeItems.set(j, itemData.toBuilder().blockRuntimeId(bedrockBlockId).build());
|
creativeItems.set(j, itemData.toBuilder().blockDefinition(blockMappings.getBedrockBlock(bedrockBlockId)).build());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -460,7 +363,7 @@ public class ItemRegistryPopulator {
|
|||||||
.bedrockIdentifier(bedrockIdentifier.intern())
|
.bedrockIdentifier(bedrockIdentifier.intern())
|
||||||
.bedrockDefinition(definition)
|
.bedrockDefinition(definition)
|
||||||
.bedrockData(mappingItem.getBedrockData())
|
.bedrockData(mappingItem.getBedrockData())
|
||||||
.bedrockBlockId(bedrockBlockId)
|
.bedrockBlockDefinition(blockMappings.getBedrockBlock(bedrockBlockId))
|
||||||
.stackSize(stackSize)
|
.stackSize(stackSize)
|
||||||
.maxDamage(mappingItem.getMaxDamage())
|
.maxDamage(mappingItem.getMaxDamage())
|
||||||
.hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect());
|
.hasSuspiciousStewEffect(mappingItem.isHasSuspiciousStewEffect());
|
||||||
@ -534,7 +437,7 @@ public class ItemRegistryPopulator {
|
|||||||
.definition(definition)
|
.definition(definition)
|
||||||
.damage(mapping.getBedrockData())
|
.damage(mapping.getBedrockData())
|
||||||
.count(1)
|
.count(1)
|
||||||
.blockRuntimeId(mapping.getBedrockBlockId())
|
.blockDefinition(mapping.getBedrockBlockDefinition())
|
||||||
.build());
|
.build());
|
||||||
} else if (javaIdentifier.startsWith("minecraft:music_disc_")) {
|
} else if (javaIdentifier.startsWith("minecraft:music_disc_")) {
|
||||||
// The Java record level event uses the item ID as the "key" to play the record
|
// 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);
|
mappings.add(mapping);
|
||||||
identifierToMapping.put(javaIdentifier, mapping);
|
javaIdentifierToMapping.put(javaIdentifier, mapping);
|
||||||
|
|
||||||
itemNames.add(javaIdentifier);
|
itemNames.add(javaIdentifier);
|
||||||
|
|
||||||
@ -570,16 +473,14 @@ public class ItemRegistryPopulator {
|
|||||||
.javaId(-1)
|
.javaId(-1)
|
||||||
.bedrockDefinition(lodestoneCompass)
|
.bedrockDefinition(lodestoneCompass)
|
||||||
.bedrockData(0)
|
.bedrockData(0)
|
||||||
.bedrockBlockId(-1)
|
.bedrockBlockDefinition(null)
|
||||||
.stackSize(1)
|
.stackSize(1)
|
||||||
.customItemOptions(Collections.emptyList())
|
.customItemOptions(Collections.emptyList())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (customItemsAllowed) {
|
if (customItemsAllowed) {
|
||||||
// Add the furnace minecart as a custom item
|
// Add furnace minecart
|
||||||
int furnaceMinecartId = nextFreeBedrockId++;
|
ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", nextFreeBedrockId, true);
|
||||||
|
|
||||||
ItemDefinition definition = new ItemDefinition("geysermc:furnace_minecart", (short) furnaceMinecartId, true);
|
|
||||||
definitions.put("geysermc:furnace_minecart", definition);
|
definitions.put("geysermc:furnace_minecart", definition);
|
||||||
registry.add(definition);
|
registry.add(definition);
|
||||||
|
|
||||||
@ -589,49 +490,18 @@ public class ItemRegistryPopulator {
|
|||||||
.javaId(javaFurnaceMinecartId)
|
.javaId(javaFurnaceMinecartId)
|
||||||
.bedrockDefinition(definition)
|
.bedrockDefinition(definition)
|
||||||
.bedrockData(0)
|
.bedrockData(0)
|
||||||
.bedrockBlockId(-1)
|
.bedrockBlockDefinition(null)
|
||||||
.stackSize(1)
|
.stackSize(1)
|
||||||
.customItemOptions(Collections.emptyList()) // TODO check for custom items with furnace minecart
|
.customItemOptions(Collections.emptyList()) // TODO check for custom items with furnace minecart
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
creativeItems.add(ItemData.builder()
|
creativeItems.add(ItemData.builder()
|
||||||
.netId(netId++)
|
.netId(creativeNetId.getAndIncrement())
|
||||||
.definition(definition)
|
.definition(definition)
|
||||||
.count(1).build());
|
.count(1)
|
||||||
|
|
||||||
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)
|
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
// We always want to allow offhand usage when we can - matches Java Edition
|
registerFurnaceMinecart(nextFreeBedrockId++, componentItemData);
|
||||||
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()));
|
|
||||||
|
|
||||||
// Register any completely custom items given to us
|
// Register any completely custom items given to us
|
||||||
IntSet registeredJavaIds = new IntOpenHashSet(); // Used to check for duplicate item java ids
|
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()) {
|
if (customItem.creativeGroup() != null || customItem.creativeCategory().isPresent()) {
|
||||||
creativeItems.add(ItemData.builder()
|
creativeItems.add(ItemData.builder()
|
||||||
.definition(registration.mapping().getBedrockDefinition())
|
.definition(registration.mapping().getBedrockDefinition())
|
||||||
.netId(netId++)
|
.netId(creativeNetId.getAndIncrement())
|
||||||
.count(1).build());
|
.count(1)
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,7 +540,7 @@ public class ItemRegistryPopulator {
|
|||||||
.definitionRegistry(registry.build())
|
.definitionRegistry(registry.build())
|
||||||
.itemDefinitions(List.copyOf(definitions.values()))
|
.itemDefinitions(List.copyOf(definitions.values()))
|
||||||
.itemNames(itemNames.toArray(new String[0]))
|
.itemNames(itemNames.toArray(new String[0]))
|
||||||
.storedItems(new StoredItemMappings(identifierToMapping))
|
.storedItems(new StoredItemMappings(javaIdentifierToMapping))
|
||||||
.javaOnlyItems(javaOnlyItems)
|
.javaOnlyItems(javaOnlyItems)
|
||||||
.buckets(buckets)
|
.buckets(buckets)
|
||||||
.boats(boats)
|
.boats(boats)
|
||||||
@ -687,4 +558,40 @@ public class ItemRegistryPopulator {
|
|||||||
|
|
||||||
ItemUtils.setDyeColors(dyeColors);
|
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())
|
.definition(mapping.getBedrockDefinition())
|
||||||
.damage(damage)
|
.damage(damage)
|
||||||
.count(count)
|
.count(count)
|
||||||
.blockRuntimeId(mapping.isBlock() ? mapping.getBedrockBlockId() : 0)
|
.blockDefinition(mapping.getBedrockBlockDefinition())
|
||||||
.tag(tag)
|
.tag(tag)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
@ -73,18 +73,11 @@ public class BlockMappings {
|
|||||||
return this.javaToBedrockBlocks[state];
|
return this.javaToBedrockBlocks[state];
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getItemFrame(NbtMap tag) {
|
public BlockDefinition getItemFrame(NbtMap tag) {
|
||||||
BlockDefinition definition = this.itemFrames.get(tag);
|
return this.itemFrames.get(tag);
|
||||||
return definition == null ? -1 : definition.getRuntimeId();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isItemFrame(int bedrockBlockRuntimeId) {
|
public boolean isItemFrame(BlockDefinition definition) {
|
||||||
for (Map.Entry<NbtMap, BlockDefinition> entry : this.itemFrames.entrySet()) {
|
return this.itemFrames.containsKey(definition.getState());
|
||||||
if (entry.getValue().getRuntimeId() == bedrockBlockRuntimeId) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -26,11 +26,11 @@
|
|||||||
package org.geysermc.geyser.registry.type;
|
package org.geysermc.geyser.registry.type;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.Pair;
|
import it.unimi.dsi.fastutil.Pair;
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectIntPair;
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
import lombok.Value;
|
import lombok.Value;
|
||||||
import org.checkerframework.checker.nullness.qual.NonNull;
|
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.cloudburstmc.protocol.bedrock.data.defintions.ItemDefinition;
|
||||||
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
import org.geysermc.geyser.api.item.custom.CustomItemOptions;
|
||||||
|
|
||||||
@ -48,7 +48,7 @@ public class ItemMapping {
|
|||||||
0,
|
0,
|
||||||
ItemDefinition.AIR,
|
ItemDefinition.AIR,
|
||||||
0,
|
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,
|
64,
|
||||||
null,
|
null,
|
||||||
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.
|
* 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.
|
* Required since 1.16.220.
|
||||||
*/
|
*/
|
||||||
int bedrockBlockId;
|
BlockDefinition bedrockBlockDefinition;
|
||||||
int stackSize;
|
int stackSize;
|
||||||
|
|
||||||
String toolType;
|
String toolType;
|
||||||
@ -92,7 +92,7 @@ public class ItemMapping {
|
|||||||
* @return if this item is a block
|
* @return if this item is a block
|
||||||
*/
|
*/
|
||||||
public boolean isBlock() {
|
public boolean isBlock() {
|
||||||
return this.bedrockBlockId != -1;
|
return this.bedrockBlockDefinition != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -127,13 +127,13 @@ public class ItemMappings {
|
|||||||
return lodestoneCompass;
|
return lodestoneCompass;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean isBlock = data.getBlockRuntimeId() != 0;
|
boolean isBlock = data.getBlockDefinition() != null;
|
||||||
boolean hasDamage = data.getDamage() != 0;
|
boolean hasDamage = data.getDamage() != 0;
|
||||||
|
|
||||||
for (ItemMapping mapping : this.items) {
|
for (ItemMapping mapping : this.items) {
|
||||||
if (mapping.getBedrockDefinition().equals(definition)) {
|
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 (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;
|
continue;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -28,6 +28,7 @@ package org.geysermc.geyser.translator.inventory.chest;
|
|||||||
import org.cloudburstmc.math.vector.Vector3i;
|
import org.cloudburstmc.math.vector.Vector3i;
|
||||||
import com.nukkitx.nbt.NbtMap;
|
import com.nukkitx.nbt.NbtMap;
|
||||||
import com.nukkitx.nbt.NbtMapBuilder;
|
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.data.inventory.ContainerType;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.ContainerClosePacket;
|
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 position = session.getPlayerEntity().getPosition().toInt().add(Vector3i.UP);
|
||||||
Vector3i pairPosition = position.add(Vector3i.UNIT_X);
|
Vector3i pairPosition = position.add(Vector3i.UNIT_X);
|
||||||
int bedrockBlockId = session.getBlockMappings().getBedrockBlockId(defaultJavaBlockState);
|
BlockDefinition definition = session.getBlockMappings().getBedrockBlock(defaultJavaBlockState);
|
||||||
|
|
||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(position);
|
blockPacket.setBlockPosition(position);
|
||||||
blockPacket.setRuntimeId(bedrockBlockId);
|
blockPacket.setDefinition(definition);
|
||||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.sendUpstreamPacket(blockPacket);
|
session.sendUpstreamPacket(blockPacket);
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||||||
blockPacket = new UpdateBlockPacket();
|
blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(pairPosition);
|
blockPacket.setBlockPosition(pairPosition);
|
||||||
blockPacket.setRuntimeId(bedrockBlockId);
|
blockPacket.setDefinition(definition);
|
||||||
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
blockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.sendUpstreamPacket(blockPacket);
|
session.sendUpstreamPacket(blockPacket);
|
||||||
|
|
||||||
@ -154,7 +155,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(holderPos);
|
blockPacket.setBlockPosition(holderPos);
|
||||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock));
|
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock));
|
||||||
session.sendUpstreamPacket(blockPacket);
|
session.sendUpstreamPacket(blockPacket);
|
||||||
|
|
||||||
holderPos = holderPos.add(Vector3i.UNIT_X);
|
holderPos = holderPos.add(Vector3i.UNIT_X);
|
||||||
@ -162,7 +163,7 @@ public class DoubleChestInventoryTranslator extends ChestInventoryTranslator {
|
|||||||
blockPacket = new UpdateBlockPacket();
|
blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setBlockPosition(holderPos);
|
blockPacket.setBlockPosition(holderPos);
|
||||||
blockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(realBlock));
|
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(realBlock));
|
||||||
session.sendUpstreamPacket(blockPacket);
|
session.sendUpstreamPacket(blockPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,18 +26,30 @@
|
|||||||
package org.geysermc.geyser.translator.inventory.item;
|
package org.geysermc.geyser.translator.inventory.item;
|
||||||
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
|
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.NbtList;
|
||||||
import com.nukkitx.nbt.NbtMap;
|
import com.nukkitx.nbt.NbtMap;
|
||||||
import com.nukkitx.nbt.NbtMapBuilder;
|
import com.nukkitx.nbt.NbtMapBuilder;
|
||||||
import com.nukkitx.nbt.NbtType;
|
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.Int2ObjectMap;
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.format.NamedTextColor;
|
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.GeyserImpl;
|
||||||
import org.geysermc.geyser.inventory.GeyserItemStack;
|
import org.geysermc.geyser.inventory.GeyserItemStack;
|
||||||
import org.geysermc.geyser.registry.BlockRegistries;
|
import org.geysermc.geyser.registry.BlockRegistries;
|
||||||
@ -50,7 +62,11 @@ import org.geysermc.geyser.util.FileUtils;
|
|||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
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;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public abstract class ItemTranslator {
|
public abstract class ItemTranslator {
|
||||||
@ -169,7 +185,7 @@ public abstract class ItemTranslator {
|
|||||||
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(bedrockItem.getJavaId(), DEFAULT_TRANSLATOR);
|
ItemTranslator itemStackTranslator = ITEM_STACK_TRANSLATORS.getOrDefault(bedrockItem.getJavaId(), DEFAULT_TRANSLATOR);
|
||||||
ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings());
|
ItemData.Builder builder = itemStackTranslator.translateToBedrock(itemStack, bedrockItem, session.getItemMappings());
|
||||||
if (bedrockItem.isBlock()) {
|
if (bedrockItem.isBlock()) {
|
||||||
builder.blockRuntimeId(bedrockItem.getBedrockBlockId());
|
builder.blockDefinition(bedrockItem.getBedrockBlockDefinition());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nbt != null) {
|
if (nbt != null) {
|
||||||
|
@ -80,7 +80,7 @@ public class FlowerPotBlockEntityTranslator implements BedrockOnlyBlockEntity {
|
|||||||
BlockEntityUtils.updateBlockEntity(session, tag, position);
|
BlockEntityUtils.updateBlockEntity(session, tag, position);
|
||||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||||
updateBlockPacket.setDataLayer(0);
|
updateBlockPacket.setDataLayer(0);
|
||||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(blockState));
|
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(blockState));
|
||||||
updateBlockPacket.setBlockPosition(position);
|
updateBlockPacket.setBlockPosition(position);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||||
|
@ -598,7 +598,7 @@ public class PistonBlockEntity {
|
|||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||||
updateBlockPacket.setBlockPosition(newPos);
|
updateBlockPacket.setBlockPosition(newPos);
|
||||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockMovingBlock().getRuntimeId());
|
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockMovingBlock());
|
||||||
updateBlockPacket.setDataLayer(0);
|
updateBlockPacket.setDataLayer(0);
|
||||||
session.sendUpstreamPacket(updateBlockPacket);
|
session.sendUpstreamPacket(updateBlockPacket);
|
||||||
// Update moving block with correct details
|
// 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
|
// 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());
|
Entity itemFrameEntity = ItemFrameEntity.getItemFrameEntity(session, packet.getBlockPosition());
|
||||||
if (itemFrameEntity != null) {
|
if (itemFrameEntity != null) {
|
||||||
processEntityInteraction(session, packet, itemFrameEntity);
|
processEntityInteraction(session, packet, itemFrameEntity);
|
||||||
@ -313,7 +313,7 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||||||
if (packet.getActions().isEmpty()) {
|
if (packet.getActions().isEmpty()) {
|
||||||
if (session.getOpPermissionLevel() >= 2 && session.getGameMode() == GameMode.CREATIVE) {
|
if (session.getOpPermissionLevel() >= 2 && session.getGameMode() == GameMode.CREATIVE) {
|
||||||
// Otherwise insufficient permissions
|
// Otherwise insufficient permissions
|
||||||
if (session.getBlockMappings().getJigsawStates().contains(packet.getBlockRuntimeId())) {
|
if (session.getBlockMappings().getJigsawStates().contains(packet.getBlockDefinition())) {
|
||||||
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
||||||
openPacket.setBlockPosition(packet.getBlockPosition());
|
openPacket.setBlockPosition(packet.getBlockPosition());
|
||||||
openPacket.setId((byte) 1);
|
openPacket.setId((byte) 1);
|
||||||
@ -539,14 +539,14 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||||
updateBlockPacket.setDataLayer(0);
|
updateBlockPacket.setDataLayer(0);
|
||||||
updateBlockPacket.setBlockPosition(blockPos);
|
updateBlockPacket.setBlockPosition(blockPos);
|
||||||
updateBlockPacket.setRuntimeId(session.getBlockMappings().getBedrockBlockId(javaBlockState));
|
updateBlockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(javaBlockState));
|
||||||
updateBlockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
updateBlockPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.sendUpstreamPacket(updateBlockPacket);
|
session.sendUpstreamPacket(updateBlockPacket);
|
||||||
|
|
||||||
UpdateBlockPacket updateWaterPacket = new UpdateBlockPacket();
|
UpdateBlockPacket updateWaterPacket = new UpdateBlockPacket();
|
||||||
updateWaterPacket.setDataLayer(1);
|
updateWaterPacket.setDataLayer(1);
|
||||||
updateWaterPacket.setBlockPosition(blockPos);
|
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);
|
updateWaterPacket.getFlags().addAll(UpdateBlockPacket.FLAG_ALL_PRIORITY);
|
||||||
session.sendUpstreamPacket(updateWaterPacket);
|
session.sendUpstreamPacket(updateWaterPacket);
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ package org.geysermc.geyser.util;
|
|||||||
|
|
||||||
import org.cloudburstmc.math.vector.Vector2i;
|
import org.cloudburstmc.math.vector.Vector2i;
|
||||||
import org.cloudburstmc.math.vector.Vector3i;
|
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.LevelChunkPacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
|
import org.cloudburstmc.protocol.bedrock.packet.NetworkChunkPublisherUpdatePacket;
|
||||||
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
import org.cloudburstmc.protocol.bedrock.packet.UpdateBlockPacket;
|
||||||
@ -133,12 +134,12 @@ public class ChunkUtils {
|
|||||||
// Prevent moving_piston from being placed
|
// 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
|
// It's used for extending piston heads, but it isn't needed on Bedrock and causes pistons to flicker
|
||||||
if (!BlockStateValues.isMovingPiston(blockState)) {
|
if (!BlockStateValues.isMovingPiston(blockState)) {
|
||||||
int blockId = session.getBlockMappings().getBedrockBlockId(blockState);
|
BlockDefinition definition = session.getBlockMappings().getBedrockBlock(blockState);
|
||||||
|
|
||||||
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket updateBlockPacket = new UpdateBlockPacket();
|
||||||
updateBlockPacket.setDataLayer(0);
|
updateBlockPacket.setDataLayer(0);
|
||||||
updateBlockPacket.setBlockPosition(position);
|
updateBlockPacket.setBlockPosition(position);
|
||||||
updateBlockPacket.setRuntimeId(blockId);
|
updateBlockPacket.setDefinition(definition);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NEIGHBORS);
|
||||||
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
updateBlockPacket.getFlags().add(UpdateBlockPacket.Flag.NETWORK);
|
||||||
session.sendUpstreamPacket(updateBlockPacket);
|
session.sendUpstreamPacket(updateBlockPacket);
|
||||||
@ -147,9 +148,9 @@ public class ChunkUtils {
|
|||||||
waterPacket.setDataLayer(1);
|
waterPacket.setDataLayer(1);
|
||||||
waterPacket.setBlockPosition(position);
|
waterPacket.setBlockPosition(position);
|
||||||
if (BlockRegistries.WATERLOGGED.get().contains(blockState)) {
|
if (BlockRegistries.WATERLOGGED.get().contains(blockState)) {
|
||||||
waterPacket.setRuntimeId(session.getBlockMappings().getBedrockWater().getRuntimeId());
|
waterPacket.setDefinition(session.getBlockMappings().getBedrockWater());
|
||||||
} else {
|
} else {
|
||||||
waterPacket.setRuntimeId(session.getBlockMappings().getBedrockAir().getRuntimeId());
|
waterPacket.setDefinition(session.getBlockMappings().getBedrockAir());
|
||||||
}
|
}
|
||||||
session.sendUpstreamPacket(waterPacket);
|
session.sendUpstreamPacket(waterPacket);
|
||||||
}
|
}
|
||||||
@ -197,7 +198,7 @@ public class ChunkUtils {
|
|||||||
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
UpdateBlockPacket blockPacket = new UpdateBlockPacket();
|
||||||
blockPacket.setBlockPosition(pos);
|
blockPacket.setBlockPosition(pos);
|
||||||
blockPacket.setDataLayer(0);
|
blockPacket.setDataLayer(0);
|
||||||
blockPacket.setRuntimeId(1);
|
blockPacket.setDefinition(session.getBlockMappings().getBedrockBlock(1));
|
||||||
session.sendUpstreamPacket(blockPacket);
|
session.sendUpstreamPacket(blockPacket);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren