Mirror von
https://github.com/GeyserMC/Geyser.git
synchronisiert 2024-11-19 14:30:17 +01:00
Merge master
Dieser Commit ist enthalten in:
Commit
db003293e9
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.platform.spigot;
|
||||||
|
|
||||||
|
import com.destroystokyo.paper.event.server.PaperServerListPingEvent;
|
||||||
|
import com.destroystokyo.paper.network.StatusClient;
|
||||||
|
import com.destroystokyo.paper.profile.PlayerProfile;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.geysermc.geyser.network.GameProtocol;
|
||||||
|
import org.geysermc.geyser.ping.GeyserPingInfo;
|
||||||
|
import org.geysermc.geyser.ping.IGeyserPingPassthrough;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is used if possible, so listeners listening for PaperServerListPingEvent exclusively have their changes
|
||||||
|
* applied.
|
||||||
|
*/
|
||||||
|
public final class GeyserPaperPingPassthrough implements IGeyserPingPassthrough {
|
||||||
|
private final GeyserSpigotLogger logger;
|
||||||
|
|
||||||
|
public GeyserPaperPingPassthrough(GeyserSpigotLogger logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public GeyserPingInfo getPingInformation(InetSocketAddress inetSocketAddress) {
|
||||||
|
try {
|
||||||
|
// We'd rather *not* use deprecations here, but unfortunately any Adventure class would be relocated at
|
||||||
|
// runtime because we still have to shade in our own Adventure class. For now.
|
||||||
|
PaperServerListPingEvent event = new PaperServerListPingEvent(new GeyserStatusClient(inetSocketAddress),
|
||||||
|
Bukkit.getMotd(), Bukkit.getOnlinePlayers().size(), Bukkit.getMaxPlayers(), Bukkit.getVersion(),
|
||||||
|
GameProtocol.getJavaProtocolVersion(), null);
|
||||||
|
Bukkit.getPluginManager().callEvent(event);
|
||||||
|
if (event.isCancelled()) {
|
||||||
|
// We have to send a ping, so not really sure what else to do here.
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
GeyserPingInfo.Players players;
|
||||||
|
if (event.shouldHidePlayers()) {
|
||||||
|
players = new GeyserPingInfo.Players(1, 0);
|
||||||
|
} else {
|
||||||
|
players = new GeyserPingInfo.Players(event.getMaxPlayers(), event.getNumPlayers());
|
||||||
|
}
|
||||||
|
|
||||||
|
GeyserPingInfo geyserPingInfo = new GeyserPingInfo(event.getMotd(), players,
|
||||||
|
new GeyserPingInfo.Version(Bukkit.getVersion(), GameProtocol.getJavaProtocolVersion()));
|
||||||
|
|
||||||
|
if (!event.shouldHidePlayers()) {
|
||||||
|
for (PlayerProfile profile : event.getPlayerSample()) {
|
||||||
|
geyserPingInfo.getPlayerList().add(profile.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return geyserPingInfo;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.debug("Error while getting Paper ping passthrough: " + e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private record GeyserStatusClient(InetSocketAddress address) implements StatusClient {
|
||||||
|
@Override
|
||||||
|
public @NotNull InetSocketAddress getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getProtocolVersion() {
|
||||||
|
return GameProtocol.getJavaProtocolVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public @Nullable InetSocketAddress getVirtualHost() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -168,8 +168,14 @@ public class GeyserSpigotPlugin extends JavaPlugin implements GeyserBootstrap {
|
|||||||
if (geyserConfig.isLegacyPingPassthrough()) {
|
if (geyserConfig.isLegacyPingPassthrough()) {
|
||||||
this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
this.geyserSpigotPingPassthrough = GeyserLegacyPingPassthrough.init(geyser);
|
||||||
} else {
|
} else {
|
||||||
|
try {
|
||||||
|
Class.forName("com.destroystokyo.paper.event.server.PaperServerListPingEvent");
|
||||||
|
this.geyserSpigotPingPassthrough = new GeyserPaperPingPassthrough(geyserLogger);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
this.geyserSpigotPingPassthrough = new GeyserSpigotPingPassthrough(geyserLogger);
|
this.geyserSpigotPingPassthrough = new GeyserSpigotPingPassthrough(geyserLogger);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
geyserLogger.debug("Spigot ping passthrough type: " + (this.geyserSpigotPingPassthrough == null ? null : this.geyserSpigotPingPassthrough.getClass()));
|
||||||
|
|
||||||
this.geyserCommandManager = new GeyserSpigotCommandManager(geyser);
|
this.geyserCommandManager = new GeyserSpigotCommandManager(geyser);
|
||||||
this.geyserCommandManager.init();
|
this.geyserCommandManager.init();
|
||||||
|
@ -33,7 +33,7 @@ object Versions {
|
|||||||
const val protocolVersion = "977a9a1"
|
const val protocolVersion = "977a9a1"
|
||||||
const val raknetVersion = "1.6.28-SNAPSHOT"
|
const val raknetVersion = "1.6.28-SNAPSHOT"
|
||||||
const val mcauthlibVersion = "d9d773e"
|
const val mcauthlibVersion = "d9d773e"
|
||||||
const val mcprotocollibversion = "bf3919a"
|
const val mcprotocollibversion = "bb2b414"
|
||||||
const val packetlibVersion = "3.0"
|
const val packetlibVersion = "3.0"
|
||||||
const val adventureVersion = "4.9.3"
|
const val adventureVersion = "4.9.3"
|
||||||
const val eventVersion = "3.0.0"
|
const val eventVersion = "3.0.0"
|
||||||
|
@ -37,7 +37,6 @@ import com.github.steveice10.mc.protocol.MinecraftProtocol;
|
|||||||
import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper;
|
import com.github.steveice10.mc.protocol.codec.MinecraftCodecHelper;
|
||||||
import com.github.steveice10.mc.protocol.data.ProtocolState;
|
import com.github.steveice10.mc.protocol.data.ProtocolState;
|
||||||
import com.github.steveice10.mc.protocol.data.UnexpectedEncryptionException;
|
import com.github.steveice10.mc.protocol.data.UnexpectedEncryptionException;
|
||||||
import com.github.steveice10.mc.protocol.data.game.MessageType;
|
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
import com.github.steveice10.mc.protocol.data.game.entity.metadata.Pose;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
import com.github.steveice10.mc.protocol.data.game.entity.object.Direction;
|
||||||
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
import com.github.steveice10.mc.protocol.data.game.entity.player.GameMode;
|
||||||
@ -123,9 +122,9 @@ import org.geysermc.geyser.session.auth.AuthData;
|
|||||||
import org.geysermc.geyser.session.auth.BedrockClientData;
|
import org.geysermc.geyser.session.auth.BedrockClientData;
|
||||||
import org.geysermc.geyser.session.cache.*;
|
import org.geysermc.geyser.session.cache.*;
|
||||||
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
import org.geysermc.geyser.skin.FloodgateSkinUploader;
|
||||||
|
import org.geysermc.geyser.text.ChatTypeEntry;
|
||||||
import org.geysermc.geyser.text.GeyserLocale;
|
import org.geysermc.geyser.text.GeyserLocale;
|
||||||
import org.geysermc.geyser.text.MinecraftLocale;
|
import org.geysermc.geyser.text.MinecraftLocale;
|
||||||
import org.geysermc.geyser.text.TextDecoration;
|
|
||||||
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
import org.geysermc.geyser.translator.inventory.InventoryTranslator;
|
||||||
import org.geysermc.geyser.translator.text.MessageTranslator;
|
import org.geysermc.geyser.translator.text.MessageTranslator;
|
||||||
import org.geysermc.geyser.util.ChunkUtils;
|
import org.geysermc.geyser.util.ChunkUtils;
|
||||||
@ -336,7 +335,7 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
*/
|
*/
|
||||||
private final Map<String, JavaDimension> dimensions = new Object2ObjectOpenHashMap<>(3);
|
private final Map<String, JavaDimension> dimensions = new Object2ObjectOpenHashMap<>(3);
|
||||||
|
|
||||||
private final Map<MessageType, TextDecoration> chatTypes = new EnumMap<>(MessageType.class);
|
private final Int2ObjectMap<ChatTypeEntry> chatTypes = new Int2ObjectOpenHashMap<>(8);
|
||||||
|
|
||||||
@Setter
|
@Setter
|
||||||
private int breakingBlock;
|
private int breakingBlock;
|
||||||
@ -547,6 +546,8 @@ public class GeyserSession implements GeyserConnection, GeyserCommandSource {
|
|||||||
this.playerEntity = new SessionPlayerEntity(this);
|
this.playerEntity = new SessionPlayerEntity(this);
|
||||||
collisionManager.updatePlayerBoundingBox(this.playerEntity.getPosition());
|
collisionManager.updatePlayerBoundingBox(this.playerEntity.getPosition());
|
||||||
|
|
||||||
|
ChatTypeEntry.applyDefaults(chatTypes);
|
||||||
|
|
||||||
this.playerInventory = new PlayerInventory();
|
this.playerInventory = new PlayerInventory();
|
||||||
this.openInventory = null;
|
this.openInventory = null;
|
||||||
this.craftingRecipes = new Int2ObjectOpenHashMap<>();
|
this.craftingRecipes = new Int2ObjectOpenHashMap<>();
|
||||||
|
@ -33,12 +33,15 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class UpstreamSession {
|
public class UpstreamSession {
|
||||||
@Getter private final BedrockServerSession session;
|
@Getter private final BedrockServerSession session;
|
||||||
@Getter @Setter
|
@Getter @Setter
|
||||||
private boolean initialized = false;
|
private boolean initialized = false;
|
||||||
|
private Queue<BedrockPacket> postStartGamePackets = new ArrayDeque<>();
|
||||||
|
|
||||||
public void sendPacket(@NonNull BedrockPacket packet) {
|
public void sendPacket(@NonNull BedrockPacket packet) {
|
||||||
if (!isClosed()) {
|
if (!isClosed()) {
|
||||||
@ -56,6 +59,25 @@ public class UpstreamSession {
|
|||||||
session.disconnect(reason);
|
session.disconnect(reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queue a packet that must be delayed until after login.
|
||||||
|
*/
|
||||||
|
public void queuePostStartGamePacket(BedrockPacket packet) {
|
||||||
|
postStartGamePackets.add(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendPostStartGamePackets() {
|
||||||
|
if (isClosed()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BedrockPacket packet;
|
||||||
|
while ((packet = postStartGamePackets.poll()) != null) {
|
||||||
|
session.sendPacket(packet);
|
||||||
|
}
|
||||||
|
postStartGamePackets = null;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
return session.isClosed();
|
return session.isClosed();
|
||||||
}
|
}
|
||||||
|
57
core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java
Normale Datei
57
core/src/main/java/org/geysermc/geyser/text/ChatTypeEntry.java
Normale Datei
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019-2022 GeyserMC. http://geysermc.org
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*
|
||||||
|
* @author GeyserMC
|
||||||
|
* @link https://github.com/GeyserMC/Geyser
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.geysermc.geyser.text;
|
||||||
|
|
||||||
|
import com.github.steveice10.mc.protocol.data.game.MessageType;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
|
|
||||||
|
import javax.annotation.Nonnull;
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
public record ChatTypeEntry(@Nonnull TextPacket.Type bedrockChatType, @Nullable TextDecoration textDecoration) {
|
||||||
|
private static final ChatTypeEntry CHAT = new ChatTypeEntry(TextPacket.Type.CHAT, null);
|
||||||
|
private static final ChatTypeEntry SYSTEM = new ChatTypeEntry(TextPacket.Type.CHAT, null);
|
||||||
|
private static final ChatTypeEntry TIP = new ChatTypeEntry(TextPacket.Type.CHAT, null);
|
||||||
|
private static final ChatTypeEntry RAW = new ChatTypeEntry(TextPacket.Type.CHAT, null);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply defaults to a map so it isn't empty in the event a chat message is sent before the login packet.
|
||||||
|
*/
|
||||||
|
public static void applyDefaults(Int2ObjectMap<ChatTypeEntry> chatTypes) {
|
||||||
|
// So the proper way to do this, probably, would be to dump the NBT data from vanilla and load it.
|
||||||
|
// But, the only way this happens is if a chat message is sent to us before the login packet, which is rare.
|
||||||
|
// So we'll just make sure chat ends up in the right place.
|
||||||
|
chatTypes.put(MessageType.CHAT.ordinal(), CHAT);
|
||||||
|
chatTypes.put(MessageType.SYSTEM.ordinal(), SYSTEM);
|
||||||
|
chatTypes.put(MessageType.GAME_INFO.ordinal(), TIP);
|
||||||
|
chatTypes.put(MessageType.SAY_COMMAND.ordinal(), RAW);
|
||||||
|
chatTypes.put(MessageType.MSG_COMMAND.ordinal(), RAW);
|
||||||
|
chatTypes.put(MessageType.TEAM_MSG_COMMAND.ordinal(), RAW);
|
||||||
|
chatTypes.put(MessageType.EMOTE_COMMAND.ordinal(), RAW);
|
||||||
|
chatTypes.put(MessageType.TELLRAW_COMMAND.ordinal(), RAW);
|
||||||
|
}
|
||||||
|
}
|
@ -30,16 +30,20 @@ import com.github.steveice10.mc.protocol.packet.ingame.clientbound.ClientboundLo
|
|||||||
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
|
import com.github.steveice10.mc.protocol.packet.ingame.serverbound.ServerboundCustomPayloadPacket;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
import com.github.steveice10.opennbt.tag.builtin.CompoundTag;
|
||||||
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
import com.github.steveice10.opennbt.tag.builtin.IntTag;
|
||||||
|
import com.github.steveice10.opennbt.tag.builtin.StringTag;
|
||||||
import com.nukkitx.protocol.bedrock.data.GameRuleData;
|
import com.nukkitx.protocol.bedrock.data.GameRuleData;
|
||||||
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
|
import com.nukkitx.protocol.bedrock.data.PlayerPermission;
|
||||||
import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket;
|
import com.nukkitx.protocol.bedrock.packet.AdventureSettingsPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.GameRulesChangedPacket;
|
import com.nukkitx.protocol.bedrock.packet.GameRulesChangedPacket;
|
||||||
import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
import com.nukkitx.protocol.bedrock.packet.SetPlayerGameTypePacket;
|
||||||
|
import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
||||||
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
|
import org.geysermc.floodgate.pluginmessage.PluginMessageChannels;
|
||||||
import org.geysermc.geyser.api.network.AuthType;
|
import org.geysermc.geyser.api.network.AuthType;
|
||||||
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
|
||||||
import org.geysermc.geyser.level.JavaDimension;
|
import org.geysermc.geyser.level.JavaDimension;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
import org.geysermc.geyser.text.ChatTypeEntry;
|
||||||
import org.geysermc.geyser.text.TextDecoration;
|
import org.geysermc.geyser.text.TextDecoration;
|
||||||
import org.geysermc.geyser.translator.level.BiomeTranslator;
|
import org.geysermc.geyser.translator.level.BiomeTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
@ -64,21 +68,29 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||||||
|
|
||||||
JavaDimension.load(packet.getRegistry(), dimensions);
|
JavaDimension.load(packet.getRegistry(), dimensions);
|
||||||
|
|
||||||
Map<MessageType, TextDecoration> chatTypes = session.getChatTypes();
|
Int2ObjectMap<ChatTypeEntry> chatTypes = session.getChatTypes();
|
||||||
chatTypes.clear();
|
chatTypes.clear();
|
||||||
for (CompoundTag tag : JavaCodecEntry.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) {
|
for (CompoundTag tag : JavaCodecEntry.iterateAsTag(packet.getRegistry().get("minecraft:chat_type"))) {
|
||||||
|
// The ID is NOT ALWAYS THE SAME! ViaVersion as of 1.19 adds two registry entries that do NOT match vanilla.
|
||||||
int id = ((IntTag) tag.get("id")).getValue();
|
int id = ((IntTag) tag.get("id")).getValue();
|
||||||
CompoundTag element = tag.get("element");
|
CompoundTag element = tag.get("element");
|
||||||
CompoundTag chat = element.get("chat");
|
CompoundTag chat = element.get("chat");
|
||||||
if (chat == null) {
|
TextDecoration textDecoration = null;
|
||||||
continue;
|
if (chat != null) {
|
||||||
|
CompoundTag decorationTag = chat.get("decoration");
|
||||||
|
if (decorationTag != null) {
|
||||||
|
textDecoration = new TextDecoration(decorationTag);
|
||||||
}
|
}
|
||||||
CompoundTag decoration = chat.get("decoration");
|
|
||||||
if (decoration == null) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
MessageType type = MessageType.from(id);
|
MessageType type = MessageType.from(((StringTag) tag.get("name")).getValue());
|
||||||
chatTypes.put(type, new TextDecoration(decoration));
|
// TODO new types?
|
||||||
|
TextPacket.Type bedrockType = switch (type) {
|
||||||
|
case CHAT -> TextPacket.Type.CHAT;
|
||||||
|
case SYSTEM -> TextPacket.Type.SYSTEM;
|
||||||
|
case GAME_INFO -> TextPacket.Type.TIP;
|
||||||
|
default -> TextPacket.Type.RAW;
|
||||||
|
};
|
||||||
|
chatTypes.put(id, new ChatTypeEntry(bedrockType, textDecoration));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the player is already initialized and a join game packet is sent, they
|
// If the player is already initialized and a join game packet is sent, they
|
||||||
@ -103,6 +115,9 @@ public class JavaLoginTranslator extends PacketTranslator<ClientboundLoginPacket
|
|||||||
// The player has yet to spawn so let's do that using some of the information in this Java packet
|
// The player has yet to spawn so let's do that using some of the information in this Java packet
|
||||||
session.setDimension(newDimension);
|
session.setDimension(newDimension);
|
||||||
session.connect();
|
session.connect();
|
||||||
|
|
||||||
|
// It is now safe to send these packets
|
||||||
|
session.getUpstream().sendPostStartGamePackets();
|
||||||
}
|
}
|
||||||
|
|
||||||
AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket();
|
AdventureSettingsPacket bedrockPacket = new AdventureSettingsPacket();
|
||||||
|
@ -30,6 +30,7 @@ import com.nukkitx.protocol.bedrock.packet.TextPacket;
|
|||||||
import net.kyori.adventure.text.Component;
|
import net.kyori.adventure.text.Component;
|
||||||
import net.kyori.adventure.text.TranslatableComponent;
|
import net.kyori.adventure.text.TranslatableComponent;
|
||||||
import org.geysermc.geyser.session.GeyserSession;
|
import org.geysermc.geyser.session.GeyserSession;
|
||||||
|
import org.geysermc.geyser.text.ChatTypeEntry;
|
||||||
import org.geysermc.geyser.text.TextDecoration;
|
import org.geysermc.geyser.text.TextDecoration;
|
||||||
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
import org.geysermc.geyser.translator.protocol.PacketTranslator;
|
||||||
import org.geysermc.geyser.translator.protocol.Translator;
|
import org.geysermc.geyser.translator.protocol.Translator;
|
||||||
@ -44,22 +45,18 @@ public class JavaPlayerChatTranslator extends PacketTranslator<ClientboundPlayer
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void translate(GeyserSession session, ClientboundPlayerChatPacket packet) {
|
public void translate(GeyserSession session, ClientboundPlayerChatPacket packet) {
|
||||||
|
ChatTypeEntry entry = session.getChatTypes().get(packet.getTypeId());
|
||||||
|
|
||||||
TextPacket textPacket = new TextPacket();
|
TextPacket textPacket = new TextPacket();
|
||||||
textPacket.setPlatformChatId("");
|
textPacket.setPlatformChatId("");
|
||||||
textPacket.setSourceName("");
|
textPacket.setSourceName("");
|
||||||
textPacket.setXuid(session.getAuthData().xuid());
|
textPacket.setXuid(session.getAuthData().xuid());
|
||||||
// TODO new types
|
textPacket.setType(entry.bedrockChatType());
|
||||||
textPacket.setType(switch (packet.getType()) {
|
|
||||||
case CHAT -> TextPacket.Type.CHAT;
|
|
||||||
case SYSTEM -> TextPacket.Type.SYSTEM;
|
|
||||||
case GAME_INFO -> TextPacket.Type.TIP;
|
|
||||||
default -> TextPacket.Type.RAW;
|
|
||||||
});
|
|
||||||
|
|
||||||
textPacket.setNeedsTranslation(false);
|
textPacket.setNeedsTranslation(false);
|
||||||
Component message = packet.getUnsignedContent() == null ? packet.getSignedContent() : packet.getUnsignedContent();
|
Component message = packet.getUnsignedContent() == null ? packet.getSignedContent() : packet.getUnsignedContent();
|
||||||
|
|
||||||
TextDecoration decoration = session.getChatTypes().get(packet.getType());
|
TextDecoration decoration = entry.textDecoration();
|
||||||
if (decoration != null) {
|
if (decoration != null) {
|
||||||
// As of 1.19 - do this to apply all the styling for signed messages
|
// As of 1.19 - do this to apply all the styling for signed messages
|
||||||
// Though, Bedrock cannot care about the signed stuff.
|
// Though, Bedrock cannot care about the signed stuff.
|
||||||
|
@ -41,17 +41,15 @@ public class JavaSystemChatTranslator extends PacketTranslator<ClientboundSystem
|
|||||||
textPacket.setPlatformChatId("");
|
textPacket.setPlatformChatId("");
|
||||||
textPacket.setSourceName("");
|
textPacket.setSourceName("");
|
||||||
textPacket.setXuid(session.getAuthData().xuid());
|
textPacket.setXuid(session.getAuthData().xuid());
|
||||||
// TODO new types
|
textPacket.setType(session.getChatTypes().get(packet.getTypeId()).bedrockChatType());
|
||||||
textPacket.setType(switch (packet.getType()) {
|
|
||||||
case CHAT -> TextPacket.Type.CHAT;
|
|
||||||
case SYSTEM -> TextPacket.Type.SYSTEM;
|
|
||||||
case GAME_INFO -> TextPacket.Type.TIP;
|
|
||||||
default -> TextPacket.Type.RAW;
|
|
||||||
});
|
|
||||||
|
|
||||||
textPacket.setNeedsTranslation(false);
|
textPacket.setNeedsTranslation(false);
|
||||||
textPacket.setMessage(MessageTranslator.convertMessage(packet.getContent(), session.locale()));
|
textPacket.setMessage(MessageTranslator.convertMessage(packet.getContent(), session.locale()));
|
||||||
|
|
||||||
|
if (session.isSentSpawnPacket()) {
|
||||||
session.sendUpstreamPacket(textPacket);
|
session.sendUpstreamPacket(textPacket);
|
||||||
|
} else {
|
||||||
|
session.getUpstream().queuePostStartGamePacket(textPacket);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit e13611fd97b1801d4c4b914cd409351a49d19537
|
Subproject commit 99a1f8070e844d059454dacbb6e8b203521eed23
|
Laden…
In neuem Issue referenzieren
Einen Benutzer sperren