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

@ -31,10 +31,10 @@ assignees: ''
<!--- Give us the exact output from /version. Saying "latest" does not help us at all. -->
**Geyser Version**
<!--- Give us the exact build number as well as branch if applicable. Saying "latest" does not help us at all. -->
<!--- Give us the exact build number as well as branch if applicable. Saying "latest" does not help us at all. Please also include if you are running the standalone version, or specify which plugin version you are using. If your issue is a connection problem, please specify if you are using the Floodgate plugin. -->
**Minecraft: Bedrock Edition Version**
<!-- The version of your Minecraft: Bedrock Edition client you tested with. -->
**Additional Context**
<!--- Add any other context about the problem here. --->
<!--- Add any other context about the problem here. Include any plugins on the Minecraft server that may cause problems. --->

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

@ -46,6 +46,9 @@ public class ItemTranslator {
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,9 +58,11 @@ public class EnchantmentTranslator extends NbtItemStackTranslator {
if (!(tag instanceof CompoundTag)) continue;
CompoundTag bedrockTag = remapEnchantment((CompoundTag) tag);
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,33 +42,30 @@ 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) {
}
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 ");
}
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
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;
}
}
soundPacket.setSound(sound);
soundPacket.setPosition(Vector3f.from(packet.getX(), packet.getY(), packet.getZ()));

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,7 +121,23 @@ 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);
}
/**
@ -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++;
}