forked from GeyserMC/Geyser
Fix NPE in console when a sound was missing and clean up nesting
This commit is contained in:
commit
497825dd96
24 changed files with 346 additions and 90 deletions
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
4
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -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. --->
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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()];
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue