Skip to content

Commit

Permalink
misc: 添加对旧版消息序列化方案的支持
Browse files Browse the repository at this point in the history
  • Loading branch information
MATRIX-feather committed Nov 25, 2024
1 parent a5d3b48 commit b4a3f12
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
package xyz.nifeather.morph.network.server;

import com.google.common.io.ByteStreams;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import net.kyori.adventure.text.Component;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.common.ClientboundCustomPayloadPacket;
Expand Down Expand Up @@ -47,6 +44,7 @@
import xyz.nifeather.morph.network.server.handlers.ICommandPacketHandler;
import xyz.nifeather.morph.network.server.handlers.LegacyCommandPacketHandler;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
Expand All @@ -69,12 +67,16 @@ public boolean logInComingPackets()
return logInComingPackets.get();
}

private void sendPacket(String channel, Player player, String message)
private void sendPacket(String channel, Player player, String message, boolean legacy)
{
var buffer = new FriendlyByteBuf(Unpooled.buffer()).writeUtf(message);
var buffer = new FriendlyByteBuf(Unpooled.buffer());
if (!legacy)
buffer.writeUtf(message);
else
buffer.writeBytes(message.getBytes(StandardCharsets.UTF_8));

if (logOutGoingPackets.get())
logPacket(true, player, channel, message, buffer.array().length);
logPacket(true, player, channel, message, buffer.readableBytes());

this.sendPacketRaw(channel, player, buffer, false);
}
Expand Down Expand Up @@ -192,15 +194,17 @@ private void load(MorphPlugin plugin, MorphConfigManager configManager)

var messenger = Bukkit.getMessenger();

// 注册init频道处理
// 注册incoming频道
messenger.registerIncomingPluginChannel(plugin, MessageChannel.initializeChannel, this::handleInitializeMessage);

// 注册api频道处理
messenger.registerIncomingPluginChannel(plugin, MessageChannel.versionChannel, this::handleVersionMessage);

// 注册command频道处理
messenger.registerIncomingPluginChannel(plugin, MessageChannel.commandChannel, this::handleCommandMessage);

// Legacy incoming channels
// todo: Remove legacy packetbuf support along with 1.23 update
messenger.registerIncomingPluginChannel(plugin, MessageChannel.versionChannelLegacy, this::handleVersionMessageLegacy);
messenger.registerIncomingPluginChannel(plugin, MessageChannel.commandChannelLegacy, this::handleCommandMessageLegacy);

// 注册outgoing频道
messenger.registerOutgoingPluginChannel(plugin, MessageChannel.initializeChannel);
messenger.registerOutgoingPluginChannel(plugin, MessageChannel.versionChannel);
Expand Down Expand Up @@ -294,17 +298,17 @@ public void handleInitializeMessage(@NotNull String cN, @NotNull Player player,
session.initializeState = InitializeState.HANDSHAKE;
session.isLegacyPacketBuf = isLegacyBuf;

this.sendPacket(MessageChannel.initializeChannel, player, newProtocolIdentify);
this.sendPacket(MessageChannel.initializeChannel, player, newProtocolIdentify, isLegacyBuf);
}

public void handleVersionMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data)
private void handleVersionInput(ICommandPacketHandler commandPacketHandler, String sourceChannel, Player player, byte[] data)
{
if (!allowClient.get()) return;

if (logInComingPackets.get())
logPacket(false, player, cN, data);
logPacket(false, player, sourceChannel, data);

var result = CommandPacketHandler.INSTANCE.handleVersionData(player, data);
var result = commandPacketHandler.handleVersionData(player, data);
if (!result.success())
{
logger.info("Packet decode failed for player %s, Rejecting...".formatted(player.getName()));
Expand Down Expand Up @@ -346,29 +350,31 @@ public void handleVersionMessage(@NotNull String cN, @NotNull Player player, byt
var session = this.getOrCreateSession(player);
session.initializeState = InitializeState.API_CHECKED;

this.sendPacket(MessageChannel.versionChannel, player, targetApiVersion);
if (!session.isLegacyPacketBuf)
this.sendPacket(MessageChannel.versionChannel, player, targetApiVersion);
else
this.sendPacket(MessageChannel.versionChannelLegacy, player, targetApiVersion);
}

public void handleCommandMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data)
private void handleCommandInput(ICommandPacketHandler commandPacketHandler, String sourceChannel, Player player, byte[] data)
{
if (!allowClient.get()) return;

if (logInComingPackets.get())
logPacket(false, player, cN, data);
logPacket(false, player, sourceChannel, data);

//在API检查完成之前忽略客户端的所有指令
if (this.getPlayerConnectionState(player).worseThan(InitializeState.API_CHECKED))
return;
var session = getSession(player);
if (session == null || session.initializeState.worseThan(InitializeState.API_CHECKED)) return;

var result = CommandPacketHandler.INSTANCE.handleCommandData(player, data);
var result = commandPacketHandler.handleCommandData(player, data);
if (!result.success())
{
logger.info("Packet decode failed for player %s, Rejecting...".formatted(player.getName()));
rejectPlayer(player);
return;
}

var input = result.result();
String input = result.result();

var str = input.split(" ", 2);

Expand All @@ -388,17 +394,38 @@ public void handleCommandMessage(@NotNull String cN, @NotNull Player player, byt
}
else
{
logger.warn("Unknown server command: " + baseCommand);
logger.warn("Unknown server command '%s', rejecting...".formatted(baseCommand));
rejectPlayer(player);
}
}

private final Map<UUID, PlayerSession> playerSessionMap = new ConcurrentHashMap<>();
private void handleCommandMessageLegacy(@NotNull String cN, @NotNull Player player, @NotNull byte[] data)
{
this.handleCommandInput(LegacyCommandPacketHandler.INSTANCE, cN, player, data);
}

private void handleVersionMessageLegacy(@NotNull String cN, @NotNull Player player, @NotNull byte[] data)
{
this.handleVersionInput(LegacyCommandPacketHandler.INSTANCE, cN, player, data);
}

public void handleVersionMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data)
{
this.handleVersionInput(CommandPacketHandler.INSTANCE, cN, player, data);
}

public void handleCommandMessage(@NotNull String cN, @NotNull Player player, byte @NotNull [] data)
{
this.handleCommandInput(CommandPacketHandler.INSTANCE, cN, player, data);
}

private final Map<Player, PlayerSession> playerSessionMap = new ConcurrentHashMap<>();

private PlayerSession createSession(Player player, boolean isUsingLegacyBuf)
{
var uuid = player.getUniqueId();

var cached = playerSessionMap.getOrDefault(uuid, null);
var cached = playerSessionMap.getOrDefault(player, null);

if (cached != null)
return cached;
Expand All @@ -408,14 +435,14 @@ private PlayerSession createSession(Player player, boolean isUsingLegacyBuf)
.isLegacy(isUsingLegacyBuf)
.build();

playerSessionMap.put(uuid, instance);
playerSessionMap.put(player, instance);
return instance;
}

@Nullable
public PlayerSession getSession(Player player)
{
return playerSessionMap.getOrDefault(player.getUniqueId(), null);
return playerSessionMap.getOrDefault(player, null);
}

@NotNull
Expand Down Expand Up @@ -689,14 +716,7 @@ public boolean isPlayerConnected(Player player)
@Override
public List<Player> getConnectedPlayers()
{
var list = new ObjectArrayList<Player>();
for (UUID uuid : this.playerSessionMap.keySet())
{
var player = Bukkit.getPlayer(uuid);
if (player != null) list.add(player);
}

return list;
return playerSessionMap.keySet().stream().toList();
}

//endregion Player Status/Option
Expand All @@ -714,7 +734,14 @@ private boolean sendCommand(Player player, AbstractS2CCommand<?> command, boolea

if ((!allowClient.get() || !this.clientConnected(player)) && !forceSend) return false;

this.sendPacket(MessageChannel.commandChannel, player, cmd);
var session = this.getSession(player);
var isLegacy = session == null || session.isLegacyPacketBuf;

if (!isLegacy)
this.sendPacket(MessageChannel.commandChannel, player, cmd, false);
else
this.sendPacket(MessageChannel.commandChannelLegacy, player, cmd, true);

return true;
}

Expand All @@ -737,47 +764,44 @@ public void onInitialCommand(C2SInitialCommand c2SInitialCommand)
if (session.connectionState != ConnectionState.JOINED)
session.connectionState = ConnectionState.CONNECTING;

this.waitUntilReady(player, () ->
{
//再检查一遍玩家有没有初始化完成
if (clientInitialized(player))
return;
//再检查一遍玩家有没有初始化完成
if (clientInitialized(player))
return;

var config = manager.getPlayerMeta(player);
var list = config.getUnlockedDisguiseIdentifiers();
refreshPlayerClientMorphs(list, player);
var config = manager.getPlayerMeta(player);
var list = config.getUnlockedDisguiseIdentifiers();
refreshPlayerClientMorphs(list, player);

var state = manager.getDisguiseStateFor(player);
var state = manager.getDisguiseStateFor(player);

if (state != null)
manager.refreshClientState(state);
if (state != null)
manager.refreshClientState(state);

sendCommand(player, new S2CSetSelfViewingCommand(config.showDisguiseToSelf));
sendCommand(player, new S2CSetModifyBoundingBoxCommand(modifyBoundingBoxes.get()));
sendCommand(player, new S2CSetSelfViewingCommand(config.showDisguiseToSelf));
sendCommand(player, new S2CSetModifyBoundingBoxCommand(modifyBoundingBoxes.get()));

if (player.hasPermission(CommonPermissions.DISGUISE_REVEALING))
sendCommand(player, manager.genMapCommand());
if (player.hasPermission(CommonPermissions.DISGUISE_REVEALING))
sendCommand(player, manager.genMapCommand());

//TODO: 独立客户端渲染器
if (state != null && state.getDisguiseWrapper().getBackend().dependsClientRenderer())
{
sendCommand(player, manager.genRenderSyncCommand());
//TODO: 独立客户端渲染器
if (state != null && state.getDisguiseWrapper().getBackend().dependsClientRenderer())
{
sendCommand(player, manager.genRenderSyncCommand());

var disguises = manager.getActiveDisguises();
for (DisguiseState bindingState : disguises)
{
var bindingPlayer = bindingState.getPlayer();
var disguises = manager.getActiveDisguises();
for (DisguiseState bindingState : disguises)
{
var bindingPlayer = bindingState.getPlayer();

var packet = networkingHelper.prepareMeta(bindingPlayer)
.forDisguiseState(bindingState)
.build();
var packet = networkingHelper.prepareMeta(bindingPlayer)
.forDisguiseState(bindingState)
.build();

this.sendCommand(player, packet);
}
this.sendCommand(player, packet);
}
}

session.initializeState = InitializeState.DONE;
});
session.initializeState = InitializeState.DONE;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,37 @@
package xyz.nifeather.morph.network.server.handlers;

import org.apache.commons.lang.NotImplementedException;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull;
import xyz.nifeather.morph.network.server.handlers.results.CommandHandleResult;
import xyz.nifeather.morph.network.server.handlers.results.VersionHandleResult;

public class LegacyCommandPacketHandler implements ICommandPacketHandler
import java.nio.charset.StandardCharsets;

public class LegacyCommandPacketHandler extends AbstractCommandPacketHandler
{
public static final LegacyCommandPacketHandler INSTANCE = new LegacyCommandPacketHandler();

@Override
@NotNull
public VersionHandleResult handleVersionData(Player player, byte @NotNull [] rawData)
{
throw new NotImplementedException();
try
{
var clientVersionStr = new String(rawData, StandardCharsets.UTF_8);

return VersionHandleResult.from(Integer.parseInt(clientVersionStr));
}
catch (Throwable t)
{
logger.error("Failed to decode client version from legacy buffer: " + t.getMessage());
return VersionHandleResult.fail();
}
}

@Override
@NotNull
public CommandHandleResult handleCommandData(Player player, byte @NotNull [] rawData)
{
throw new NotImplementedException();
return CommandHandleResult.from(new String(rawData, StandardCharsets.UTF_8));
}
}

0 comments on commit b4a3f12

Please sign in to comment.