mirror of
https://github.com/MikuLeaks/MikuSB.git
synced 2026-06-04 07:44:00 +00:00
enter intro cutscene
This commit is contained in:
142
GameServer/Server/Connection.cs
Normal file
142
GameServer/Server/Connection.cs
Normal file
@@ -0,0 +1,142 @@
|
||||
using MikuSB.Enums.Packet;
|
||||
using MikuSB.GameServer.Game.Player;
|
||||
using MikuSB.GameServer.Server.Packet;
|
||||
using MikuSB.TcpSharp;
|
||||
using MikuSB.Util;
|
||||
using System.Buffers;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace MikuSB.GameServer.Server;
|
||||
|
||||
public class Connection(Socket socket, IPEndPoint remote) : SocketConnection(socket, remote)
|
||||
{
|
||||
private static readonly Logger Logger = new("GameServer");
|
||||
|
||||
public PlayerInstance? Player { get; set; }
|
||||
|
||||
private static readonly HashSet<string> DummyPacketNames =
|
||||
[
|
||||
|
||||
];
|
||||
|
||||
public override async void Start()
|
||||
{
|
||||
Logger.Info($"New connection from {RemoteEndPoint}.");
|
||||
State = SessionStateEnum.WAITING_FOR_TOKEN;
|
||||
await ReceiveLoop();
|
||||
}
|
||||
|
||||
public override void Stop(bool isServerStop = false)
|
||||
{
|
||||
Player?.OnLogoutAsync();
|
||||
SocketListener.UnregisterConnection(this);
|
||||
base.Stop(isServerStop);
|
||||
}
|
||||
|
||||
public static int GetInt32(byte[] buf, int index)
|
||||
{
|
||||
int networkValue = BitConverter.ToInt32(buf, index);
|
||||
return IPAddress.NetworkToHostOrder((int)networkValue);
|
||||
}
|
||||
|
||||
protected async Task ReceiveLoop()
|
||||
{
|
||||
try
|
||||
{
|
||||
var stream = new NetworkStream(Socket, ownsSocket: false);
|
||||
|
||||
while (SocketConnected())
|
||||
{
|
||||
var decodedPacket = await new PacketCodec().ReadPacketAsync(stream, CancelToken.Token);
|
||||
|
||||
if (decodedPacket == null)
|
||||
{
|
||||
Logger.Info("Client disconnected");
|
||||
break;
|
||||
}
|
||||
|
||||
switch (decodedPacket.Framing)
|
||||
{
|
||||
case PacketFraming.FourByteLittleEndianLength:
|
||||
case PacketFraming.TwoByteBigEndianLength:
|
||||
Framing = decodedPacket.Framing;
|
||||
LogPacket("Recv", decodedPacket.CmdId, decodedPacket.Body.ToArray(),Framing);
|
||||
await HandlePacket(decodedPacket.CmdId, decodedPacket.Body.ToArray());
|
||||
break;
|
||||
|
||||
case PacketFraming.Control:
|
||||
Logger.Info("Control packet received");
|
||||
// Handle control packet if needed
|
||||
break;
|
||||
|
||||
case PacketFraming.Unknown:
|
||||
Logger.Warn("Unknown packet format received");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
Logger.Info("ReceiveLoop cancelled");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Info($"ReceiveLoop error: {ex}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
Socket.Close();
|
||||
}
|
||||
Stop();
|
||||
}
|
||||
|
||||
private async Task HandlePacket(ushort opcode, byte[] payload)
|
||||
{
|
||||
var packetName = LogMap.GetValueOrDefault(opcode);
|
||||
if (DummyPacketNames.Contains(packetName!))
|
||||
{
|
||||
await SendDummy(packetName!);
|
||||
Logger.Info($"[Dummy] Send Dummy {packetName}");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the Handler for this opcode
|
||||
var handler = HandlerManager.GetHandler(opcode);
|
||||
if (handler != null)
|
||||
{
|
||||
// Handle
|
||||
// Make sure session is ready for packets
|
||||
var state = State;
|
||||
try
|
||||
{
|
||||
await handler.OnHandle(this, payload, (ushort)DownStreamSeqNo);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Error(e.Message, e);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (ConfigManager.Config.ServerOption.EnableDebug &&
|
||||
ConfigManager.Config.ServerOption.DebugNoHandlerPacket && !IgnoreLog.Contains(opcode))
|
||||
Logger.Error($"No handler found for {packetName}({opcode})");
|
||||
|
||||
//if (ConfigManager.Config.ServerOption.AutoSendResponseWhenNoHandler)
|
||||
//{
|
||||
// await SendDummy(packetName);
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
private async Task SendDummy(string packetName)
|
||||
{
|
||||
var respName = packetName.Replace("Req", "Rsp"); // Get the response packet name
|
||||
if (respName == packetName) return; // do not send rsp when resp name = recv name
|
||||
var respOpcode = LogMap.FirstOrDefault(x => x.Value == respName).Key; // Get the response opcode
|
||||
|
||||
// Send Rsp
|
||||
await SendPacket(respOpcode);
|
||||
}
|
||||
}
|
||||
13
GameServer/Server/Listener.cs
Normal file
13
GameServer/Server/Listener.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using MikuSB.TcpSharp;
|
||||
|
||||
namespace MikuSB.GameServer.Server;
|
||||
|
||||
public class Listener : SocketListener
|
||||
{
|
||||
public static Connection? GetActiveConnection(int uid)
|
||||
{
|
||||
var con = Connections.Values.FirstOrDefault(c =>
|
||||
(c as Connection)?.Player?.Uid == uid && c.State == SessionStateEnum.ACTIVE) as Connection;
|
||||
return con;
|
||||
}
|
||||
}
|
||||
6
GameServer/Server/Packet/Handler.cs
Normal file
6
GameServer/Server/Packet/Handler.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace MikuSB.GameServer.Server.Packet;
|
||||
|
||||
public abstract class Handler
|
||||
{
|
||||
public abstract Task OnHandle(Connection connection, byte[] data, ushort SeqNo = 0);
|
||||
}
|
||||
31
GameServer/Server/Packet/HandlerManager.cs
Normal file
31
GameServer/Server/Packet/HandlerManager.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace MikuSB.GameServer.Server.Packet;
|
||||
|
||||
public static class HandlerManager
|
||||
{
|
||||
public static Dictionary<int, Handler> handlers = [];
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
var classes = Assembly.GetExecutingAssembly().GetTypes(); // Get all classes in the assembly
|
||||
foreach (var cls in classes)
|
||||
{
|
||||
var attribute = (Opcode?)Attribute.GetCustomAttribute(cls, typeof(Opcode));
|
||||
|
||||
if (attribute != null) handlers.Add(attribute.CmdId, (Handler)Activator.CreateInstance(cls)!);
|
||||
}
|
||||
}
|
||||
|
||||
public static Handler? GetHandler(int cmdId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return handlers[cmdId];
|
||||
}
|
||||
catch
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
7
GameServer/Server/Packet/Opcode.cs
Normal file
7
GameServer/Server/Packet/Opcode.cs
Normal file
@@ -0,0 +1,7 @@
|
||||
namespace MikuSB.GameServer.Server.Packet;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class Opcode(int cmdId) : Attribute
|
||||
{
|
||||
public int CmdId = cmdId;
|
||||
}
|
||||
50
GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs
Normal file
50
GameServer/Server/Packet/Recv/Login/HandlerReqLogin.cs
Normal file
@@ -0,0 +1,50 @@
|
||||
using MikuSB.Data;
|
||||
using MikuSB.Database;
|
||||
using MikuSB.Database.Account;
|
||||
using MikuSB.Database.Player;
|
||||
using MikuSB.GameServer.Game.Player;
|
||||
using MikuSB.GameServer.Server.Packet.Send.Login;
|
||||
using MikuSB.Proto;
|
||||
using MikuSB.TcpSharp;
|
||||
using MikuSB.Util;
|
||||
|
||||
namespace MikuSB.GameServer.Server.Packet.Recv.Login;
|
||||
|
||||
[Opcode(CmdIds.ReqLogin)]
|
||||
public class HandlerReqLogin : Handler
|
||||
{
|
||||
public override async Task OnHandle(Connection connection, byte[] data, ushort seqNo)
|
||||
{
|
||||
var req = ReqLogin.Parser.ParseFrom(data);
|
||||
var account = AccountData.GetAccountByUid(1);
|
||||
if (account == null)
|
||||
{
|
||||
AccountData.CreateAccount("MIKU", 0, "");
|
||||
account = AccountData.GetAccountByUid(1);
|
||||
if (account == null)
|
||||
{
|
||||
await connection.SendPacket(CmdIds.NtfLogout);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!ResourceManager.IsLoaded)
|
||||
// resource manager not loaded, return
|
||||
return;
|
||||
var prev = Listener.GetActiveConnection(account.Uid);
|
||||
if (prev != null)
|
||||
{
|
||||
await connection.SendPacket(CmdIds.NtfLogout);
|
||||
prev.Stop();
|
||||
}
|
||||
|
||||
connection.State = SessionStateEnum.WAITING_FOR_LOGIN;
|
||||
var pd = DatabaseHelper.GetInstance<PlayerGameData>(account.Uid);
|
||||
connection.Player = pd == null ? new PlayerInstance(account.Uid) : new PlayerInstance(pd);
|
||||
|
||||
connection.DebugFile = Path.Combine(ConfigManager.Config.Path.LogPath, "Debug/", $"{account.Uid}/",
|
||||
$"Debug-{DateTime.Now:yyyy-MM-dd HH-mm-ss}.log");
|
||||
await connection.Player.OnEnterGame();
|
||||
connection.Player.Connection = connection;
|
||||
await connection.SendPacket(new PacketRspLogin(connection.Player!));
|
||||
}
|
||||
}
|
||||
29
GameServer/Server/Packet/Send/Login/PacketRspLogin.cs
Normal file
29
GameServer/Server/Packet/Send/Login/PacketRspLogin.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using MikuSB.GameServer.Game.Player;
|
||||
using MikuSB.TcpSharp;
|
||||
using MikuSB.Proto;
|
||||
using MikuSB.Util.Extensions;
|
||||
|
||||
namespace MikuSB.GameServer.Server.Packet.Send.Login;
|
||||
|
||||
public class PacketRspLogin : BasePacket
|
||||
{
|
||||
public PacketRspLogin(PlayerInstance player) : base(CmdIds.RspLogin)
|
||||
{
|
||||
var proto = new RspLogin
|
||||
{
|
||||
Timestamp = (uint)Extensions.GetUnixSec(),
|
||||
WorldChannel = 1,
|
||||
AreaId = 1,
|
||||
Data = new Player
|
||||
{
|
||||
Pid = (ulong)player.Data.Uid,
|
||||
Account = player.Data.Name,
|
||||
Name = player.Data.Name,
|
||||
Level = 80
|
||||
},
|
||||
NeedRename = false
|
||||
};
|
||||
|
||||
SetData(proto);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user