Server side plugin networking

Untested port for Forge
This commit is contained in:
s809
2024-03-14 21:46:23 +05:00
parent 1f438d8f87
commit e008eb8a13
6 changed files with 58 additions and 29 deletions
@@ -11,9 +11,11 @@ import com.seibel.distanthorizons.core.network.messages.plugin.PluginHelloMessag
import com.seibel.distanthorizons.core.network.messages.plugin.ServerConnectInfoMessage;
import com.seibel.distanthorizons.core.network.plugin.PluginChannelHandler;
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
import io.netty.buffer.ByteBuf;
import org.apache.logging.log4j.LogManager;
import org.jetbrains.annotations.Nullable;
import java.util.function.Consumer;
@@ -91,7 +93,11 @@ public class ClientPluginChannelApi implements AutoCloseable
public void handlePacket(ByteBuf buffer)
{
this.channelHandler.decodeAndHandle(buffer);
this.handlePacket(null, buffer);
}
public void handlePacket(@Nullable IServerPlayerWrapper serverPlayer, ByteBuf buffer)
{
this.channelHandler.decodeAndHandle(serverPlayer, buffer);
}
@Override
@@ -36,13 +36,9 @@ import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import io.netty.buffer.ByteBuf;
import org.apache.logging.log4j.Logger;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ThreadPoolExecutor;
/**
* This holds the methods that should be called by the host mod loader (Fabric,
* Forge, etc.). Specifically server events.
@@ -182,4 +178,14 @@ public class ServerApi
}
}
public void pluginMessageReceived(IServerPlayerWrapper player, ByteBuf buffer)
{
IDhServerWorld serverWorld = SharedApi.getIDhServerWorld();
if (serverWorld instanceof DhServerWorld) // TODO add support for DhClientServerWorld's (lan worlds) as well
{
LOGGER.debug("Player " + player.getUUID() + " sent plugin message: " + buffer.toString());
((DhServerWorld) serverWorld).handlePluginMessage(player, buffer);
}
}
}
@@ -8,9 +8,9 @@ import com.seibel.distanthorizons.core.config.types.ConfigEntry;
import com.seibel.distanthorizons.core.level.DhServerLevel;
import com.seibel.distanthorizons.core.multiplayer.config.MultiplayerConfig;
import com.seibel.distanthorizons.core.multiplayer.config.MultiplayerConfigChangeListener;
import com.seibel.distanthorizons.core.network.messages.plugin.PluginHelloMessage;
import com.seibel.distanthorizons.core.network.netty.INettyConnection;
import com.seibel.distanthorizons.core.network.netty.NettyServer;
import com.seibel.distanthorizons.core.network.ScopedNetworkEventSource;
import com.seibel.distanthorizons.core.network.exceptions.InvalidLevelException;
import com.seibel.distanthorizons.core.network.messages.netty.base.AckMessage;
import com.seibel.distanthorizons.core.network.messages.netty.base.NettyCloseEvent;
@@ -19,8 +19,10 @@ import com.seibel.distanthorizons.core.network.messages.netty.session.PlayerUUID
import com.seibel.distanthorizons.core.network.messages.netty.session.RemotePlayerConfigMessage;
import com.seibel.distanthorizons.core.network.netty.TrackableNettyMessage;
import com.seibel.distanthorizons.core.network.netty.NettyMessage;
import com.seibel.distanthorizons.core.network.plugin.PluginChannelHandler;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.Nullable;
import java.io.Closeable;
@@ -34,23 +36,20 @@ public class RemotePlayerConnectionHandler implements Closeable
{
private static final ConfigEntry<Boolean> GENERATE_MULTIPLE_DIMENSIONS_CONFIG = Config.Client.Advanced.Multiplayer.ServerNetworking.generateMultipleDimensions;
private final ScopedNetworkEventSource<NettyServer, NettyMessage> eventSource;
private final NettyServer server = new NettyServer(Config.Client.Advanced.Multiplayer.ServerNetworking.serverPort.get());
private final ConcurrentHashMap<UUID, ServerPlayerState> playersByUUID = new ConcurrentHashMap<>();
private final BiMap<INettyConnection, ServerPlayerState> playersByConnection = Maps.synchronizedBiMap(HashBiMap.create());
private final MultiplayerConfigChangeListener configChangeListener = new MultiplayerConfigChangeListener(this::onConfigChanged);
public NettyServer server() { return this.eventSource.parent; }
private final PluginChannelHandler pluginChannelHandler = new PluginChannelHandler();
// TODO port change listener
public RemotePlayerConnectionHandler(NettyServer nettyServer)
{
this.eventSource = new ScopedNetworkEventSource<>(nettyServer);
this.registerNetworkHandlers();
}
public NettyServer server() { return this.server; }
private void registerNetworkHandlers()
public RemotePlayerConnectionHandler()
{
this.eventSource.registerHandler(PlayerUUIDMessage.class, playerUUIDMessage ->
//region Netty server
this.server.registerHandler(PlayerUUIDMessage.class, playerUUIDMessage ->
{
INettyConnection connection = playerUUIDMessage.getConnection();
ServerPlayerState serverPlayerState = this.playersByUUID.get(playerUUIDMessage.playerUUID);
@@ -73,13 +72,13 @@ public class RemotePlayerConnectionHandler implements Closeable
playerUUIDMessage.sendResponse(new AckMessage());
});
this.eventSource.registerHandler(RemotePlayerConfigMessage.class, this.connectedPlayersOnly((remotePlayerConfigMessage, serverPlayerState) ->
this.server.registerHandler(RemotePlayerConfigMessage.class, this.connectedPlayersOnly((remotePlayerConfigMessage, serverPlayerState) ->
{
serverPlayerState.config.clientConfig = (MultiplayerConfig) remotePlayerConfigMessage.payload;
serverPlayerState.connection.sendMessage(new RemotePlayerConfigMessage(serverPlayerState.config));
}));
this.eventSource.registerHandler(NettyCloseEvent.class, closeEvent ->
this.server.registerHandler(NettyCloseEvent.class, closeEvent ->
{
ServerPlayerState dhPlayer = this.playersByConnection.remove(closeEvent.getConnection());
if (dhPlayer != null)
@@ -87,6 +86,19 @@ public class RemotePlayerConnectionHandler implements Closeable
dhPlayer.connection = null;
}
});
//endregion
//region Plugin channel
this.pluginChannelHandler.registerHandler(PluginHelloMessage.class, msg -> {
// TODO tell to connect somewhere
int i = 0;
});
//endregion
}
public void handlePluginMessage(IServerPlayerWrapper player, ByteBuf buffer)
{
this.pluginChannelHandler.decodeAndHandle(player, buffer);
}
private void onConfigChanged()
@@ -171,7 +183,7 @@ public class RemotePlayerConnectionHandler implements Closeable
public void close()
{
this.configChangeListener.close();
this.eventSource.close();
this.pluginChannelHandler.close();
this.server().close();
}
@@ -41,7 +41,7 @@ public class PluginChannelHandler extends NetworkEventSource<PluginChannelMessag
}
public void decodeAndHandle(ByteBuf byteBuf)
public void decodeAndHandle(@Nullable IServerPlayerWrapper serverPlayer, ByteBuf byteBuf)
{
if (this.isClosed.get())
{
@@ -53,9 +53,11 @@ public class PluginChannelHandler extends NetworkEventSource<PluginChannelMessag
ArrayList<Object> messages = new ArrayList<>();
this.messageDecoder.decode(byteBuf, messages);
for (Object msg : messages)
for (Object msgObj : messages)
{
this.handleMessage((PluginChannelMessage) msg);
PluginChannelMessage msg = (PluginChannelMessage) msgObj;
msg.serverPlayer = serverPlayer;
this.handleMessage(msg);
}
}
catch (Throwable e)
@@ -73,7 +75,6 @@ public class PluginChannelHandler extends NetworkEventSource<PluginChannelMessag
{
ByteBuf buffer = PooledByteBufAllocator.DEFAULT.buffer();
this.messageEncoder.encode(message, buffer);
this.packetSender.sendPluginPacket(serverPlayer, buffer);
}
@@ -1,8 +1,9 @@
package com.seibel.distanthorizons.core.network.plugin;
import com.seibel.distanthorizons.core.network.protocol.INetworkObject;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
public abstract class PluginChannelMessage implements INetworkObject
{
// Exists only to distinguish "message" from "object"
public IServerPlayerWrapper serverPlayer;
}
@@ -19,16 +19,15 @@
package com.seibel.distanthorizons.core.world;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.file.structure.LocalSaveStructure;
import com.seibel.distanthorizons.core.level.DhServerLevel;
import com.seibel.distanthorizons.core.level.IDhLevel;
import com.seibel.distanthorizons.core.multiplayer.server.RemotePlayerConnectionHandler;
import com.seibel.distanthorizons.core.network.netty.NettyServer;
import com.seibel.distanthorizons.core.util.LodUtil;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
import java.io.File;
@@ -38,6 +37,7 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld
{
private final HashMap<IServerLevelWrapper, DhServerLevel> levels;
public final LocalSaveStructure saveStructure;
private final RemotePlayerConnectionHandler remotePlayerConnectionHandler;
@@ -52,8 +52,7 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld
this.saveStructure = new LocalSaveStructure();
this.levels = new HashMap<>();
NettyServer nettyServer = new NettyServer(Config.Client.Advanced.Multiplayer.ServerNetworking.serverPort.get());
this.remotePlayerConnectionHandler = new RemotePlayerConnectionHandler(nettyServer);
this.remotePlayerConnectionHandler = new RemotePlayerConnectionHandler();
LOGGER.info("Started "+DhServerWorld.class.getSimpleName()+" of type "+this.environment);
}
@@ -79,6 +78,10 @@ public class DhServerWorld extends AbstractDhWorld implements IDhServerWorld
this.getLevel(dest).addPlayer(player);
this.getLevel(origin).removePlayer(player);
}
public void handlePluginMessage(IServerPlayerWrapper player, ByteBuf buffer)
{
this.remotePlayerConnectionHandler.handlePluginMessage(player, buffer);
}
@Override
public DhServerLevel getOrLoadLevel(@NotNull ILevelWrapper wrapper)