SunnyCase 8 лет назад
Родитель
Сommit
e64c5a11c5

+ 19 - 8
src/MineCase.Gateway/Network/ClientSession.cs

@@ -28,7 +28,7 @@ namespace MineCase.Gateway.Network
             _tcpClient = tcpClient;
             _grainFactory = grainFactory;
             _outcomingPacketObserver = new OutcomingPacketObserver(this);
-            _outcomingPacketDispatcher = new ActionBlock<UncompressedPacket>(SendOutcommingPacket);
+            _outcomingPacketDispatcher = new ActionBlock<UncompressedPacket>(SendOutcomingPacket);
         }
 
         public async Task Startup(CancellationToken cancellationToken)
@@ -42,7 +42,7 @@ namespace MineCase.Gateway.Network
                     while (!cancellationToken.IsCancellationRequested &&
                         !_outcomingPacketDispatcher.Completion.IsCompleted)
                     {
-                        await DispatchIncommingPacket();
+                        await DispatchIncomingPacket();
                     }
                 }
                 catch (EndOfStreamException)
@@ -52,7 +52,13 @@ namespace MineCase.Gateway.Network
             }
         }
 
-        private async Task DispatchIncommingPacket()
+        private void OnClosed()
+        {
+            _outcomingPacketDispatcher.Complete();
+            _tcpClient.Client.Shutdown(SocketShutdown.Send);
+        }
+
+        private async Task DispatchIncomingPacket()
         {
             UncompressedPacket packet;
             if (_useCompression)
@@ -64,10 +70,10 @@ namespace MineCase.Gateway.Network
             {
                 packet = await UncompressedPacket.DeserializeAsync(_remoteStream);
             }
-            await DispatchIncommingPacket(packet);
+            await DispatchIncomingPacket(packet);
         }
 
-        private async Task SendOutcommingPacket(UncompressedPacket packet)
+        private async Task SendOutcomingPacket(UncompressedPacket packet)
         {
             if (_useCompression)
             {
@@ -80,13 +86,13 @@ namespace MineCase.Gateway.Network
             }
         }
 
-        private async Task DispatchIncommingPacket(UncompressedPacket packet)
+        private async Task DispatchIncomingPacket(UncompressedPacket packet)
         {
             var router = _grainFactory.GetGrain<IPacketRouter>(_sessionId);
             await router.SendPacket(packet);
         }
 
-        private async void DispatchOutcommingPacket(UncompressedPacket packet)
+        private async void DispatchOutcomingPacket(UncompressedPacket packet)
         {
             try
             {
@@ -108,9 +114,14 @@ namespace MineCase.Gateway.Network
                 _session = session;
             }
 
+            public void OnClosed()
+            {
+                _session.OnClosed();
+            }
+
             public void ReceivePacket(UncompressedPacket packet)
             {
-                _session.DispatchOutcommingPacket(packet);
+                _session.DispatchOutcomingPacket(packet);
             }
         }
 

+ 39 - 0
src/MineCase.Protocol/Protocol/Login/LoginStart.cs

@@ -0,0 +1,39 @@
+using MineCase.Serialization;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace MineCase.Protocol.Login
+{
+    [Packet(0x00)]
+    public sealed class LoginStart
+    {
+        [SerializeAs(DataType.String)]
+        public string Name;
+
+        public static LoginStart Deserialize(BinaryReader br)
+        {
+            return new LoginStart
+            {
+                Name = br.ReadAsString(),
+            };
+        }
+    }
+
+    [Packet(0x02)]
+    public sealed class LoginSuccess : ISerializablePacket
+    {
+        [SerializeAs(DataType.String)]
+        public string UUID;
+
+        [SerializeAs(DataType.String)]
+        public string Username;
+
+        public void Serialize(BinaryWriter bw)
+        {
+            bw.WriteAsString(UUID);
+            bw.WriteAsString(Username);
+        }
+    }
+}

+ 7 - 0
src/MineCase.Server.Grains/Network/ClientboundPaketSinkGrain.cs

@@ -62,5 +62,12 @@ namespace MineCase.Server.Network
             _subsManager.Notify(n => n.ReceivePacket(packet));
             return Task.CompletedTask;
         }
+
+        public Task Close()
+        {
+            _subsManager.Notify(n => n.OnClosed());
+            DeactivateOnIdle();
+            return Task.CompletedTask;
+        }
     }
 }

+ 37 - 0
src/MineCase.Server.Grains/Network/Login/LoginFlowGrain.cs

@@ -0,0 +1,37 @@
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using MineCase.Protocol.Login;
+using System.Threading.Tasks;
+using MineCase.Server.Player;
+
+namespace MineCase.Server.Network.Login
+{
+    class LoginFlowGrain : Grain, ILoginFlow
+    {
+        private bool _useAuthentication = false;
+
+        public async Task DispatchPacket(LoginStart packet)
+        {
+            if (_useAuthentication)
+                throw new NotImplementedException();
+            else
+            {
+                var uuid = await GrainFactory.GetGrain<INonAuthenticatedPlayer>(packet.Name).GetUUID();
+                await SendLoginSuccess(packet.Name, uuid);
+            }
+        }
+
+        private async Task SendLoginSuccess(string userName, Guid uuid)
+        {
+            var sink = GrainFactory.GetGrain<IClientboundPaketSink>(this.GetPrimaryKey());
+            await GrainFactory.GetGrain<IPacketRouter>(this.GetPrimaryKey()).Play();
+            await sink.SendPacket(new LoginSuccess
+            {
+                Username = userName,
+                UUID = uuid.ToString()
+            });
+        }
+    }
+}

+ 15 - 0
src/MineCase.Server.Grains/Network/Login/LoginModule.cs

@@ -0,0 +1,15 @@
+using Autofac;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Server.Network.Login
+{
+    class LoginModule : Module
+    {
+        protected override void Load(ContainerBuilder builder)
+        {
+            builder.RegisterType<LoginFlowGrain>();
+        }
+    }
+}

+ 37 - 0
src/MineCase.Server.Grains/Network/PacketRouterGrain.Login.cs

@@ -0,0 +1,37 @@
+using MineCase.Protocol;
+using MineCase.Protocol.Login;
+using MineCase.Server.Network.Login;
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Server.Network
+{
+    partial class PacketRouterGrain
+    {
+        private object DeserializeLoginPacket(ref UncompressedPacket packet)
+        {
+            using (var br = new BinaryReader(new MemoryStream(packet.Data)))
+            {
+                switch (packet.PacketId)
+                {
+                    // Login Start
+                    case 0x00:
+                        return LoginStart.Deserialize(br);
+                    default:
+                        throw new InvalidDataException($"Unrecognizable packet id: 0x{packet.PacketId:X}.");
+                }
+            }
+        }
+
+        private Task DispatchPacket(LoginStart packet)
+        {
+            var requestGrain = GrainFactory.GetGrain<ILoginFlow>(this.GetPrimaryKey());
+            requestGrain.DispatchPacket(packet).Ignore();
+            return Task.CompletedTask;
+        }
+    }
+}

+ 14 - 0
src/MineCase.Server.Grains/Network/PacketRouterGrain.cs

@@ -26,6 +26,7 @@ namespace MineCase.Server.Network
                     innerPacket = DeserializeStatusPacket(ref packet);
                     break;
                 case SessionState.Login:
+                    innerPacket = DeserializeLoginPacket(ref packet);
                     break;
                 case SessionState.Play:
                     break;
@@ -37,11 +38,24 @@ namespace MineCase.Server.Network
             await DispatchPacket(innerPacket);
         }
 
+        public async Task Close()
+        {
+            _state = SessionState.Closed;
+            await GrainFactory.GetGrain<IClientboundPaketSink>(this.GetPrimaryKey()).Close();
+            DeactivateOnIdle();
+        }
+
         private Task DispatchPacket(object packet)
         {
             throw new NotImplementedException();
         }
 
+        public Task Play()
+        {
+            _state = SessionState.Play;
+            return Task.CompletedTask;
+        }
+
         public enum SessionState
         {
             Handshaking,

+ 2 - 4
src/MineCase.Server.Grains/Network/Status/PingGrain.cs

@@ -14,10 +14,8 @@ namespace MineCase.Server.Network.Status
     {
         public async Task DispatchPacket(Guid sessionId, Ping packet)
         {
-            await GrainFactory.GetGrain<IClientboundPaketSink>(sessionId).SendPacket(new Pong
-            {
-                Payload = packet.Payload
-            });
+            await GrainFactory.GetGrain<IClientboundPaketSink>(sessionId).SendPacket(new Pong { Payload = packet.Payload });
+            GrainFactory.GetGrain<IPacketRouter>(sessionId).Close().Ignore();
         }
     }
 }

+ 24 - 0
src/MineCase.Server.Grains/Player/NonAuthenticatedPlayerGrain.cs

@@ -0,0 +1,24 @@
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Server.Player
+{
+    class NonAuthenticatedPlayerGrain : Grain, INonAuthenticatedPlayer
+    {
+        private Guid _uuid;
+
+        public override Task OnActivateAsync()
+        {
+            _uuid = Guid.NewGuid();
+            return base.OnActivateAsync();
+        }
+
+        public Task<Guid> GetUUID()
+        {
+            return Task.FromResult(_uuid);
+        }
+    }
+}

+ 15 - 0
src/MineCase.Server.Grains/Player/PlayerModule.cs

@@ -0,0 +1,15 @@
+using Autofac;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Server.Player
+{
+    class PlayerModule : Module
+    {
+        protected override void Load(ContainerBuilder builder)
+        {
+            builder.RegisterType<NonAuthenticatedPlayerGrain>();
+        }
+    }
+}

+ 23 - 0
src/MineCase.Server.Grains/World/WorldAccessorGrain.cs

@@ -0,0 +1,23 @@
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Server.World
+{
+    class WorldAccessorGrain : Grain, IWorldAccessor
+    {
+        private const string _defaultWorldName = "defaultWorld";
+
+        public Task<IWorld> GetDefaultWorld()
+        {
+            return Task.FromResult(GrainFactory.GetGrain<IWorld>(_defaultWorldName));
+        }
+
+        public async Task<IWorld> GetWorld(string name)
+        {
+            return null;
+        }
+    }
+}

+ 11 - 0
src/MineCase.Server.Grains/World/WorldGrain.cs

@@ -0,0 +1,11 @@
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Server.World
+{
+    class WorldGrain : Grain, IWorld
+    {
+    }
+}

+ 16 - 0
src/MineCase.Server.Grains/World/WorldModule.cs

@@ -0,0 +1,16 @@
+using Autofac;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Server.World
+{
+    class WorldModule : Module
+    {
+        protected override void Load(ContainerBuilder builder)
+        {
+            builder.RegisterType<WorldGrain>();
+            builder.RegisterType<WorldAccessorGrain>();
+        }
+    }
+}

+ 1 - 0
src/MineCase.Server.Interfaces/Network/IClientboundPacketObserver.cs

@@ -9,5 +9,6 @@ namespace MineCase.Server.Network
     public interface IClientboundPacketObserver : IGrainObserver
     {
         void ReceivePacket(UncompressedPacket packet);
+        void OnClosed();
     }
 }

+ 1 - 0
src/MineCase.Server.Interfaces/Network/IClientboundPaketSink.cs

@@ -14,5 +14,6 @@ namespace MineCase.Server.Network
         Task UnSubscribe(IClientboundPacketObserver observer);
         
         Task SendPacket(ISerializablePacket packet);
+        Task Close();
     }
 }

+ 2 - 0
src/MineCase.Server.Interfaces/Network/IPacketRouter.cs

@@ -10,5 +10,7 @@ namespace MineCase.Server.Network
     public interface IPacketRouter : IGrainWithGuidKey
     {
         Task SendPacket(UncompressedPacket packet);
+        Task Close();
+        Task Play();
     }
 }

+ 14 - 0
src/MineCase.Server.Interfaces/Network/Login/ILoginFlow.cs

@@ -0,0 +1,14 @@
+using MineCase.Protocol.Login;
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Server.Network.Login
+{
+    public interface ILoginFlow : IGrainWithGuidKey
+    {
+        Task DispatchPacket(LoginStart packet);
+    }
+}

+ 13 - 0
src/MineCase.Server.Interfaces/Player/INonAuthenticatedPlayer.cs

@@ -0,0 +1,13 @@
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Server.Player
+{
+    public interface INonAuthenticatedPlayer : IGrainWithStringKey
+    {
+        Task<Guid> GetUUID();
+    }
+}

+ 11 - 0
src/MineCase.Server.Interfaces/World/IWorld.cs

@@ -0,0 +1,11 @@
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Server.World
+{
+    public interface IWorld : IGrainWithStringKey
+    {
+    }
+}

+ 14 - 0
src/MineCase.Server.Interfaces/World/IWorldAccessor.cs

@@ -0,0 +1,14 @@
+using Orleans;
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Server.World
+{
+    public interface IWorldAccessor : IGrainWithIntegerKey
+    {
+        Task<IWorld> GetDefaultWorld();
+        Task<IWorld> GetWorld(string name);
+    }
+}