forked from GeyserMC/Geyser
Implement command block and jigsaw support (#1291)
* Implement command block and jigsaw support - Command block UI is now fully implemented to match Java Edition. - Command block minecarts are now supported. - Command blocks now show the correct type of command block. - Jigsaw blocks are translated. Structure blocks can be implemented, but these will be trickier as there are significant GUI differences between Java and Bedrock. * Add more detail about command block minecart color * Set PlayerPermission.OPERATOR to allow command blocks to be destroyed
This commit is contained in:
parent
f5a9254fae
commit
6638c53029
23 changed files with 359 additions and 155 deletions
|
@ -39,7 +39,6 @@ Take a look [here](https://github.com/GeyserMC/Geyser/wiki#Setup) for how to set
|
|||
- [ ] Beacon
|
||||
- [ ] Cartography Table
|
||||
- [ ] Stonecutter
|
||||
- [ ] Command Block
|
||||
- [ ] Structure Block
|
||||
- [ ] Horse Inventory
|
||||
- [ ] Loom
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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.connector.entity;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
|
||||
import com.github.steveice10.mc.protocol.data.message.Message;
|
||||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.protocol.bedrock.data.entity.EntityData;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockTranslator;
|
||||
import org.geysermc.connector.utils.MessageUtils;
|
||||
|
||||
public class CommandBlockMinecartEntity extends DefaultBlockMinecartEntity {
|
||||
|
||||
public CommandBlockMinecartEntity(long entityId, long geyserId, EntityType entityType, Vector3f position, Vector3f motion, Vector3f rotation) {
|
||||
super(entityId, geyserId, entityType, position, motion, rotation);
|
||||
// Required, or else the GUI will not open
|
||||
metadata.put(EntityData.CONTAINER_TYPE, (byte) 16);
|
||||
metadata.put(EntityData.CONTAINER_BASE_SIZE, 1);
|
||||
// Required, or else the client does not bother to send a packet back with the new information
|
||||
metadata.put(EntityData.COMMAND_BLOCK_ENABLED, (byte) 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateBedrockMetadata(EntityMetadata entityMetadata, GeyserSession session) {
|
||||
if (entityMetadata.getId() == 13) {
|
||||
metadata.put(EntityData.COMMAND_BLOCK_COMMAND, entityMetadata.getValue());
|
||||
}
|
||||
if (entityMetadata.getId() == 14) {
|
||||
metadata.put(EntityData.COMMAND_BLOCK_LAST_OUTPUT, MessageUtils.getBedrockMessage((Message) entityMetadata.getValue()));
|
||||
}
|
||||
super.updateBedrockMetadata(entityMetadata, session);
|
||||
}
|
||||
|
||||
/**
|
||||
* By default, the command block shown is purple on Bedrock, which does not match Java Edition's orange.
|
||||
*/
|
||||
@Override
|
||||
public void updateDefaultBlockMetadata() {
|
||||
metadata.put(EntityData.DISPLAY_ITEM, BlockTranslator.BEDROCK_RUNTIME_COMMAND_BLOCK_ID);
|
||||
metadata.put(EntityData.DISPLAY_OFFSET, 6);
|
||||
}
|
||||
}
|
|
@ -135,7 +135,7 @@ public enum EntityType {
|
|||
MINECART_CHEST(MinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:chest_minecart"),
|
||||
MINECART_FURNACE(FurnaceMinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:minecart"),
|
||||
MINECART_SPAWNER(SpawnerMinecartEntity.class, 98, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:minecart"),
|
||||
MINECART_COMMAND_BLOCK(MinecartEntity.class, 100, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:command_block_minecart"),
|
||||
MINECART_COMMAND_BLOCK(CommandBlockMinecartEntity.class, 100, 0.7f, 0.98f, 0.98f, 0.35f, "minecraft:command_block_minecart"),
|
||||
LINGERING_POTION(ThrowableEntity.class, 101, 0f),
|
||||
LLAMA_SPIT(Entity.class, 102, 0.25f),
|
||||
EVOKER_FANGS(Entity.class, 103, 0.8f, 0.5f, 0.5f, 0f, "minecraft:evocation_fang"),
|
||||
|
|
|
@ -714,7 +714,8 @@ public class GeyserSession implements CommandSender {
|
|||
// This allows mobile players access to a GUI for doing commands. The commands there do not change above OPERATOR
|
||||
// and all commands there are accessible with OP permission level 2
|
||||
adventureSettingsPacket.setCommandPermission(opPermissionLevel >= 2 ? CommandPermission.OPERATOR : CommandPermission.NORMAL);
|
||||
adventureSettingsPacket.setPlayerPermission(PlayerPermission.MEMBER);
|
||||
// Required to make command blocks destroyable
|
||||
adventureSettingsPacket.setPlayerPermission(opPermissionLevel >= 2 ? PlayerPermission.OPERATOR : PlayerPermission.MEMBER);
|
||||
|
||||
Set<AdventureSetting> flags = new HashSet<>();
|
||||
if (canFly) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
package org.geysermc.connector.network.translators.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientUpdateJigsawBlockPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.client.world.ClientUpdateSignPacket;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.protocol.bedrock.packet.BlockEntityDataPacket;
|
||||
|
@ -109,6 +110,18 @@ public class BedrockBlockEntityDataTranslator extends PacketTranslator<BlockEnti
|
|||
|
||||
// We set the sign text cached in the session to null to indicate there is no work-in-progress sign
|
||||
session.setLastSignMessage(null);
|
||||
|
||||
} else if (tag.getString("id").equals("JigsawBlock")) {
|
||||
// Client has just sent a jigsaw block update
|
||||
Position pos = new Position(tag.getInt("x"), tag.getInt("y"), tag.getInt("z"));
|
||||
String name = tag.getString("name");
|
||||
String target = tag.getString("target");
|
||||
String pool = tag.getString("target_pool");
|
||||
String finalState = tag.getString("final_state");
|
||||
String joint = tag.getString("joint");
|
||||
ClientUpdateJigsawBlockPacket jigsawPacket = new ClientUpdateJigsawBlockPacket(pos, name, target, pool,
|
||||
finalState, joint);
|
||||
session.sendDownstreamPacket(jigsawPacket);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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.connector.network.translators.bedrock;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.block.CommandBlockMode;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientUpdateCommandBlockMinecartPacket;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientUpdateCommandBlockPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.CommandBlockUpdatePacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
|
||||
@Translator(packet = CommandBlockUpdatePacket.class)
|
||||
public class BedrockCommandBlockUpdateTranslator extends PacketTranslator<CommandBlockUpdatePacket> {
|
||||
|
||||
@Override
|
||||
public void translate(CommandBlockUpdatePacket packet, GeyserSession session) {
|
||||
String command = packet.getCommand();
|
||||
boolean outputTracked = packet.isOutputTracked();
|
||||
if (packet.isBlock()) {
|
||||
CommandBlockMode mode;
|
||||
switch (packet.getMode()) {
|
||||
case CHAIN: // The green one
|
||||
mode = CommandBlockMode.SEQUENCE;
|
||||
break;
|
||||
case REPEATING: // The purple one
|
||||
mode = CommandBlockMode.AUTO;
|
||||
break;
|
||||
default: // NORMAL, the orange one
|
||||
mode = CommandBlockMode.REDSTONE;
|
||||
break;
|
||||
}
|
||||
boolean isConditional = packet.isConditional();
|
||||
boolean automatic = !packet.isRedstoneMode(); // Automatic = Always Active option in Java
|
||||
ClientUpdateCommandBlockPacket commandBlockPacket = new ClientUpdateCommandBlockPacket(
|
||||
new Position(packet.getBlockPosition().getX(), packet.getBlockPosition().getY(), packet.getBlockPosition().getZ()),
|
||||
command, mode, outputTracked, isConditional, automatic);
|
||||
session.sendDownstreamPacket(commandBlockPacket);
|
||||
} else {
|
||||
ClientUpdateCommandBlockMinecartPacket commandMinecartPacket = new ClientUpdateCommandBlockMinecartPacket(
|
||||
(int) session.getEntityCache().getEntityByGeyserId(packet.getMinecartRuntimeEntityId()).getEntityId(),
|
||||
command, outputTracked
|
||||
);
|
||||
session.sendDownstreamPacket(commandMinecartPacket);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -39,8 +39,11 @@ import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlaye
|
|||
import com.nukkitx.math.vector.Vector3f;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.LevelEventType;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.InventoryTransactionPacket;
|
||||
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
|
||||
import org.geysermc.connector.entity.CommandBlockMinecartEntity;
|
||||
import org.geysermc.connector.entity.Entity;
|
||||
import org.geysermc.connector.entity.ItemFrameEntity;
|
||||
import org.geysermc.connector.entity.living.merchant.AbstractMerchantEntity;
|
||||
|
@ -105,6 +108,24 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
session.sendDownstreamPacket(itemPacket);
|
||||
}
|
||||
|
||||
if (packet.getActions().isEmpty()) {
|
||||
if (session.getOpPermissionLevel() >= 2 && session.getGameMode() == GameMode.CREATIVE) {
|
||||
// Otherwise insufficient permissions
|
||||
int blockState = BlockTranslator.getJavaBlockState(packet.getBlockRuntimeId());
|
||||
String blockName = BlockTranslator.getJavaIdBlockMap().inverse().getOrDefault(blockState, "");
|
||||
// In the future this can be used for structure blocks too, however not all elements
|
||||
// are available in each GUI
|
||||
if (blockName.contains("jigsaw")) {
|
||||
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
||||
openPacket.setBlockPosition(packet.getBlockPosition());
|
||||
openPacket.setId((byte) 1);
|
||||
openPacket.setType(ContainerType.JIGSAW_EDITOR);
|
||||
openPacket.setUniqueEntityId(-1);
|
||||
session.sendUpstreamPacket(openPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Vector3i blockPos = packet.getBlockPosition();
|
||||
// TODO: Find a better way to do this?
|
||||
switch (packet.getBlockFace()) {
|
||||
|
@ -197,6 +218,18 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
|
|||
//https://wiki.vg/Protocol#Interact_Entity
|
||||
switch (packet.getActionType()) {
|
||||
case 0: //Interact
|
||||
if (entity instanceof CommandBlockMinecartEntity) {
|
||||
// The UI is handled client-side on Java Edition
|
||||
// Ensure OP permission level and gamemode is appropriate
|
||||
if (session.getOpPermissionLevel() < 2 || session.getGameMode() != GameMode.CREATIVE) return;
|
||||
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
||||
openPacket.setBlockPosition(Vector3i.ZERO);
|
||||
openPacket.setId((byte) 1);
|
||||
openPacket.setType(ContainerType.COMMAND_BLOCK);
|
||||
openPacket.setUniqueEntityId(entity.getGeyserId());
|
||||
session.sendUpstreamPacket(openPacket);
|
||||
break;
|
||||
}
|
||||
Vector3f vector = packet.getClickPosition();
|
||||
ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
|
||||
InteractAction.INTERACT, Hand.MAIN_HAND, session.isSneaking());
|
||||
|
|
|
@ -25,8 +25,12 @@
|
|||
|
||||
package org.geysermc.connector.network.translators.java.world;
|
||||
|
||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||
import com.github.steveice10.mc.protocol.data.game.world.block.UpdatedTileType;
|
||||
import com.github.steveice10.mc.protocol.packet.ingame.server.world.ServerUpdateTileEntityPacket;
|
||||
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.protocol.bedrock.data.inventory.ContainerType;
|
||||
import com.nukkitx.protocol.bedrock.packet.ContainerOpenPacket;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.PacketTranslator;
|
||||
import org.geysermc.connector.network.translators.Translator;
|
||||
|
@ -54,5 +58,15 @@ public class JavaUpdateTileEntityTranslator extends PacketTranslator<ServerUpdat
|
|||
} else {
|
||||
BlockEntityUtils.updateBlockEntity(session, translator.getBlockEntityTag(id, packet.getNbt(), 0), packet.getPosition());
|
||||
}
|
||||
// If block entity is command block, OP permission level is appropriate, player is in creative mode and the NBT is not empty
|
||||
if (packet.getType() == UpdatedTileType.COMMAND_BLOCK && session.getOpPermissionLevel() >= 2 &&
|
||||
session.getGameMode() == GameMode.CREATIVE && packet.getNbt().size() > 5) {
|
||||
ContainerOpenPacket openPacket = new ContainerOpenPacket();
|
||||
openPacket.setBlockPosition(Vector3i.from(packet.getPosition().getX(), packet.getPosition().getY(), packet.getPosition().getZ()));
|
||||
openPacket.setId((byte) 1);
|
||||
openPacket.setType(ContainerType.COMMAND_BLOCK);
|
||||
openPacket.setUniqueEntityId(-1);
|
||||
session.sendUpstreamPacket(openPacket);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ public class BlockStateValues {
|
|||
|
||||
private static final Int2IntMap BANNER_COLORS = new Int2IntOpenHashMap();
|
||||
private static final Int2ByteMap BED_COLORS = new Int2ByteOpenHashMap();
|
||||
private static final Int2ByteMap COMMAND_BLOCK_VALUES = new Int2ByteOpenHashMap();
|
||||
private static final Int2ObjectMap<DoubleChestValue> DOUBLE_CHEST_VALUES = new Int2ObjectOpenHashMap<>();
|
||||
private static final Int2ObjectMap<String> FLOWER_POT_VALUES = new Int2ObjectOpenHashMap<>();
|
||||
private static final Map<String, NbtMap> FLOWER_POT_BLOCKS = new HashMap<>();
|
||||
|
@ -67,6 +68,11 @@ public class BlockStateValues {
|
|||
return;
|
||||
}
|
||||
|
||||
if (entry.getKey().contains("command_block")) {
|
||||
COMMAND_BLOCK_VALUES.put(javaBlockState, entry.getKey().contains("conditional=true") ? (byte) 1 : (byte) 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry.getValue().get("double_chest_position") != null) {
|
||||
boolean isX = (entry.getValue().get("x") != null);
|
||||
boolean isDirectionPositive = ((entry.getValue().get("x") != null && entry.getValue().get("x").asBoolean()) ||
|
||||
|
@ -138,6 +144,16 @@ public class BlockStateValues {
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* The block state in Java and Bedrock both contain the conditional bit, however command block block entity tags
|
||||
* in Bedrock need the conditional information.
|
||||
*
|
||||
* @return the list of all command blocks and if they are conditional (1 or 0)
|
||||
*/
|
||||
public static Int2ByteMap getCommandBlockValues() {
|
||||
return COMMAND_BLOCK_VALUES;
|
||||
}
|
||||
|
||||
/**
|
||||
* All double chest values are part of the block state in Java and part of the block entity tag in Bedrock.
|
||||
* This gives the DoubleChestValue that can be calculated into the final tag.
|
||||
|
|
|
@ -67,6 +67,11 @@ public class BlockTranslator {
|
|||
public static final Int2BooleanMap JAVA_RUNTIME_ID_TO_CAN_HARVEST_WITH_HAND = new Int2BooleanOpenHashMap();
|
||||
public static final Int2ObjectMap<String> JAVA_RUNTIME_ID_TO_TOOL_TYPE = new Int2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* Runtime command block ID, used for fixing command block minecart appearances
|
||||
*/
|
||||
public static final int BEDROCK_RUNTIME_COMMAND_BLOCK_ID;
|
||||
|
||||
// For block breaking animation math
|
||||
public static final IntSet JAVA_RUNTIME_WOOL_IDS = new IntOpenHashSet();
|
||||
public static final int JAVA_RUNTIME_COBWEB_ID;
|
||||
|
@ -115,6 +120,7 @@ public class BlockTranslator {
|
|||
int javaRuntimeId = -1;
|
||||
int bedrockRuntimeId = 0;
|
||||
int cobwebRuntimeId = -1;
|
||||
int commandBlockRuntimeId = -1;
|
||||
int furnaceRuntimeId = -1;
|
||||
int furnaceLitRuntimeId = -1;
|
||||
int spawnerRuntimeId = -1;
|
||||
|
@ -142,14 +148,6 @@ public class BlockTranslator {
|
|||
JAVA_RUNTIME_ID_TO_TOOL_TYPE.put(javaRuntimeId, toolTypeNode.textValue());
|
||||
}
|
||||
|
||||
if (javaId.contains("wool")) {
|
||||
JAVA_RUNTIME_WOOL_IDS.add(javaRuntimeId);
|
||||
}
|
||||
|
||||
if (javaId.contains("cobweb")) {
|
||||
cobwebRuntimeId = javaRuntimeId;
|
||||
}
|
||||
|
||||
JAVA_ID_BLOCK_MAP.put(javaId, javaRuntimeId);
|
||||
|
||||
// Used for adding all "special" Java block states to block state map
|
||||
|
@ -205,15 +203,23 @@ public class BlockTranslator {
|
|||
}
|
||||
JAVA_TO_BEDROCK_BLOCK_MAP.put(javaRuntimeId, bedrockRuntimeId);
|
||||
|
||||
if (javaId.startsWith("minecraft:furnace[facing=north")) {
|
||||
if (javaId.contains("wool")) {
|
||||
JAVA_RUNTIME_WOOL_IDS.add(javaRuntimeId);
|
||||
|
||||
} else if (javaId.contains("cobweb")) {
|
||||
cobwebRuntimeId = javaRuntimeId;
|
||||
|
||||
} else if (javaId.equals("minecraft:command_block[conditional=false,facing=north]")) {
|
||||
commandBlockRuntimeId = bedrockRuntimeId;
|
||||
|
||||
} else if (javaId.startsWith("minecraft:furnace[facing=north")) {
|
||||
if (javaId.contains("lit=true")) {
|
||||
furnaceLitRuntimeId = javaRuntimeId;
|
||||
} else {
|
||||
furnaceRuntimeId = javaRuntimeId;
|
||||
}
|
||||
}
|
||||
|
||||
if (javaId.startsWith("minecraft:spawner")) {
|
||||
} else if (javaId.startsWith("minecraft:spawner")) {
|
||||
spawnerRuntimeId = javaRuntimeId;
|
||||
}
|
||||
|
||||
|
@ -225,6 +231,11 @@ public class BlockTranslator {
|
|||
}
|
||||
JAVA_RUNTIME_COBWEB_ID = cobwebRuntimeId;
|
||||
|
||||
if (commandBlockRuntimeId == -1) {
|
||||
throw new AssertionError("Unable to find command block in palette");
|
||||
}
|
||||
BEDROCK_RUNTIME_COMMAND_BLOCK_ID = commandBlockRuntimeId;
|
||||
|
||||
if (furnaceRuntimeId == -1) {
|
||||
throw new AssertionError("Unable to find furnace in palette");
|
||||
}
|
||||
|
|
|
@ -27,12 +27,9 @@ package org.geysermc.connector.network.translators.world.block.entity;
|
|||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.ListTag;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import org.geysermc.connector.network.translators.item.translators.BannerTranslator;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -65,17 +62,4 @@ public class BannerBlockEntityTranslator extends BlockEntityTranslator implement
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
CompoundTag tag = getConstantJavaTag(javaId, x, y, z);
|
||||
tag.put(new ListTag("Patterns"));
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z).toBuilder()
|
||||
.putList("Patterns", NbtType.COMPOUND, new ArrayList<>())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -50,15 +49,4 @@ public class BedBlockEntityTranslator extends BlockEntityTranslator implements R
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z).toBuilder()
|
||||
.putByte("color", (byte) 0)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,9 @@ package org.geysermc.connector.network.translators.world.block.entity;
|
|||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.Tag;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import org.geysermc.connector.GeyserConnector;
|
||||
import org.geysermc.connector.utils.BlockEntityUtils;
|
||||
|
@ -53,6 +53,7 @@ public abstract class BlockEntityTranslator {
|
|||
{
|
||||
// Bedrock/Java differences
|
||||
put("minecraft:enchanting_table", "EnchantTable");
|
||||
put("minecraft:jigsaw", "JigsawBlock");
|
||||
put("minecraft:piston_head", "PistonArm");
|
||||
put("minecraft:trapped_chest", "Chest");
|
||||
// There are some legacy IDs sent but as far as I can tell they are not needed for things to work properly
|
||||
|
@ -90,10 +91,6 @@ public abstract class BlockEntityTranslator {
|
|||
|
||||
public abstract Map<String, Object> translateTag(CompoundTag tag, int blockState);
|
||||
|
||||
public abstract CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z);
|
||||
|
||||
public abstract NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z);
|
||||
|
||||
public NbtMap getBlockEntityTag(String id, CompoundTag tag, int blockState) {
|
||||
int x = Integer.parseInt(String.valueOf(tag.getValue().get("x").getValue()));
|
||||
int y = Integer.parseInt(String.valueOf(tag.getValue().get("y").getValue()));
|
||||
|
@ -124,7 +121,7 @@ public abstract class BlockEntityTranslator {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T> T getOrDefault(com.github.steveice10.opennbt.tag.builtin.Tag tag, T defaultValue) {
|
||||
protected <T> T getOrDefault(Tag tag, T defaultValue) {
|
||||
return (tag != null && tag.getValue() != null) ? (T) tag.getValue() : defaultValue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,18 +50,6 @@ public class CampfireBlockEntityTranslator extends BlockEntityTranslator {
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
CompoundTag tag = getConstantJavaTag(javaId, x, y, z);
|
||||
tag.put(new ListTag("Items"));
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z);
|
||||
}
|
||||
|
||||
protected NbtMap getItem(CompoundTag tag) {
|
||||
ItemEntry entry = ItemRegistry.getItemEntry((String) tag.get("id").getValue());
|
||||
NbtMapBuilder tagBuilder = NbtMap.builder()
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.*;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
import org.geysermc.connector.utils.MessageUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@BlockEntity(name = "CommandBlock", regex = "command_block")
|
||||
public class CommandBlockBlockEntityTranslator extends BlockEntityTranslator implements RequiresBlockState {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> translateTag(CompoundTag tag, int blockState) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
if (tag.size() < 5) {
|
||||
return map; // These values aren't here
|
||||
}
|
||||
// Java infers from the block state, but Bedrock needs it in the tag
|
||||
map.put("conditionalMode", BlockStateValues.getCommandBlockValues().getOrDefault(blockState, (byte) 0));
|
||||
// Java and Bedrock values
|
||||
map.put("conditionMet", ((ByteTag) tag.get("conditionMet")).getValue());
|
||||
map.put("auto", ((ByteTag) tag.get("auto")).getValue());
|
||||
map.put("CustomName", MessageUtils.getBedrockMessage(((StringTag) tag.get("CustomName")).getValue()));
|
||||
map.put("powered", ((ByteTag) tag.get("powered")).getValue());
|
||||
map.put("Command", ((StringTag) tag.get("Command")).getValue());
|
||||
map.put("SuccessCount", ((IntTag) tag.get("SuccessCount")).getValue());
|
||||
map.put("TrackOutput", ((ByteTag) tag.get("TrackOutput")).getValue());
|
||||
map.put("UpdateLastExecution", ((ByteTag) tag.get("UpdateLastExecution")).getValue());
|
||||
if (tag.get("LastExecution") != null) {
|
||||
map.put("LastExecution", ((LongTag) tag.get("LastExecution")).getValue());
|
||||
} else {
|
||||
map.put("LastExecution", (long) 0);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isBlock(int blockState) {
|
||||
return BlockStateValues.getCommandBlockValues().containsKey(blockState);
|
||||
}
|
||||
}
|
|
@ -27,7 +27,6 @@ package org.geysermc.connector.network.translators.world.block.entity;
|
|||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.nukkitx.math.vector.Vector3i;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtMapBuilder;
|
||||
import org.geysermc.connector.network.session.GeyserSession;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
@ -92,13 +91,4 @@ public class DoubleChestBlockEntityTranslator extends BlockEntityTranslator impl
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -39,13 +38,4 @@ public class EmptyBlockEntityTranslator extends BlockEntityTranslator {
|
|||
return new HashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
return getConstantJavaTag(javaId, x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,14 +26,12 @@
|
|||
package org.geysermc.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.LongTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||
import com.nukkitx.nbt.NbtList;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import com.nukkitx.nbt.NbtType;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
@ -56,25 +54,11 @@ public class EndGatewayBlockEntityTranslator extends BlockEntityTranslator {
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
CompoundTag tag = getConstantJavaTag(javaId, x, y, z);
|
||||
tag.put(new LongTag("Age"));
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z).toBuilder()
|
||||
.putList("ExitPortal", NbtType.INT, Arrays.asList(0, 0, 0))
|
||||
.build();
|
||||
}
|
||||
|
||||
private int getExitPortalCoordinate(CompoundTag tag, String axis) {
|
||||
// Return 0 if it doesn't exist, otherwise give proper value
|
||||
if (tag.get("ExitPortal") != null) {
|
||||
LinkedHashMap<?, ?> compoundTag = (LinkedHashMap<?, ?>) tag.get("ExitPortal").getValue();
|
||||
com.github.steveice10.opennbt.tag.builtin.IntTag intTag = (com.github.steveice10.opennbt.tag.builtin.IntTag) compoundTag.get(axis);
|
||||
IntTag intTag = (IntTag) compoundTag.get(axis);
|
||||
return intTag.getValue();
|
||||
} return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2019-2020 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.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@BlockEntity(name = "JigsawBlock", regex = "jigsaw")
|
||||
public class JigsawBlockBlockEntityTranslator extends BlockEntityTranslator {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> translateTag(CompoundTag tag, int blockState) {
|
||||
Map<String, Object> map = new HashMap<>();
|
||||
map.put("joint", ((StringTag) tag.get("joint")).getValue());
|
||||
map.put("name", ((StringTag) tag.get("name")).getValue());
|
||||
map.put("target_pool", ((StringTag) tag.get("pool")).getValue());
|
||||
map.put("final_state", ((StringTag) tag.get("final_state")).getValue());
|
||||
map.put("target", ((StringTag) tag.get("target")).getValue());
|
||||
return map;
|
||||
}
|
||||
}
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -46,15 +45,4 @@ public class ShulkerBoxBlockEntityTranslator extends BlockEntityTranslator {
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z).toBuilder()
|
||||
.putByte("facing", (byte) 1)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ package org.geysermc.connector.network.translators.world.block.entity;
|
|||
|
||||
import com.github.steveice10.mc.protocol.data.message.MessageSerializer;
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import org.geysermc.connector.utils.MessageUtils;
|
||||
import org.geysermc.connector.utils.SignUtils;
|
||||
|
||||
|
@ -73,23 +72,6 @@ public class SignBlockEntityTranslator extends BlockEntityTranslator {
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
CompoundTag tag = getConstantJavaTag(javaId, x, y, z);
|
||||
tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text1", "{\"text\":\"\"}"));
|
||||
tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text2", "{\"text\":\"\"}"));
|
||||
tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text3", "{\"text\":\"\"}"));
|
||||
tag.put(new com.github.steveice10.opennbt.tag.builtin.StringTag("Text4", "{\"text\":\"\"}"));
|
||||
return tag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z).toBuilder()
|
||||
.putString("Text", "")
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps a color stored in a sign's Color tag to a Bedrock Edition formatting code.
|
||||
* <br>
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
|
||||
package org.geysermc.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import org.geysermc.connector.network.translators.world.block.BlockStateValues;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -51,16 +50,4 @@ public class SkullBlockEntityTranslator extends BlockEntityTranslator implements
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public com.github.steveice10.opennbt.tag.builtin.CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z).toBuilder()
|
||||
.putFloat("Rotation", 0f)
|
||||
.putByte("SkullType", (byte) 0)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
package org.geysermc.connector.network.translators.world.block.entity;
|
||||
|
||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||
import com.nukkitx.nbt.NbtMap;
|
||||
import org.geysermc.connector.entity.type.EntityType;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -86,16 +85,4 @@ public class SpawnerBlockEntityTranslator extends BlockEntityTranslator {
|
|||
return tags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompoundTag getDefaultJavaTag(String javaId, int x, int y, int z) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NbtMap getDefaultBedrockTag(String bedrockId, int x, int y, int z) {
|
||||
return getConstantBedrockTag(bedrockId, x, y, z).toBuilder()
|
||||
.putByte("isMovable", (byte) 1)
|
||||
.putString("id", "MobSpawner")
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue