Fix NPE in console when a sound was missing and clean up nesting

This commit is contained in:
RednedEpic 2020-04-25 18:23:01 -05:00
commit 497825dd96
24 changed files with 346 additions and 90 deletions

View file

@ -33,7 +33,7 @@
<dependency>
<groupId>com.nukkitx.protocol</groupId>
<artifactId>bedrock-v390</artifactId>
<version>2.5.5-SNAPSHOT</version>
<version>2.5.6-SNAPSHOT</version>
<scope>compile</scope>
<exclusions>
<exclusion>
@ -117,7 +117,7 @@
<dependency>
<groupId>com.github.steveice10</groupId>
<artifactId>mcauthlib</artifactId>
<version>1.1-SNAPSHOT</version>
<version>1.3-SNAPSHOT</version>
<scope>compile</scope>
</dependency>
<dependency>
@ -145,5 +145,23 @@
<artifactId>reflections</artifactId>
<version>0.9.12</version>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-api</artifactId>
<version>3.0.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-gson</artifactId>
<version>3.0.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>net.kyori</groupId>
<artifactId>text-serializer-legacy</artifactId>
<version>3.0.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>

View file

@ -28,10 +28,7 @@ package org.geysermc.connector.command;
import lombok.Getter;
import org.geysermc.common.command.ICommandManager;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.defaults.HelpCommand;
import org.geysermc.connector.command.defaults.ListCommand;
import org.geysermc.connector.command.defaults.ReloadCommand;
import org.geysermc.connector.command.defaults.StopCommand;
import org.geysermc.connector.command.defaults.*;
import java.util.Collections;
import java.util.HashMap;
@ -51,6 +48,7 @@ public abstract class CommandManager implements ICommandManager {
registerCommand(new ListCommand(connector, "list", "List all players connected through Geyser.", "geyser.command.list"));
registerCommand(new ReloadCommand(connector, "reload", "Reloads the Geyser configurations. Kicks all players when used!", "geyser.command.reload"));
registerCommand(new StopCommand(connector, "stop", "Shuts down Geyser.", "geyser.command.stop"));
registerCommand(new OffhandCommand(connector, "offhand", "Puts an items in your offhand.", "geyser.command.offhand"));
}
public void registerCommand(GeyserCommand command) {

View file

@ -0,0 +1,61 @@
/*
* 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.command.defaults;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.command.CommandSender;
import org.geysermc.connector.command.GeyserCommand;
import org.geysermc.connector.network.session.GeyserSession;
public class OffhandCommand extends GeyserCommand {
private GeyserConnector connector;
public OffhandCommand(GeyserConnector connector, String name, String description, String permission) {
super(name, description, permission);
this.connector = connector;
}
@Override
public void execute(CommandSender sender, String[] args) {
if (sender.isConsole()) {
return;
}
// Make sure the sender is a Bedrock edition client
if (sender instanceof GeyserSession) {
GeyserSession session = (GeyserSession) sender;
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.SWAP_HANDS, new Position(0,0,0),
BlockFace.DOWN);
session.getDownstream().getSession().send(releaseItemPacket);
}
}
}

View file

@ -48,7 +48,7 @@ public class ReloadCommand extends GeyserCommand {
}
sender.sendMessage(ChatColor.YELLOW + "Reloading Geyser configurations... all connected bedrock clients will be kicked.");
for (GeyserSession session : connector.getPlayers().values()) {
session.getUpstream().disconnect("Geyser has been reloaded... sorry for the inconvenience!");
session.disconnect("Geyser has been reloaded... sorry for the inconvenience!");
}
connector.reload();
}

View file

@ -27,12 +27,15 @@ package org.geysermc.connector.entity;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.EntityMetadata;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.MetadataType;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Position;
import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.PlayerAction;
import com.github.steveice10.mc.protocol.data.game.world.block.BlockFace;
import com.github.steveice10.mc.protocol.data.message.TextMessage;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerActionPacket;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerUseItemPacket;
import com.nukkitx.math.vector.Vector3f;
import com.nukkitx.protocol.bedrock.data.EntityData;
import com.nukkitx.protocol.bedrock.data.EntityDataMap;
import com.nukkitx.protocol.bedrock.data.EntityFlag;
import com.nukkitx.protocol.bedrock.data.EntityFlags;
import com.nukkitx.protocol.bedrock.data.*;
import com.nukkitx.protocol.bedrock.packet.*;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
@ -45,6 +48,7 @@ import org.geysermc.connector.entity.attribute.Attribute;
import org.geysermc.connector.entity.attribute.AttributeType;
import org.geysermc.connector.entity.type.EntityType;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.utils.AttributeUtils;
import org.geysermc.connector.utils.MessageUtils;
@ -199,6 +203,28 @@ public class Entity {
metadata.getFlags().setFlag(EntityFlag.SPRINTING, (xd & 0x08) == 0x08);
metadata.getFlags().setFlag(EntityFlag.SWIMMING, (xd & 0x10) == 0x10);
metadata.getFlags().setFlag(EntityFlag.GLIDING, (xd & 0x80) == 0x80);
// Shield code
if (session.getPlayerEntity().getEntityId() == entityId && metadata.getFlags().getFlag(EntityFlag.SNEAKING)) {
if ((session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() == ItemTranslator.SHIELD) ||
(session.getInventoryCache().getPlayerInventory().getItem(45) != null && session.getInventoryCache().getPlayerInventory().getItem(45).getId() == ItemTranslator.SHIELD)) {
ClientPlayerUseItemPacket useItemPacket;
metadata.getFlags().setFlag(EntityFlag.BLOCKING, true);
if (session.getInventory().getItemInHand() != null && session.getInventory().getItemInHand().getId() == ItemTranslator.SHIELD) {
useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
}
// Else we just assume it's the offhand, to simplify logic and to assure the packet gets sent
else {
useItemPacket = new ClientPlayerUseItemPacket(Hand.OFF_HAND);
}
session.getDownstream().getSession().send(useItemPacket);
}
} else if (session.getPlayerEntity().getEntityId() == entityId && !metadata.getFlags().getFlag(EntityFlag.SNEAKING) && metadata.getFlags().getFlag(EntityFlag.BLOCKING)) {
metadata.getFlags().setFlag(EntityFlag.BLOCKING, false);
metadata.getFlags().setFlag(EntityFlag.DISABLE_BLOCKING, true);
ClientPlayerActionPacket releaseItemPacket = new ClientPlayerActionPacket(PlayerAction.RELEASE_USE_ITEM, new Position(0,0,0), BlockFace.DOWN);
session.getDownstream().getSession().send(releaseItemPacket);
}
// metadata.getFlags().setFlag(EntityFlag.INVISIBLE, (xd & 0x20) == 0x20);
if ((xd & 0x20) == 0x20)
metadata.put(EntityData.SCALE, 0.0f);
@ -221,6 +247,12 @@ public class Entity {
case 5: // no gravity
metadata.getFlags().setFlag(EntityFlag.HAS_GRAVITY, !(boolean) entityMetadata.getValue());
break;
case 7: // blocking
if (entityMetadata.getType() == MetadataType.BYTE) {
byte xd = (byte) entityMetadata.getValue();
metadata.getFlags().setFlag(EntityFlag.BLOCKING, (xd & 0x01) == 0x01);
}
break;
}
updateBedrockMetadata(session);

View file

@ -47,10 +47,10 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
@Override
public boolean handle(LoginPacket loginPacket) {
if (loginPacket.getProtocolVersion() > GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) {
session.getUpstream().disconnect("Outdated Geyser proxy! I'm still on " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion());
session.disconnect("Outdated Geyser proxy! I'm still on " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion());
return true;
} else if (loginPacket.getProtocolVersion() < GeyserConnector.BEDROCK_PACKET_CODEC.getProtocolVersion()) {
session.getUpstream().disconnect("Outdated Bedrock client! Please use " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion());
session.disconnect("Outdated Bedrock client! Please use " + GeyserConnector.BEDROCK_PACKET_CODEC.getMinecraftVersion());
return true;
}
@ -80,7 +80,7 @@ public class UpstreamPacketHandler extends LoggingPacketHandler {
session.getUpstream().sendPacket(stack);
break;
default:
session.getUpstream().disconnect("disconnectionScreen.resourcePack");
session.disconnect("disconnectionScreen.resourcePack");
break;
}

View file

@ -340,10 +340,16 @@ public class GeyserSession implements CommandSender {
downstream.getSession().disconnect(reason);
}
if (upstream != null && !upstream.isClosed()) {
connector.getPlayers().remove(this.upstream.getAddress());
upstream.disconnect(reason);
}
}
this.entityCache.getEntities().clear();
this.scoreboardCache.removeScoreboard();
this.inventoryCache.getInventories().clear();
this.windowCache.getWindows().clear();
closed = true;
}

View file

@ -25,14 +25,13 @@
package org.geysermc.connector.network.session.cache;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
import lombok.Setter;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
import java.util.HashMap;
import java.util.Map;
public class InventoryCache {
private GeyserSession session;
@ -42,7 +41,7 @@ public class InventoryCache {
private Inventory openInventory;
@Getter
private Map<Integer, Inventory> inventories = new HashMap<Integer, Inventory>();
private Int2ObjectMap<Inventory> inventories = new Int2ObjectOpenHashMap<>();
public InventoryCache(GeyserSession session) {
this.session = session;

View file

@ -34,6 +34,7 @@ import com.github.steveice10.mc.protocol.data.game.entity.player.Hand;
import com.github.steveice10.mc.protocol.data.game.entity.player.InteractAction;
import com.github.steveice10.mc.protocol.packet.ingame.client.player.ClientPlayerInteractEntityPacket;
import com.nukkitx.protocol.bedrock.packet.InteractPacket;
import org.geysermc.connector.network.translators.item.ItemTranslator;
@Translator(packet = InteractPacket.class)
public class BedrockInteractTranslator extends PacketTranslator<InteractPacket> {
@ -46,6 +47,9 @@ public class BedrockInteractTranslator extends PacketTranslator<InteractPacket>
switch (packet.getAction()) {
case INTERACT:
if (session.getInventory().getItem(session.getInventory().getHeldItemSlot() + 36).getId() == ItemTranslator.SHIELD) {
break;
}
ClientPlayerInteractEntityPacket interactPacket = new ClientPlayerInteractEntityPacket((int) entity.getEntityId(),
InteractAction.INTERACT, Hand.MAIN_HAND);
session.getDownstream().getSession().send(interactPacket);

View file

@ -46,6 +46,7 @@ import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.Translators;
import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.network.translators.item.ItemTranslator;
import org.geysermc.connector.utils.InventoryUtils;
@Translator(packet = InventoryTransactionPacket.class)
@ -104,6 +105,9 @@ public class BedrockInventoryTransactionTranslator extends PacketTranslator<Inve
}
break;
case 1:
if (session.getInventory().getItem(session.getInventory().getHeldItemSlot() + 36).getId() == ItemTranslator.SHIELD) {
break;
} // Handled in Entity.java
ClientPlayerUseItemPacket useItemPacket = new ClientPlayerUseItemPacket(Hand.MAIN_HAND);
session.getDownstream().getSession().send(useItemPacket);
break;

View file

@ -67,8 +67,10 @@ public class BedrockMovePlayerTranslator extends PacketTranslator<MovePlayerPack
double javaY = packet.getPosition().getY() - EntityType.PLAYER.getOffset();
if (packet.isOnGround()) javaY = Math.ceil(javaY * 2) / 2;
// We need to parse the float as a string since casting a float to a double causes us to
// lose precision and thus, causes players to get stuck when walking near walls
ClientPlayerPositionRotationPacket playerPositionRotationPacket = new ClientPlayerPositionRotationPacket(
packet.isOnGround(), GenericMath.round(packet.getPosition().getX(), 4), javaY, GenericMath.round(packet.getPosition().getZ(), 4), packet.getRotation().getY(), packet.getRotation().getX()
packet.isOnGround(), Double.parseDouble(Float.toString(packet.getPosition().getX())), javaY, Double.parseDouble(Float.toString(packet.getPosition().getZ())), packet.getRotation().getY(), packet.getRotation().getX()
);
// head yaw, pitch, head yaw

View file

@ -28,32 +28,33 @@ package org.geysermc.connector.network.translators.inventory;
import com.github.steveice10.mc.protocol.data.game.entity.metadata.ItemStack;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.packet.ingame.client.window.ClientCreativeInventoryActionPacket;
import com.nukkitx.protocol.bedrock.data.*;
import com.nukkitx.protocol.bedrock.data.ContainerId;
import com.nukkitx.protocol.bedrock.data.InventoryActionData;
import com.nukkitx.protocol.bedrock.data.InventorySource;
import com.nukkitx.protocol.bedrock.data.ItemData;
import com.nukkitx.protocol.bedrock.packet.InventoryContentPacket;
import com.nukkitx.protocol.bedrock.packet.InventorySlotPacket;
import it.unimi.dsi.fastutil.longs.LongArraySet;
import org.geysermc.connector.inventory.Inventory;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.Translators;
import org.geysermc.connector.network.translators.inventory.action.InventoryActionDataTranslator;
import org.geysermc.connector.utils.InventoryUtils;
import org.geysermc.connector.utils.Toolbox;
import java.util.List;
public class PlayerInventoryTranslator extends InventoryTranslator {
private static final LongArraySet HAS_RECEIVED_MESSAGE = new LongArraySet();
public PlayerInventoryTranslator() {
super(46);
}
@Override
public void updateInventory(GeyserSession session, Inventory inventory) {
// Crafting grid
for (int i = 1; i < 5; i++) {
InventorySlotPacket slotPacket = new InventorySlotPacket();
slotPacket.setContainerId(ContainerId.CURSOR);
slotPacket.setSlot(i + 27);
slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)));
session.getUpstream().sendPacket(slotPacket);
}
updateCraftingGrid(session, inventory);
InventoryContentPacket inventoryContentPacket = new InventoryContentPacket();
inventoryContentPacket.setContainerId(ContainerId.INVENTORY);
@ -86,6 +87,28 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
session.getUpstream().sendPacket(offhandPacket);
}
/**
* Update the crafting grid for the player to hide/show the barriers in the creative inventory
* @param session Session of the player
* @param inventory Inventory of the player
*/
public static void updateCraftingGrid(GeyserSession session, Inventory inventory) {
// Crafting grid
for (int i = 1; i < 5; i++) {
InventorySlotPacket slotPacket = new InventorySlotPacket();
slotPacket.setContainerId(ContainerId.CURSOR);
slotPacket.setSlot(i + 27);
if (session.getGameMode() == GameMode.CREATIVE) {
slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, new ItemStack(Toolbox.BARRIER_INDEX)));
}else{
slotPacket.setItem(Translators.getItemTranslator().translateToBedrock(session, inventory.getItem(i)));
}
session.getUpstream().sendPacket(slotPacket);
}
}
@Override
public void updateSlot(GeyserSession session, Inventory inventory, int slot) {
if (slot >= 1 && slot <= 44) {
@ -164,6 +187,11 @@ public class PlayerInventoryTranslator extends InventoryTranslator {
//crafting grid is not visible in creative mode in java edition
for (InventoryActionData action : actions) {
if (action.getSource().getContainerId() == ContainerId.CURSOR && (action.getSlot() >= 28 && 31 >= action.getSlot())) {
if (!HAS_RECEIVED_MESSAGE.contains(session.getPlayerEntity().getEntityId())) {
// TODO: Allow the crafting table to be used with non-standalone versions
session.sendMessage("The creative crafting table cannot be used as it's incompatible with Minecraft: Java Edition.");
HAS_RECEIVED_MESSAGE.add(session.getPlayerEntity().getEntityId());
}
updateInventory(session, inventory);
InventoryUtils.updateCursor(session);
return;

View file

@ -45,6 +45,9 @@ public class ItemTranslator {
private Int2ObjectMap<ItemStackTranslator> itemTranslators = new Int2ObjectOpenHashMap();
private List<NbtItemStackTranslator> nbtItemTranslators;
private Map<String, ItemEntry> javaIdentifierMap = new HashMap<>();
// Shield ID, used in Entity.java
public static final int SHIELD = 829;
public void init() {
Reflections ref = new Reflections("org.geysermc.connector.network.translators.item");

View file

@ -0,0 +1,84 @@
/*
* 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.item.translators.nbt;
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
import com.github.steveice10.opennbt.tag.builtin.ListTag;
import com.github.steveice10.opennbt.tag.builtin.StringTag;
import com.github.steveice10.opennbt.tag.builtin.Tag;
import org.geysermc.connector.network.translators.ItemRemapper;
import org.geysermc.connector.network.translators.NbtItemStackTranslator;
import org.geysermc.connector.network.translators.item.ItemEntry;
import org.geysermc.connector.utils.MessageUtils;
import java.util.ArrayList;
import java.util.List;
@ItemRemapper
public class BookPagesTranslator extends NbtItemStackTranslator {
@Override
public void translateToBedrock(CompoundTag itemTag, ItemEntry itemEntry) {
if (itemTag.contains("pages")) {
List<Tag> pages = new ArrayList<>();
ListTag pagesTag = itemTag.get("pages");
for (Tag tag : pagesTag.getValue()) {
if (!(tag instanceof StringTag))
continue;
StringTag textTag = (StringTag) tag;
CompoundTag pageTag = new CompoundTag("");
pageTag.put(new StringTag("photoname", ""));
pageTag.put(new StringTag("text", MessageUtils.getBedrockMessage(textTag.getValue())));
pages.add(pageTag);
}
itemTag.remove("pages");
itemTag.put(new ListTag("pages", pages));
}
}
@Override
public void translateToJava(CompoundTag itemTag, ItemEntry itemEntry) {
if (itemTag.contains("pages")) {
List<Tag> pages = new ArrayList<>();
ListTag pagesTag = itemTag.get("pages");
for (Tag tag : pagesTag.getValue()) {
if (!(tag instanceof CompoundTag))
continue;
CompoundTag pageTag = (CompoundTag) tag;
StringTag textTag = pageTag.get("text");
pages.add(new StringTag(MessageUtils.getJavaMessage(textTag.getValue())));
}
itemTag.remove("pages");
itemTag.put(new ListTag("pages", pages));
}
}
}

View file

@ -58,8 +58,10 @@ public class EnchantmentTranslator extends NbtItemStackTranslator {
if (!(tag instanceof CompoundTag)) continue;
CompoundTag bedrockTag = remapEnchantment((CompoundTag) tag);
bedrockTag.put(new ShortTag("GeyserStoredEnchantment", (short) 0));
newTags.add(bedrockTag);
if (bedrockTag != null) {
bedrockTag.put(new ShortTag("GeyserStoredEnchantment", (short) 0));
newTags.add(bedrockTag);
}
}
itemTag.remove("StoredEnchantments");
}
@ -117,11 +119,11 @@ public class EnchantmentTranslator extends NbtItemStackTranslator {
private CompoundTag remapEnchantment(CompoundTag tag) {
Tag javaEnchLvl = ((CompoundTag) tag).get("lvl");
Tag javaEnchLvl = tag.get("lvl");
if (!(javaEnchLvl instanceof ShortTag))
return null;
Tag javaEnchId = ((CompoundTag) tag).get("id");
Tag javaEnchId = tag.get("id");
if (!(javaEnchId instanceof StringTag))
return null;

View file

@ -32,6 +32,8 @@ import com.nukkitx.protocol.bedrock.data.CommandData;
import com.nukkitx.protocol.bedrock.data.CommandEnumData;
import com.nukkitx.protocol.bedrock.data.CommandParamData;
import com.nukkitx.protocol.bedrock.packet.AvailableCommandsPacket;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import lombok.Getter;
import org.geysermc.connector.GeyserConnector;
import org.geysermc.connector.network.session.GeyserSession;
@ -45,8 +47,8 @@ public class JavaServerDeclareCommandsTranslator extends PacketTranslator<Server
@Override
public void translate(ServerDeclareCommandsPacket packet, GeyserSession session) {
List<CommandData> commandData = new ArrayList<>();
Map<Integer, String> commands = new HashMap<>();
Map<Integer, List<CommandNode>> commandArgs = new HashMap<>();
Int2ObjectMap<String> commands = new Int2ObjectOpenHashMap<>();
Int2ObjectMap<List<CommandNode>> commandArgs = new Int2ObjectOpenHashMap<>();
// Get the first node, it should be a root node
CommandNode rootNode = packet.getNodes()[packet.getFirstNodeIndex()];

View file

@ -51,13 +51,12 @@ public class JavaMapDataTranslator extends PacketTranslator<ServerMapDataPacket>
mapItemDataPacket.setWidth(data.getColumns());
mapItemDataPacket.setHeight(data.getRows());
// Every int entry is an ARGB color
// Every int entry is an ABGR color
int[] colors = new int[data.getData().length];
int idx = 0;
for (byte colorId : data.getData()) {
colors[idx] = MapColor.fromId(colorId).toARGB();
idx++;
colors[idx++] = MapColor.fromId(colorId & 0xFF).toABGR();
}
mapItemDataPacket.setColors(colors);

View file

@ -25,14 +25,6 @@
package org.geysermc.connector.network.translators.java.world;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import com.github.steveice10.mc.protocol.data.game.ClientRequest;
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
import com.github.steveice10.mc.protocol.data.game.world.notify.EnterCreditsValue;
@ -43,13 +35,16 @@ import com.nukkitx.protocol.bedrock.data.EntityDataMap;
import com.nukkitx.protocol.bedrock.data.EntityFlag;
import com.nukkitx.protocol.bedrock.data.LevelEventType;
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket;
import com.nukkitx.protocol.bedrock.packet.LevelEventPacket;
import com.nukkitx.protocol.bedrock.packet.SetEntityDataPacket;
import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket;
import com.nukkitx.protocol.bedrock.packet.ShowCreditsPacket;
import com.nukkitx.protocol.bedrock.packet.*;
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet;
import org.geysermc.connector.entity.Entity;
import org.geysermc.connector.network.session.GeyserSession;
import org.geysermc.connector.network.translators.PacketTranslator;
import org.geysermc.connector.network.translators.Translator;
import org.geysermc.connector.network.translators.inventory.PlayerInventoryTranslator;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
@Translator(packet = ServerNotifyClientPacket.class)
public class JavaNotifyClientTranslator extends PacketTranslator<ServerNotifyClientPacket> {
@ -110,6 +105,10 @@ public class JavaNotifyClientTranslator extends PacketTranslator<ServerNotifyCli
entityDataPacket.setRuntimeEntityId(entity.getGeyserId());
entityDataPacket.getMetadata().putAll(metadata);
session.getUpstream().sendPacket(entityDataPacket);
// Update the crafting grid to add/remove barriers for creative inventory
PlayerInventoryTranslator.updateCraftingGrid(session, session.getInventory());
break;
case ENTER_CREDITS:
switch ((EnterCreditsValue) packet.getValue()) {

View file

@ -42,32 +42,29 @@ public class JavaPlayBuiltinSoundTranslator extends PacketTranslator<ServerPlayB
String packetSound = packet.getSound().getName();
SoundUtils.SoundMapping soundMapping = SoundUtils.fromJava(packetSound);
session.getConnector().getLogger()
.debug("[Builtin] Sound mapping " + packetSound + " -> "
session.getConnector().getLogger().debug("[Builtin] Sound mapping " + packetSound + " -> "
+ soundMapping + (soundMapping == null ? "[not found]" : "")
+ " - " + packet.toString());
if(soundMapping == null) {
if (soundMapping == null) {
return;
}
LevelSoundEventPacket soundPacket = new LevelSoundEventPacket();
SoundEvent sound = SoundUtils.toSoundEvent(soundMapping.getBedrock());
if(sound == null) {
if (sound == null) {
sound = SoundUtils.toSoundEvent(soundMapping.getBedrock());
if(sound == null) {
sound = SoundUtils.toSoundEvent(packetSound);
if(sound == null) {
session.getConnector().getLogger()
.debug("[Builtin] Sound for original " + packetSound + " to mappings " + soundPacket
+ " was not a playable level sound, or has yet to be mapped to an enum in " +
"NukkitX SoundEvent ");
} else {
session.getConnector().getLogger()
.debug("[Builtin] Sound for original " + packetSound + " to mappings " + soundPacket
+ " was not found in NukkitX SoundEvent, but original packet sound name was.");
}
return;
}
}
if (sound == null) {
sound = SoundUtils.toSoundEvent(packetSound);
}
if (sound == null) {
session.getConnector().getLogger().debug("[Builtin] Sound for original " + packetSound + " to mappings " + soundPacket
+ " was not a playable level sound, or has yet to be mapped to an enum in "
+ "NukkitX SoundEvent ");
} else {
session.getConnector().getLogger().debug("[Builtin] Sound for original " + packetSound + " to mappings " + soundPacket
+ " was not found in NukkitX SoundEvent, but original packet sound name was.");
}
soundPacket.setSound(sound);

View file

@ -1,7 +1,5 @@
package org.geysermc.connector.utils;
import java.util.Arrays;
public enum MapColor {
COLOR_0(-1, -1, -1),
COLOR_1(-1, -1, -1),
@ -212,6 +210,8 @@ public enum MapColor {
COLOR_206(37, 22, 16),
COLOR_207(19, 11, 8);
private static final MapColor[] VALUES = values();
private final int red;
private final int green;
private final int blue;
@ -222,23 +222,18 @@ public enum MapColor {
this.blue = blue;
}
int getId() {
return ordinal();
}
public static MapColor fromId(int id) {
return Arrays.stream(values()).filter(color -> color.getId() == id).findFirst().orElse(COLOR_0);
return id >= 0 && id < VALUES.length ? VALUES[id] : COLOR_0;
}
public int toARGB() {
public int toABGR() {
int alpha = 255;
if (red == -1 && green == -1 && blue == -1)
alpha = 0; // transparent
long result = red & 0xff;
result |= (green & 0xff) << 8;
result |= (blue & 0xff) << 16;
result |= (alpha & 0xff) << 24;
return (int) (result & 0xFFFFFFFFL);
return ((alpha & 0xFF) << 24) |
((blue & 0xFF) << 16) |
((green & 0xFF) << 8) |
((red & 0xFF) << 0);
}
}

View file

@ -32,6 +32,9 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import net.kyori.text.Component;
import net.kyori.text.serializer.gson.GsonComponentSerializer;
import net.kyori.text.serializer.legacy.LegacyComponentSerializer;
import org.geysermc.connector.network.session.GeyserSession;
import java.util.*;
@ -62,7 +65,7 @@ public class MessageUtils {
List<String> furtherParams = getTranslationParams(translation.getTranslationParams(), locale);
if (locale != null) {
strings.add(insertParams(LocaleUtils.getLocaleString(translation.getTranslationKey(), locale), furtherParams));
}else{
} else {
strings.addAll(furtherParams);
}
} else {
@ -118,14 +121,30 @@ public class MessageUtils {
}
public static String getBedrockMessage(Message message) {
return getTranslatedBedrockMessage(message, null, false);
Component component;
if (isMessage(message.getText())) {
component = GsonComponentSerializer.INSTANCE.deserialize(message.getText());
} else {
component = GsonComponentSerializer.INSTANCE.deserialize(message.toJsonString());
}
return LegacyComponentSerializer.legacy().serialize(component);
}
public static String getBedrockMessage(String message) {
Component component = GsonComponentSerializer.INSTANCE.deserialize(message);
return LegacyComponentSerializer.legacy().serialize(component);
}
public static String getJavaMessage(String message) {
Component component = LegacyComponentSerializer.legacy().deserialize(message);
return GsonComponentSerializer.INSTANCE.serialize(component);
}
/**
* Inserts the given parameters into the given message both in sequence and as requested
*
* @param message Message containing possible parameter replacement strings
* @param params A list of parameter strings
* @param params A list of parameter strings
* @return Parsed message with all params inserted as needed
*/
public static String insertParams(String message, List<String> params) {
@ -135,7 +154,7 @@ public class MessageUtils {
Matcher m = p.matcher(message);
while (m.find()) {
try {
newMessage = newMessage.replaceFirst("%" + m.group(1) + "\\$s" , params.get(Integer.parseInt(m.group(1)) - 1));
newMessage = newMessage.replaceFirst("%" + m.group(1) + "\\$s", params.get(Integer.parseInt(m.group(1)) - 1));
} catch (Exception e) {
// Couldn't find the param to replace
}

View file

@ -84,7 +84,7 @@ public class SoundUtils {
public static SoundEvent toSoundEvent(String sound) {
try {
return SoundEvent.valueOf(sound.toUpperCase().replaceAll("\\.", "_"));
} catch (IllegalArgumentException ex) {
} catch (Exception ex) {
return null;
}
}

View file

@ -55,7 +55,7 @@ public class Toolbox {
public static final Int2ObjectMap<ItemEntry> ITEM_ENTRIES = new Int2ObjectOpenHashMap<>();
public static final Map<String, Map<String, String>> LOCALE_MAPPINGS = new HashMap<>();
public static int BARRIER_INDEX = 0;
static {
/* Load biomes */
@ -129,6 +129,10 @@ public class Toolbox {
entry.getValue().get("bedrock_data").intValue(),
entry.getValue().get("is_block").booleanValue()));
}
if (entry.getKey().equals("minecraft:barrier")) {
BARRIER_INDEX = itemIndex;
}
itemIndex++;
}