Преглед на файлове

Update packages and apply source genenerator (#141)

* Update to net5.0

* Use generic host in server

* Add code gen

* Add serialize codegen

* Complete protocol refactor

* bug fix

* Move config loader

* Update package sources

* Update set compression

* Add azure pipelines

* Set up CI with Azure Pipelines

[skip ci]

* Update azure-pipelines.yml for Azure Pipelines

* Replace multiple frameworks

Co-authored-by: JasonWang <[email protected]>
sunnycase преди 5 години
родител
ревизия
87863ae1ea
променени са 100 файла, в които са добавени 660 реда и са изтрити 1266 реда
  1. 0 3
      NuGet.config
  2. 59 0
      azure-pipelines.yml
  3. 5 0
      global.json
  4. 1 1
      src/MineCase.Algorithm/Game/Entity/Ai/Action/CreatureAiActionLookAtPlayer.cs
  5. 2 2
      src/MineCase.Algorithm/MineCase.Algorithm.csproj
  6. 80 80
      src/MineCase.Algorithm/Noise/PerlinNoise.cs
  7. 0 1
      src/MineCase.Core/Block/BlockStateExtensions.cs
  8. 1 1
      src/MineCase.Core/Block/BlockType.cs
  9. 2 7
      src/MineCase.Core/MineCase.Core.csproj
  10. 11 11
      src/MineCase.Core/World/ChunkColumnCompactStorage.cs
  11. 0 3
      src/MineCase.Core/World/GameTickArgs.cs
  12. 4 4
      src/MineCase.Engine/MineCase.Server.Engine.csproj
  13. 29 7
      src/MineCase.Gateway/AppBootstrapper.cs
  14. 9 11
      src/MineCase.Gateway/MineCase.Gateway.csproj
  15. 27 29
      src/MineCase.Gateway/Network/ClientSession.cs
  16. 21 18
      src/MineCase.Gateway/Network/ConnectionRouter.cs
  17. 10 73
      src/MineCase.Gateway/Program.cs
  18. 2 3
      src/MineCase.Nbt/MineCase.Nbt.csproj
  19. 6 7
      src/MineCase.Protocol/MineCase.Protocol.csproj
  20. 2 23
      src/MineCase.Protocol/Protocol/Handshaking/Handshake.cs
  21. 8 57
      src/MineCase.Protocol/Protocol/Login/LoginEncryption.cs
  22. 7 54
      src/MineCase.Protocol/Protocol/Login/LoginStart.cs
  23. 3 18
      src/MineCase.Protocol/Protocol/Login/SetCompression.cs
  24. 3 7
      src/MineCase.Protocol/Protocol/Packet.cs
  25. 12 5
      src/MineCase.Protocol/Protocol/PacketCompress.cs
  26. 20 0
      src/MineCase.Protocol/Protocol/PacketDeserializer.cs
  27. 2 12
      src/MineCase.Protocol/Protocol/Play/Animation.cs
  28. 2 11
      src/MineCase.Protocol/Protocol/Play/BlockBreakAnimation.cs
  29. 2 10
      src/MineCase.Protocol/Protocol/Play/BlockChange.cs
  30. 4 22
      src/MineCase.Protocol/Protocol/Play/ChatMessage.cs
  31. 12 8
      src/MineCase.Protocol/Protocol/Play/ChunkData.cs
  32. 2 17
      src/MineCase.Protocol/Protocol/Play/ClickWindow.cs
  33. 2 17
      src/MineCase.Protocol/Protocol/Play/ClientSettings.cs
  34. 2 12
      src/MineCase.Protocol/Protocol/Play/ClientboundAnimation.cs
  35. 4 21
      src/MineCase.Protocol/Protocol/Play/CloseWindow.cs
  36. 2 11
      src/MineCase.Protocol/Protocol/Play/CollectItem.cs
  37. 4 25
      src/MineCase.Protocol/Protocol/Play/ConfirmTransaction.cs
  38. 3 9
      src/MineCase.Protocol/Protocol/Play/DeclareCommands.cs
  39. 3 12
      src/MineCase.Protocol/Protocol/Play/DestroyEntities.cs
  40. 2 9
      src/MineCase.Protocol/Protocol/Play/Entity.cs
  41. 2 11
      src/MineCase.Protocol/Protocol/Play/EntityAction.cs
  42. 3 11
      src/MineCase.Protocol/Protocol/Play/EntityHeadLook.cs
  43. 4 14
      src/MineCase.Protocol/Protocol/Play/EntityLook.cs
  44. 4 31
      src/MineCase.Protocol/Protocol/Play/EntityLookAndRelativeMove.cs
  45. 6 4
      src/MineCase.Protocol/Protocol/Play/EntityMetadata.cs
  46. 2 13
      src/MineCase.Protocol/Protocol/Play/EntityRelativeMove.cs
  47. 4 17
      src/MineCase.Protocol/Protocol/Play/EntityTeleport.cs
  48. 2 12
      src/MineCase.Protocol/Protocol/Play/HeldItemChange.cs
  49. 2 17
      src/MineCase.Protocol/Protocol/Play/JoinGame.cs
  50. 4 21
      src/MineCase.Protocol/Protocol/Play/KeepAlive.cs
  51. 6 4
      src/MineCase.Protocol/Protocol/Play/OpenWindow.cs
  52. 2 17
      src/MineCase.Protocol/Protocol/Play/PlayerBlockPlacement.cs
  53. 2 11
      src/MineCase.Protocol/Protocol/Play/PlayerDigging.cs
  54. 16 16
      src/MineCase.Protocol/Protocol/Play/PlayerInfo.cs
  55. 2 14
      src/MineCase.Protocol/Protocol/Play/PlayerLook.cs
  56. 2 9
      src/MineCase.Protocol/Protocol/Play/PlayerOnGround.cs
  57. 2 15
      src/MineCase.Protocol/Protocol/Play/PlayerPosition.cs
  58. 2 13
      src/MineCase.Protocol/Protocol/Play/PluginMessage.cs
  59. 4 32
      src/MineCase.Protocol/Protocol/Play/PositionAndLook.cs
  60. 2 13
      src/MineCase.Protocol/Protocol/Play/PrepareCraftingGrid.cs
  61. 2 23
      src/MineCase.Protocol/Protocol/Play/Respawn.cs
  62. 2 11
      src/MineCase.Protocol/Protocol/Play/SetExperience.cs
  63. 2 11
      src/MineCase.Protocol/Protocol/Play/SetSlot.cs
  64. 5 24
      src/MineCase.Protocol/Protocol/Play/SpawnMob.cs
  65. 4 22
      src/MineCase.Protocol/Protocol/Play/SpawnObject.cs
  66. 2 15
      src/MineCase.Protocol/Protocol/Play/SpawnPlayer.cs
  67. 2 12
      src/MineCase.Protocol/Protocol/Play/TeleportConfirm.cs
  68. 2 10
      src/MineCase.Protocol/Protocol/Play/TimeUpdate.cs
  69. 2 10
      src/MineCase.Protocol/Protocol/Play/UnloadChunk.cs
  70. 2 11
      src/MineCase.Protocol/Protocol/Play/UpdateHealth.cs
  71. 2 19
      src/MineCase.Protocol/Protocol/Play/UpdateViewPosition.cs
  72. 15 17
      src/MineCase.Protocol/Protocol/Play/UseEntity.cs
  73. 2 12
      src/MineCase.Protocol/Protocol/Play/UseItem.cs
  74. 3 13
      src/MineCase.Protocol/Protocol/Play/WindowItems.cs
  75. 2 11
      src/MineCase.Protocol/Protocol/Play/WindowProperty.cs
  76. 2 0
      src/MineCase.Protocol/Protocol/Protocol.cs
  77. 4 34
      src/MineCase.Protocol/Protocol/Status/Ping.cs
  78. 4 30
      src/MineCase.Protocol/Protocol/Status/Request.cs
  79. 13 3
      src/MineCase.Protocol/Serialization/BinaryWriterExtensions.cs
  80. 21 0
      src/MineCase.Protocol/Serialization/GenerateSerializerAttribute.cs
  81. 4 0
      src/MineCase.Protocol/Serialization/SerializeAsAttribute.cs
  82. 76 18
      src/MineCase.Protocol/Serialization/SpanReader.cs
  83. 2 2
      src/MineCase.Serialization/MineCase.Serialization.csproj
  84. 1 1
      src/MineCase.Server.Grains/Components/AddressByPartitionKeyComponent.cs
  85. 3 3
      src/MineCase.Server.Grains/Components/GameTickComponent.cs
  86. 3 3
      src/MineCase.Server.Grains/Game/BlockEntities/Components/ChestComponent.cs
  87. 4 4
      src/MineCase.Server.Grains/Game/Blocks/ChestBlockHandler.cs
  88. 5 5
      src/MineCase.Server.Grains/Game/Entities/Components/ActiveWorldPartitionComponent.cs
  89. 3 3
      src/MineCase.Server.Grains/Game/Entities/Components/BlockPlacementComponent.cs
  90. 3 3
      src/MineCase.Server.Grains/Game/Entities/Components/ColliderComponent.cs
  91. 1 1
      src/MineCase.Server.Grains/Game/Entities/Components/DiggingComponent.cs
  92. 3 3
      src/MineCase.Server.Grains/Game/Entities/Components/DiscoveryRegisterComponent.cs
  93. 1 1
      src/MineCase.Server.Grains/Game/Entities/Components/EntityAiComponent.cs
  94. 3 3
      src/MineCase.Server.Grains/Game/Entities/Components/HeldItemComponent.cs
  95. 1 1
      src/MineCase.Server.Grains/Game/Entities/Components/SlotContainerComponent.cs
  96. 2 2
      src/MineCase.Server.Grains/Game/Entities/Components/StandaloneHeldItemComponent.cs
  97. 2 2
      src/MineCase.Server.Grains/Game/Entities/Components/SyncPlayerStateComponent.cs
  98. 1 1
      src/MineCase.Server.Grains/Game/Items/ChestItemHandler.cs
  99. 1 1
      src/MineCase.Server.Grains/Game/Windows/InventoryWindowGrain.cs
  100. 5 5
      src/MineCase.Server.Grains/Game/Windows/SlotAreas/SlotArea.cs

+ 0 - 3
NuGet.config

@@ -5,11 +5,8 @@
   <packageSources>
     <clear />
     <add key="moeathome" value="https://www.myget.org/F/moeathome-public/api/v3/index.json" />
-    <add key="orleans-ci" value="https://dotnet.myget.org/F/orleans-ci/api/v3/index.json" />
     <add key="corefxlab" value="https://dotnet.myget.org/F/dotnet-corefxlab/api/v3/index.json" />
     <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
-    <add key="dotnet-core" value="https://dotnet.myget.org/F/dotnet-core/api/v3/index.json" />
-    <add key="imageSharp" value="https://www.myget.org/F/imagesharp/api/v3/index.json" />
   </packageSources>
   <config>
     <add key="repositoryPath" value="..\packages" />

+ 59 - 0
azure-pipelines.yml

@@ -0,0 +1,59 @@
+# Starter pipeline
+# Start with a minimal pipeline that you can customize to build and deploy your code.
+# Add steps that build, run tests, deploy, and more:
+# https://aka.ms/yaml
+
+trigger:
+  branches:
+    include:
+    - '*'
+
+jobs:
+- job: Linux
+  timeoutInMinutes: 0
+  pool:
+    vmImage: 'ubuntu-18.04'
+
+  variables:
+    buildConfiguration: 'Release'
+
+  steps:
+  - checkout: self
+    submodules: true
+
+  - task: UseDotNet@2
+    displayName: 'Install .NET Core SDK'
+    inputs:
+      version: '5.0.100-preview.4.20258.7' 
+      includePreviewVersions: true # Required for preview versions
+
+  - task: DotNetCoreCLI@2
+    displayName: Build
+    inputs:
+      command: 'build'
+      projects: |
+        src/MineCase.sln
+        tests/MineCase.Tests.sln
+      arguments: '--configuration $(buildConfiguration)'
+
+  - task: DotNetCoreCLI@2
+    displayName: Test
+    inputs:
+      command: 'test'
+      projects: 'tests/MineCase.Tests.sln'
+      arguments: '--configuration $(buildConfiguration)'
+    
+  - task: DotNetCoreCLI@2
+    displayName: 'Publish'
+    inputs:
+      command: 'publish'
+      publishWebProjects: false
+      projects: |
+        src/MineCase.Server/MineCase.Server.csproj
+        src/MineCase.Gateway/MineCase.Gateway.csproj
+      arguments: '--configuration $(BuildConfiguration) --output $(Build.ArtifactStagingDirectory)'
+
+  - task: PublishBuildArtifacts@1
+    inputs:
+      pathToPublish: $(Build.ArtifactStagingDirectory)
+      artifactName: MineCase

+ 5 - 0
global.json

@@ -0,0 +1,5 @@
+{
+  "sdk": {
+    "version": "5.0.100-preview.4.20258.7"
+  }
+}

+ 1 - 1
src/MineCase.Algorithm/Game/Entity/Ai/Action/CreatureAiActionLookAtPlayer.cs

@@ -42,7 +42,7 @@ namespace MineCase.Server.World.EntitySpawner.Ai.Action
             */
         }
 
-        public static (byte, byte) VectorToYawAndPitch(Vector3 from, Vector3 to)
+        public static (byte Yaw, byte Pitch) VectorToYawAndPitch(Vector3 from, Vector3 to)
         {
             Vector3 v = to - from;
             v = Vector3.Normalize(v);

+ 2 - 2
src/MineCase.Algorithm/MineCase.Algorithm.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFrameworks>net5.0</TargetFrameworks>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <CodeAnalysisRuleSet>../../build/Analyzers.ruleset</CodeAnalysisRuleSet>
     <Configurations>Debug;Release;Appveyor;TravisCI</Configurations>
@@ -10,7 +10,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164" PrivateAssets="All" />
     <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
     <PackageReference Include="Stateless" Version="4.4.0" />
   </ItemGroup>

+ 80 - 80
src/MineCase.Algorithm/Noise/PerlinNoise.cs

@@ -4,12 +4,12 @@ using System.Numerics;
 namespace MineCase.Algorithm.Noise
 {
     /// <summary>
-    /// Implementation for Improved Perlin Noise (http://mrl.nyu.edu/~perlin/noise/)
+    /// Implementation for Improved Perlin Noise (http://mrl.nyu.edu/~perlin/noise/).
     /// </summary>
     public class PerlinNoise : INoise
     {
         /// <summary>
-        /// Permutation
+        /// Permutation.
         /// </summary>
         private readonly byte[] _p = new byte[512];
 
@@ -30,36 +30,36 @@ namespace MineCase.Algorithm.Noise
             var ycoord = Split(y);
             var zcoord = Split(z);
 
-            var u = Fade(xcoord.remainder);
-            var v = Fade(ycoord.remainder);
-            var w = Fade(zcoord.remainder);
-
-            int a = _p[xcoord.integer];
-            int b = _p[xcoord.integer + 1];
-            int aa = _p[a + ycoord.integer];
-            int ab = _p[a + ycoord.integer + 1];
-            int ba = _p[b + ycoord.integer];
-            int bb = _p[b + ycoord.integer + 1];
-
-            int aaa = _p[aa + zcoord.integer];
-            int aba = _p[ab + zcoord.integer];
-            int aab = _p[aa + zcoord.integer + 1];
-            int abb = _p[ab + zcoord.integer + 1];
-            int baa = _p[ba + zcoord.integer];
-            int bba = _p[bb + zcoord.integer];
-            int bab = _p[ba + zcoord.integer + 1];
-            int bbb = _p[bb + zcoord.integer + 1];
+            var u = Fade(xcoord.Remainder);
+            var v = Fade(ycoord.Remainder);
+            var w = Fade(zcoord.Remainder);
+
+            int a = _p[xcoord.Integer];
+            int b = _p[xcoord.Integer + 1];
+            int aa = _p[a + ycoord.Integer];
+            int ab = _p[a + ycoord.Integer + 1];
+            int ba = _p[b + ycoord.Integer];
+            int bb = _p[b + ycoord.Integer + 1];
+
+            int aaa = _p[aa + zcoord.Integer];
+            int aba = _p[ab + zcoord.Integer];
+            int aab = _p[aa + zcoord.Integer + 1];
+            int abb = _p[ab + zcoord.Integer + 1];
+            int baa = _p[ba + zcoord.Integer];
+            int bba = _p[bb + zcoord.Integer];
+            int bab = _p[ba + zcoord.Integer + 1];
+            int bbb = _p[bb + zcoord.Integer + 1];
 
             var xa = new Vector4(
-                Grad(aaa, xcoord.remainder, ycoord.remainder, zcoord.remainder),
-                Grad(aba, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder),
-                Grad(aab, xcoord.remainder, ycoord.remainder, zcoord.remainder - 1),
-                Grad(abb, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder - 1));
+                Grad(aaa, xcoord.Remainder, ycoord.Remainder, zcoord.Remainder),
+                Grad(aba, xcoord.Remainder, ycoord.Remainder - 1, zcoord.Remainder),
+                Grad(aab, xcoord.Remainder, ycoord.Remainder, zcoord.Remainder - 1),
+                Grad(abb, xcoord.Remainder, ycoord.Remainder - 1, zcoord.Remainder - 1));
             var xb = new Vector4(
-                Grad(baa, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder),
-                Grad(bba, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder),
-                Grad(bab, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder - 1),
-                Grad(bbb, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder - 1));
+                Grad(baa, xcoord.Remainder - 1, ycoord.Remainder, zcoord.Remainder),
+                Grad(bba, xcoord.Remainder - 1, ycoord.Remainder - 1, zcoord.Remainder),
+                Grad(bab, xcoord.Remainder - 1, ycoord.Remainder, zcoord.Remainder - 1),
+                Grad(bbb, xcoord.Remainder - 1, ycoord.Remainder - 1, zcoord.Remainder - 1));
             var xl = Vector4.Lerp(xa, xb, u);
             var ya = new Vector2(xl.X, xl.Z);
             var yb = new Vector2(xl.Y, xl.W);
@@ -78,45 +78,45 @@ namespace MineCase.Algorithm.Noise
             {
                 var xOffset = offset.X + x * scale.X;
                 var xcoord = Split(xOffset);
-                var u = Fade(xcoord.remainder);
+                var u = Fade(xcoord.Remainder);
 
-                int a = _p[xcoord.integer];
-                int b = _p[xcoord.integer + 1];
+                int a = _p[xcoord.Integer];
+                int b = _p[xcoord.Integer + 1];
                 for (int y = 0; y < yExtent; y++)
                 {
                     var yOffset = offset.Y + y * scale.Y;
                     var ycoord = Split(yOffset);
-                    var v = Fade(ycoord.remainder);
+                    var v = Fade(ycoord.Remainder);
 
-                    int aa = _p[a + ycoord.integer];
-                    int ab = _p[a + ycoord.integer + 1];
-                    int ba = _p[b + ycoord.integer];
-                    int bb = _p[b + ycoord.integer + 1];
+                    int aa = _p[a + ycoord.Integer];
+                    int ab = _p[a + ycoord.Integer + 1];
+                    int ba = _p[b + ycoord.Integer];
+                    int bb = _p[b + ycoord.Integer + 1];
                     for (int z = 0; z < zExtent; z++)
                     {
                         var zOffset = offset.Z + z * scale.Z;
                         var zcoord = Split(zOffset);
-                        var w = Fade(zcoord.remainder);
+                        var w = Fade(zcoord.Remainder);
 
-                        int aaa = _p[aa + zcoord.integer];
-                        int aba = _p[ab + zcoord.integer];
-                        int aab = _p[aa + zcoord.integer + 1];
-                        int abb = _p[ab + zcoord.integer + 1];
-                        int baa = _p[ba + zcoord.integer];
-                        int bba = _p[bb + zcoord.integer];
-                        int bab = _p[ba + zcoord.integer + 1];
-                        int bbb = _p[bb + zcoord.integer + 1];
+                        int aaa = _p[aa + zcoord.Integer];
+                        int aba = _p[ab + zcoord.Integer];
+                        int aab = _p[aa + zcoord.Integer + 1];
+                        int abb = _p[ab + zcoord.Integer + 1];
+                        int baa = _p[ba + zcoord.Integer];
+                        int bba = _p[bb + zcoord.Integer];
+                        int bab = _p[ba + zcoord.Integer + 1];
+                        int bbb = _p[bb + zcoord.Integer + 1];
 
                         var xa = new Vector4(
-                            Grad(aaa, xcoord.remainder, ycoord.remainder, zcoord.remainder),
-                            Grad(aba, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder),
-                            Grad(aab, xcoord.remainder, ycoord.remainder, zcoord.remainder - 1),
-                            Grad(abb, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder - 1));
+                            Grad(aaa, xcoord.Remainder, ycoord.Remainder, zcoord.Remainder),
+                            Grad(aba, xcoord.Remainder, ycoord.Remainder - 1, zcoord.Remainder),
+                            Grad(aab, xcoord.Remainder, ycoord.Remainder, zcoord.Remainder - 1),
+                            Grad(abb, xcoord.Remainder, ycoord.Remainder - 1, zcoord.Remainder - 1));
                         var xb = new Vector4(
-                            Grad(baa, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder),
-                            Grad(bba, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder),
-                            Grad(bab, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder - 1),
-                            Grad(bbb, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder - 1));
+                            Grad(baa, xcoord.Remainder - 1, ycoord.Remainder, zcoord.Remainder),
+                            Grad(bba, xcoord.Remainder - 1, ycoord.Remainder - 1, zcoord.Remainder),
+                            Grad(bab, xcoord.Remainder - 1, ycoord.Remainder, zcoord.Remainder - 1),
+                            Grad(bbb, xcoord.Remainder - 1, ycoord.Remainder - 1, zcoord.Remainder - 1));
                         var xl = Vector4.Lerp(xa, xb, u);
                         var ya = new Vector2(xl.X, xl.Z);
                         var yb = new Vector2(xl.Y, xl.W);
@@ -138,45 +138,45 @@ namespace MineCase.Algorithm.Noise
             {
                 var xOffset = offset.X + x * scale.X;
                 var xcoord = Split(xOffset);
-                var u = Fade(xcoord.remainder);
+                var u = Fade(xcoord.Remainder);
 
-                int a = _p[xcoord.integer];
-                int b = _p[xcoord.integer + 1];
+                int a = _p[xcoord.Integer];
+                int b = _p[xcoord.Integer + 1];
                 for (int y = 0; y < yExtent; y++)
                 {
                     var yOffset = offset.Y + y * scale.Y;
                     var ycoord = Split(yOffset);
-                    var v = Fade(ycoord.remainder);
+                    var v = Fade(ycoord.Remainder);
 
-                    int aa = _p[a + ycoord.integer];
-                    int ab = _p[a + ycoord.integer + 1];
-                    int ba = _p[b + ycoord.integer];
-                    int bb = _p[b + ycoord.integer + 1];
+                    int aa = _p[a + ycoord.Integer];
+                    int ab = _p[a + ycoord.Integer + 1];
+                    int ba = _p[b + ycoord.Integer];
+                    int bb = _p[b + ycoord.Integer + 1];
                     for (int z = 0; z < zExtent; z++)
                     {
                         var zOffset = offset.Z + z * scale.Z;
                         var zcoord = Split(zOffset);
-                        var w = Fade(zcoord.remainder);
+                        var w = Fade(zcoord.Remainder);
 
-                        int aaa = _p[aa + zcoord.integer];
-                        int aba = _p[ab + zcoord.integer];
-                        int aab = _p[aa + zcoord.integer + 1];
-                        int abb = _p[ab + zcoord.integer + 1];
-                        int baa = _p[ba + zcoord.integer];
-                        int bba = _p[bb + zcoord.integer];
-                        int bab = _p[ba + zcoord.integer + 1];
-                        int bbb = _p[bb + zcoord.integer + 1];
+                        int aaa = _p[aa + zcoord.Integer];
+                        int aba = _p[ab + zcoord.Integer];
+                        int aab = _p[aa + zcoord.Integer + 1];
+                        int abb = _p[ab + zcoord.Integer + 1];
+                        int baa = _p[ba + zcoord.Integer];
+                        int bba = _p[bb + zcoord.Integer];
+                        int bab = _p[ba + zcoord.Integer + 1];
+                        int bbb = _p[bb + zcoord.Integer + 1];
 
                         var xa = new Vector4(
-                            Grad(aaa, xcoord.remainder, ycoord.remainder, zcoord.remainder),
-                            Grad(aba, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder),
-                            Grad(aab, xcoord.remainder, ycoord.remainder, zcoord.remainder - 1),
-                            Grad(abb, xcoord.remainder, ycoord.remainder - 1, zcoord.remainder - 1));
+                            Grad(aaa, xcoord.Remainder, ycoord.Remainder, zcoord.Remainder),
+                            Grad(aba, xcoord.Remainder, ycoord.Remainder - 1, zcoord.Remainder),
+                            Grad(aab, xcoord.Remainder, ycoord.Remainder, zcoord.Remainder - 1),
+                            Grad(abb, xcoord.Remainder, ycoord.Remainder - 1, zcoord.Remainder - 1));
                         var xb = new Vector4(
-                            Grad(baa, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder),
-                            Grad(bba, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder),
-                            Grad(bab, xcoord.remainder - 1, ycoord.remainder, zcoord.remainder - 1),
-                            Grad(bbb, xcoord.remainder - 1, ycoord.remainder - 1, zcoord.remainder - 1));
+                            Grad(baa, xcoord.Remainder - 1, ycoord.Remainder, zcoord.Remainder),
+                            Grad(bba, xcoord.Remainder - 1, ycoord.Remainder - 1, zcoord.Remainder),
+                            Grad(bab, xcoord.Remainder - 1, ycoord.Remainder, zcoord.Remainder - 1),
+                            Grad(bbb, xcoord.Remainder - 1, ycoord.Remainder - 1, zcoord.Remainder - 1));
                         var xl = Vector4.Lerp(xa, xb, u);
                         var ya = new Vector2(xl.X, xl.Z);
                         var yb = new Vector2(xl.Y, xl.W);
@@ -188,7 +188,7 @@ namespace MineCase.Algorithm.Noise
             }
         }
 
-        private static (int integer, float remainder) Split(float value)
+        private static (int Integer, float Remainder) Split(float value)
         {
             value = value % 256;
             if (value < 0) value += 256;

+ 0 - 1
src/MineCase.Core/Block/BlockStateExtensions.cs

@@ -3,7 +3,6 @@ using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
 using MineCase.World;
-using Orleans;
 
 namespace MineCase.Block
 {

+ 1 - 1
src/MineCase.Core/Block/BlockType.cs

@@ -718,7 +718,7 @@ namespace MineCase.Block
             }
         }
 
-        public static (uint id, uint meta) ParseBlockStateId(uint value)
+        public static (uint Id, uint Meta) ParseBlockStateId(uint value)
         {
             var id = BlockType.BaseBlockIdTable[value];
             var meta = value - id;

+ 2 - 7
src/MineCase.Core/MineCase.Core.csproj

@@ -2,7 +2,7 @@
 
   <PropertyGroup>
     <RootNamespace>MineCase</RootNamespace>
-    <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
+    <TargetFrameworks>net5.0</TargetFrameworks>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <CodeAnalysisRuleSet>../../build/Analyzers.ruleset</CodeAnalysisRuleSet>
@@ -17,13 +17,8 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.Orleans.Core.Abstractions" Version="3.1.0" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164" PrivateAssets="All" />
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
-    <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
-    <PackageReference Include="System.Memory" Version="4.5.3" />
-    <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.0" />
-    <PackageReference Include="System.ValueTuple" Version="4.5.0" />
   </ItemGroup>
 
   <ItemGroup>

+ 11 - 11
src/MineCase.Core/World/ChunkColumnCompactStorage.cs

@@ -143,13 +143,13 @@ namespace MineCase.World
                     if (y < 0 || y > 255)
                         return BlockStates.Air();
                     var offset = GetOffset(x, y, z);
-                    var toRead = Math.Min(_bitsPerBlock, 64 - offset.bitOffset);
-                    var value = Storage[offset.indexOffset] >> offset.bitOffset;
+                    var toRead = Math.Min(_bitsPerBlock, 64 - offset.BitOffset);
+                    var value = Storage[offset.IndexOffset] >> offset.BitOffset;
                     var rest = _bitsPerBlock - toRead;
                     if (rest > 0)
-                        value |= (Storage[offset.indexOffset + 1] & ((1u << rest) - 1)) << toRead;
+                        value |= (Storage[offset.IndexOffset + 1] & ((1u << rest) - 1)) << toRead;
                     var blockState = BlockType.ParseBlockStateId((uint)(value & BlockMask));
-                    return new BlockState { Id = blockState.id, MetaValue = blockState.meta };
+                    return new BlockState { Id = blockState.Id, MetaValue = blockState.Meta };
                 }
 
                 set
@@ -158,17 +158,17 @@ namespace MineCase.World
                         throw new IndexOutOfRangeException("Axis y out of range");
                     var stgValue = (ulong)((value.Id + value.MetaValue) & BlockMask);
                     var offset = GetOffset(x, y, z);
-                    var tmpValue = Storage[offset.indexOffset];
-                    var mask = BlockMask << offset.bitOffset;
-                    var toWrite = Math.Min(_bitsPerBlock, 64 - offset.bitOffset);
-                    Storage[offset.indexOffset] = (tmpValue & ~mask) | (stgValue << offset.bitOffset);
+                    var tmpValue = Storage[offset.IndexOffset];
+                    var mask = BlockMask << offset.BitOffset;
+                    var toWrite = Math.Min(_bitsPerBlock, 64 - offset.BitOffset);
+                    Storage[offset.IndexOffset] = (tmpValue & ~mask) | (stgValue << offset.BitOffset);
                     var rest = _bitsPerBlock - toWrite;
                     if (rest > 0)
                     {
                         mask = (1u << rest) - 1;
-                        tmpValue = Storage[offset.indexOffset + 1];
+                        tmpValue = Storage[offset.IndexOffset + 1];
                         stgValue >>= toWrite;
-                        Storage[offset.indexOffset + 1] = (tmpValue & ~mask) | (stgValue & mask);
+                        Storage[offset.IndexOffset + 1] = (tmpValue & ~mask) | (stgValue & mask);
                     }
                 }
             }
@@ -183,7 +183,7 @@ namespace MineCase.World
                 Storage = new ulong[ChunkConstants.BlocksInSection * _bitsPerBlock / 64];
             }
 
-            private static (int indexOffset, int bitOffset) GetOffset(int x, int y, int z)
+            private static (int IndexOffset, int BitOffset) GetOffset(int x, int y, int z)
             {
                 var index = GetBlockSerialIndex(x, y, z) * _bitsPerBlock;
                 return (index / 64, index % 64);

+ 0 - 3
src/MineCase.Core/World/GameTickArgs.cs

@@ -4,9 +4,6 @@ using System.Text;
 
 namespace MineCase.World
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     public sealed class GameTickArgs
     {
         public TimeSpan DeltaTime { get; set; }

+ 4 - 4
src/MineCase.Engine/MineCase.Server.Engine.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFrameworks>net5.0</TargetFrameworks>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <CodeAnalysisRuleSet>../../build/Analyzers.ruleset</CodeAnalysisRuleSet>
@@ -13,15 +13,15 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.1.0">
+    <PackageReference Include="Microsoft.Orleans.CodeGenerator.MSBuild" Version="3.2.0-rc2">
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
     </PackageReference>
-    <PackageReference Include="Microsoft.Orleans.Core" Version="3.1.0" />
+    <PackageReference Include="Microsoft.Orleans.Core" Version="3.2.0-rc2" />
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164" PrivateAssets="All" />
     <PackageReference Include="System.Collections.Generic.MultiValueDictionary" Version="0.1.0-e170912-3" />
     <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.2" />
     <PackageReference Include="MongoDB.Bson" Version="2.10.2" />

+ 29 - 7
src/MineCase.Gateway/AppBootstrapper.cs

@@ -13,15 +13,39 @@ using System.IO;
 using System.Reflection;
 using System.Text;
 using System.Linq;
+using Orleans;
+using Microsoft.Extensions.Hosting;
 
 namespace MineCase.Gateway
 {
     partial class Program
     {
-        private static void ConfigureServices(IServiceCollection services)
+        private static void ConfigureServices(HostBuilderContext context, IServiceCollection services)
         {
             services.AddLogging();
             services.AddSingleton<ConnectionRouter>();
+            services.AddSingleton<IPacketCompress, PacketCompress>();
+            services.AddTransient<ClientSession>();
+            services.AddHostedService<ConnectionRouter>();
+            services.AddOrleansMultiClient(builder =>
+            {
+                builder.AddClient(options =>
+                {
+                    options.ClusterId = "dev";
+                    options.ServiceId = "MineCaseService";
+                    options.Configure = c =>
+                    {
+                        // c.UseLocalhostClustering(gatewayPort: 30000);
+                        c.UseMongoDBClient(context.Configuration.GetSection("persistenceOptions")["connectionString"]);
+                        c.UseMongoDBClustering(options =>
+                        {
+                            options.DatabaseName = context.Configuration.GetSection("persistenceOptions")["databaseName"];
+                        });
+                    };
+                    options.SetServiceAssembly(SelectAssemblies());
+                });
+            });
+
             ConfigureObjectPools(services);
         }
 
@@ -36,12 +60,10 @@ namespace MineCase.Gateway
             services.AddSingleton<IBufferPool<byte>>(s => new BufferPool<byte>(ArrayPool<byte>.Shared));
         }
 
-        private static IConfiguration LoadConfiguration()
+        private static void ConfigureAppConfiguration(HostBuilderContext context, IConfigurationBuilder builder)
         {
-            var configurationBuilder = new ConfigurationBuilder()
-                .SetBasePath(Directory.GetCurrentDirectory())
+            builder.SetBasePath(Directory.GetCurrentDirectory())
                 .AddJsonFile("config.json", false, false);
-            return configurationBuilder.Build();
         }
 
         private static void ConfigureLogging(ILoggingBuilder loggingBuilder)
@@ -49,12 +71,12 @@ namespace MineCase.Gateway
             loggingBuilder.AddConsole();
         }
 
-        private static void SelectAssemblies()
+        private static Assembly[] SelectAssemblies()
         {
             var assemblies = new List<Assembly>();
             assemblies
                 .AddInterfaces();
-            _assemblies = assemblies.ToArray();
+            return assemblies.ToArray();
         }
     }
 }

+ 9 - 11
src/MineCase.Gateway/MineCase.Gateway.csproj

@@ -2,10 +2,9 @@
 
   <PropertyGroup>
     <OutputType>Exe</OutputType>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFramework>net5.0</TargetFramework>
     <ServerGarbageCollection>true</ServerGarbageCollection>
     <ConcurrentGarbageCollection>true</ConcurrentGarbageCollection>
-    <Configurations>Debug;Release;Appveyor;TravisCI</Configurations>
     <DebugType>full</DebugType>
     <DebugSymbols>true</DebugSymbols>
   </PropertyGroup>
@@ -33,16 +32,15 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.Extensions.Configuration" Version="3.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Logging" Version="3.1.2" />
-    <PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.2" />
-    <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="3.1.2" />
-    <PackageReference Include="Microsoft.Orleans.Client" Version="3.1.0" />
-    <PackageReference Include="Orleans.Providers.MongoDB" Version="3.1.1" />
+    <PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.4" />
+    <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="3.1.4" />
+    <PackageReference Include="Microsoft.Extensions.ObjectPool" Version="3.1.4" />
+    <PackageReference Include="Microsoft.Orleans.Client" Version="3.2.0-rc2" />
+    <PackageReference Include="Orleans.MultiClient" Version="3.1.7" />
+    <PackageReference Include="Orleans.Providers.MongoDB" Version="3.1.7" />
     <PackageReference Include="Polly" Version="7.2.0" />
-    <PackageReference Include="sharpcompress" Version="0.24.0" />
-    <PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-beta0006" />
+    <PackageReference Include="sharpcompress" Version="0.25.1" />
+    <PackageReference Include="SixLabors.ImageSharp" Version="1.0.0-rc0001" />
   </ItemGroup>
 
   <ItemGroup>

+ 27 - 29
src/MineCase.Gateway/Network/ClientSession.cs

@@ -1,6 +1,7 @@
 using Microsoft.Extensions.ObjectPool;
 using MineCase.Buffers;
 using MineCase.Protocol;
+using MineCase.Serialization;
 using MineCase.Server.Game;
 using MineCase.Server.Network;
 using Orleans;
@@ -19,7 +20,7 @@ namespace MineCase.Gateway.Network
     {
         private readonly TcpClient _tcpClient;
         private Stream _remoteStream;
-        private readonly IGrainFactory _grainFactory;
+        private readonly IOrleansClient _grainFactory;
         private volatile bool _useCompression = false;
         private readonly Guid _sessionId;
         private readonly OutcomingPacketObserver _outcomingPacketObserver;
@@ -27,16 +28,17 @@ namespace MineCase.Gateway.Network
         private readonly ActionBlock<object> _outcomingPacketDispatcher;
         private readonly ObjectPool<UncompressedPacket> _uncompressedPacketObjectPool;
         private readonly IBufferPool<byte> _bufferPool;
+        private readonly IPacketCompress _packetCompress;
 
-        private readonly object _useCompressionPacket = new object();
         private uint _compressThreshold;
 
-        public ClientSession(TcpClient tcpClient, IGrainFactory grainFactory, IBufferPool<byte> bufferPool, ObjectPool<UncompressedPacket> uncompressedPacketObjectPool)
+        public ClientSession(TcpClient tcpClient, IOrleansClient grainFactory, IBufferPool<byte> bufferPool, ObjectPool<UncompressedPacket> uncompressedPacketObjectPool, IPacketCompress packetCompress)
         {
             _sessionId = Guid.NewGuid();
             _tcpClient = tcpClient;
             _grainFactory = grainFactory;
             _bufferPool = bufferPool;
+            _packetCompress = packetCompress;
             _uncompressedPacketObjectPool = uncompressedPacketObjectPool;
             _outcomingPacketObserver = new OutcomingPacketObserver(this);
             _outcomingPacketDispatcher = new ActionBlock<object>(SendOutcomingPacket);
@@ -57,7 +59,7 @@ namespace MineCase.Gateway.Network
                     {
                         await DispatchIncomingPacket();
                         // renew subscribe, 10 sec
-                        if(DateTime.Now > expiredTime)
+                        if (DateTime.Now > expiredTime)
                         {
                             await _grainFactory.GetGrain<IClientboundPacketSink>(_sessionId).Subscribe(_clientboundPacketObserverRef);
                             expiredTime = DateTime.Now + TimeSpan.FromSeconds(10);
@@ -83,24 +85,18 @@ namespace MineCase.Gateway.Network
         {
             using (var bufferScope = _bufferPool.CreateScope())
             {
-                var packet = _uncompressedPacketObjectPool.Get();
-                try
+                UncompressedPacket packet;
+                if (_useCompression)
                 {
-                    if (_useCompression)
-                    {
-                        var compressedPacket = await CompressedPacket.DeserializeAsync(_remoteStream, null);
-                        packet = PacketCompress.Decompress(compressedPacket, bufferScope, _compressThreshold, packet);
-                    }
-                    else
-                    {
-                        packet = await UncompressedPacket.DeserializeAsync(_remoteStream, bufferScope, packet);
-                    }
-                    await DispatchIncomingPacket(packet);
+                    var compressedPacket = await CompressedPacket.DeserializeAsync(_remoteStream, null);
+                    packet = _packetCompress.Decompress(compressedPacket, _compressThreshold);
                 }
-                finally
+                else
                 {
-                    _uncompressedPacketObjectPool.Return(packet);
+                    packet = await UncompressedPacket.DeserializeAsync(_remoteStream, bufferScope);
                 }
+
+                await DispatchIncomingPacket(packet);
             }
         }
 
@@ -111,27 +107,35 @@ namespace MineCase.Gateway.Network
                 _tcpClient.Client.Shutdown(SocketShutdown.Send);
                 _outcomingPacketDispatcher.Complete();
             }
-            else if (packetOrCommand == _useCompressionPacket)
-            {
-                _useCompression = true;
-            }
             else if (packetOrCommand is UncompressedPacket packet)
             {
                 using (var bufferScope = _bufferPool.CreateScope())
                 {
                     if (_useCompression)
                     {
-                        var newPacket = PacketCompress.Compress(packet, bufferScope, _compressThreshold);
+                        var newPacket = _packetCompress.Compress(packet, _compressThreshold);
                         await newPacket.SerializeAsync(_remoteStream);
                     }
                     else
                     {
                         await packet.SerializeAsync(_remoteStream);
                     }
+
+                    if (!_useCompression && packet.PacketId == Protocol.Protocol.SetCompressionPacketId)
+                    {
+                        _compressThreshold = GetCompressionThreshold(packet);
+                        _useCompression = true;
+                    }
                 }
             }
         }
 
+        private static uint GetCompressionThreshold(UncompressedPacket packet)
+        {
+            var br = new SpanReader(packet.Data);
+            return br.ReadAsVarInt(out _);
+        }
+
         private async Task DispatchIncomingPacket(UncompressedPacket packet)
         {
             var router = _grainFactory.GetGrain<IPacketRouter>(_sessionId);
@@ -169,12 +173,6 @@ namespace MineCase.Gateway.Network
             {
                 _session.DispatchOutcomingPacket(packet);
             }
-
-            public void UseCompression(uint threshold)
-            {
-                _session._compressThreshold = threshold;
-                _session.DispatchOutcomingPacket(_session._useCompressionPacket);
-            }
         }
 
         #region IDisposable Support

+ 21 - 18
src/MineCase.Gateway/Network/ConnectionRouter.cs

@@ -1,35 +1,33 @@
-using Microsoft.Extensions.Logging;
+using System;
+using System.Net;
+using System.Net.Sockets;
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Hosting;
+using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.ObjectPool;
 using MineCase.Buffers;
 using MineCase.Protocol;
 using MineCase.Server.Settings;
 using Orleans;
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
 
 namespace MineCase.Gateway.Network
 {
-    class ConnectionRouter
+    class ConnectionRouter : IHostedService
     {
-        private readonly IGrainFactory _grainFactory;
+        private readonly IOrleansClient _grainFactory;
         private readonly ILogger _logger;
-        private readonly IBufferPool<byte> _bufferPool;
-        private readonly ObjectPool<UncompressedPacket> _uncompressedPacketObjectPool;
+        private readonly IServiceProvider _serviceProvider;
 
-        public ConnectionRouter(IGrainFactory grainFactory, ILoggerFactory loggerFactory, IBufferPool<byte> bufferPool, ObjectPool<UncompressedPacket> uncompressedPacketObjectPool)
+        public ConnectionRouter(IOrleansClient grainFactory, ILogger<ConnectionRouter> logger, IServiceProvider serviceProvider)
         {
             _grainFactory = grainFactory;
-            _logger = loggerFactory.CreateLogger<ConnectionRouter>();
-            _bufferPool = bufferPool;
-            _uncompressedPacketObjectPool = uncompressedPacketObjectPool;
+            _logger = logger;
+            _serviceProvider = serviceProvider;
         }
 
-        public async Task Startup(CancellationToken cancellationToken)
+        public async Task StartAsync(CancellationToken cancellationToken)
         {
             try
             {
@@ -53,12 +51,17 @@ namespace MineCase.Gateway.Network
             }
         }
 
+        public Task StopAsync(CancellationToken cancellationToken)
+        {
+            return Task.CompletedTask;
+        }
+
         private async void DispatchIncomingClient(TcpClient tcpClient, CancellationToken cancellationToken)
         {
             try
             {
                 _logger.LogInformation($"Incoming connection from {tcpClient.Client.RemoteEndPoint}.");
-                using (var session = new ClientSession(tcpClient, _grainFactory, _bufferPool, _uncompressedPacketObjectPool))
+                using (var session = ActivatorUtilities.CreateInstance<ClientSession>(_serviceProvider, tcpClient))
                 {
                     await session.Startup(cancellationToken);
                 }

+ 10 - 73
src/MineCase.Gateway/Program.cs

@@ -12,85 +12,22 @@ using Polly;
 using Orleans.Configuration;
 using Orleans.ApplicationParts;
 using Orleans.Hosting;
+using Microsoft.Extensions.Hosting;
 
 namespace MineCase.Gateway
 {
     partial class Program
     {
-        public static IConfiguration Configuration { get; private set; }
-
-        private static IClusterClient _clusterClient;
-        private static readonly ManualResetEvent _exitEvent = new ManualResetEvent(false);
-        private static Assembly[] _assemblies;
-
-        static void Main(string[] args)
-        {
-            Console.CancelKeyPress += (s, e) => _exitEvent.Set();
-            Configuration = LoadConfiguration();
-            Startup();
-            _exitEvent.WaitOne();
-            _clusterClient?.Dispose();
-        }
-
-        private static void ConfigureApplicationParts(IApplicationPartManager parts)
-        {
-            //foreach (var assembly in _assemblies)
-            //    parts.AddApplicationPart(assembly);
-            parts.AddFromApplicationBaseDirectory().WithReferences();
-        }
-
-        private static async void Startup()
-        {
-            ILogger logger = null;
-
-            var retryPolicy = Policy.Handle<OrleansException>()
-                .WaitAndRetryForeverAsync(
-                    retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)),
-                    (ex, timeSpan) => logger?.LogError($"Cluster connection failed. Next retry: {timeSpan.TotalSeconds} secs later."));
-            await retryPolicy.ExecuteAsync(async () =>
-            {
-                _clusterClient?.Dispose();
-                SelectAssemblies();
-                var builder = new ClientBuilder()
-                    .Configure<ClusterOptions>(options =>
-                    {
-                        options.ClusterId = "dev";
-                        options.ServiceId = "MineCaseService";
-                    })
-                    .Configure<SchedulingOptions>(options =>
-                    {
-                        options.AllowCallChainReentrancy = true;
-                        options.PerformDeadlockDetection = true;
-                    })
-                    .ConfigureServices(ConfigureServices)
-                    .ConfigureLogging(ConfigureLogging)
-                    .ConfigureApplicationParts(ConfigureApplicationParts)
-                    .AddSimpleMessageStreamProvider("JobsProvider")
-                    .AddSimpleMessageStreamProvider("TransientProvider")
-                    .UseMongoDBClient(Configuration.GetSection("persistenceOptions")["connectionString"])
-                    .UseMongoDBClustering(options=>
-                    {
-                        options.DatabaseName = Configuration.GetSection("persistenceOptions")["databaseName"];
-                    });
-                
-                // ConfigureApplicationParts(builder);
-                _clusterClient = builder.Build();
-
-                var serviceProvider = _clusterClient.ServiceProvider;
-                logger = _clusterClient.ServiceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<Program>();
-
-                await Connect(logger);
-            });
-
-            var connectionRouter = _clusterClient.ServiceProvider.GetRequiredService<ConnectionRouter>();
-            await connectionRouter.Startup(default(CancellationToken));
-        }
-
-        private static async Task Connect(ILogger logger)
+        static async Task Main(string[] args)
         {
-            logger.LogInformation("Connecting to cluster...");
-            await _clusterClient.Connect();
-            logger.LogInformation("Connected to cluster.");
+            var hostBuilder = new HostBuilder()
+                .ConfigureAppConfiguration(ConfigureAppConfiguration)
+                .ConfigureServices(ConfigureServices)
+                .ConfigureLogging(ConfigureLogging)
+                .UseConsoleLifetime();
+
+            var host = hostBuilder.Build();
+            await host.RunAsync();
         }
     }
 }

+ 2 - 3
src/MineCase.Nbt/MineCase.Nbt.csproj

@@ -1,7 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
+    <TargetFrameworks>net5.0</TargetFrameworks>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <CodeAnalysisRuleSet>../../build/Analyzers.ruleset</CodeAnalysisRuleSet>
     <Configurations>Debug;Release;Appveyor;TravisCI</Configurations>
@@ -10,8 +10,7 @@
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.0" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164" PrivateAssets="All" />
   </ItemGroup>
 
   <ItemGroup>

+ 6 - 7
src/MineCase.Protocol/MineCase.Protocol.csproj

@@ -1,12 +1,12 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFrameworks>netcoreapp3.1</TargetFrameworks>
+    <TargetFrameworks>net5.0</TargetFrameworks>
     <RootNamespace>MineCase</RootNamespace>
     <TreatWarningsAsErrors>true</TreatWarningsAsErrors>
     <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
     <CodeAnalysisRuleSet>../../build/Analyzers.ruleset</CodeAnalysisRuleSet>
-    <LangVersion>latest</LangVersion>
+    <LangVersion>preview</LangVersion>
     <Configurations>Debug;Release;Appveyor;TravisCI</Configurations>
     <DebugType>full</DebugType>
     <DebugSymbols>true</DebugSymbols>
@@ -14,12 +14,8 @@
 
   <ItemGroup>
     <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
-    <PackageReference Include="System.Buffers" Version="4.5.0" />
-    <PackageReference Include="System.Memory" Version="4.5.3" />
-    <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
-    <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" PrivateAssets="All" />
+    <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.164" PrivateAssets="All" />
     <PackageReference Include="sharpcompress" Version="0.24.0" />
-    <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.7.0" />
   </ItemGroup>
 
   <ItemGroup>
@@ -29,6 +25,9 @@
   <ItemGroup>
     <ProjectReference Include="..\MineCase.Core\MineCase.Core.csproj" />
     <ProjectReference Include="..\MineCase.Nbt\MineCase.Nbt.csproj" />
+    <ProjectReference Include="..\Tools\MineCase.CodeGeneration\MineCase.CodeGeneration.csproj"
+                      OutputItemType="Analyzer"
+                      ReferenceOutputAssembly="false"/>
   </ItemGroup>
 
 </Project>

+ 2 - 23
src/MineCase.Protocol/Protocol/Handshaking/Handshake.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Handshaking
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x00)]
-    public sealed class Handshake : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class Handshake : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint ProtocolVersion;
@@ -23,24 +21,5 @@ namespace MineCase.Protocol.Handshaking
 
         [SerializeAs(DataType.VarInt)]
         public uint NextState;
-
-        public static Handshake Deserialize(ref SpanReader br)
-        {
-            return new Handshake
-            {
-                ProtocolVersion = br.ReadAsVarInt(out _),
-                ServerAddress = br.ReadAsString(),
-                ServerPort = br.ReadAsUnsignedShort(),
-                NextState = br.ReadAsVarInt(out _)
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(ProtocolVersion, out _);
-            bw.WriteAsString(ServerAddress);
-            bw.WriteAsUnsignedShort(ServerPort);
-            bw.WriteAsVarInt(NextState, out _);
-        }
     }
 }

+ 8 - 57
src/MineCase.Protocol/Protocol/Login/LoginEncryption.cs

@@ -7,7 +7,8 @@ using MineCase.Serialization;
 namespace MineCase.Protocol.Login
 {
     [Packet(0x01)]
-    public sealed class EncryptionRequest : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class EncryptionRequest : IPacket
     {
         [SerializeAs(DataType.String)]
         public string ServerID;
@@ -15,80 +16,30 @@ namespace MineCase.Protocol.Login
         [SerializeAs(DataType.VarInt)]
         public uint PublicKeyLength;
 
-        [SerializeAs(DataType.ByteArray)]
+        [SerializeAs(DataType.ByteArray, ArrayLengthMember = nameof(PublicKeyLength))]
         public byte[] PublicKey;
 
         [SerializeAs(DataType.VarInt)]
         public uint VerifyTokenLength;
 
-        [SerializeAs(DataType.ByteArray)]
+        [SerializeAs(DataType.ByteArray, ArrayLengthMember = nameof(VerifyTokenLength))]
         public byte[] VerifyToken;
-
-        public static EncryptionRequest Deserialize(ref SpanReader br)
-        {
-            string serverID = br.ReadAsString();
-            uint publicKeyLength = br.ReadAsVarInt(out _);
-            byte[] publicKey = br.ReadAsByteArray((int)publicKeyLength);
-            uint verifyTokenLength = br.ReadAsVarInt(out _);
-            byte[] verifyToken = br.ReadAsByteArray((int)verifyTokenLength);
-
-            return new EncryptionRequest
-            {
-                ServerID = serverID,
-                PublicKeyLength = publicKeyLength,
-                PublicKey = publicKey,
-                VerifyTokenLength = verifyTokenLength,
-                VerifyToken = verifyToken
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsString(ServerID);
-            bw.WriteAsVarInt(PublicKeyLength, out _);
-            bw.WriteAsByteArray(PublicKey);
-            bw.WriteAsVarInt(VerifyTokenLength, out _);
-            bw.WriteAsByteArray(VerifyToken);
-        }
     }
 
     [Packet(0x01)]
-    public sealed class EncryptionResponse : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class EncryptionResponse : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint SharedSecretLength;
 
-        [SerializeAs(DataType.ByteArray)]
+        [SerializeAs(DataType.ByteArray, ArrayLengthMember = nameof(SharedSecretLength))]
         public byte[] SharedSecret;
 
         [SerializeAs(DataType.VarInt)]
         public uint VerifyTokenLength;
 
-        [SerializeAs(DataType.ByteArray)]
+        [SerializeAs(DataType.ByteArray, ArrayLengthMember = nameof(VerifyTokenLength))]
         public byte[] VerifyToken;
-
-        public static EncryptionResponse Deserialize(ref SpanReader br)
-        {
-            uint sharedSecretLength = br.ReadAsVarInt(out _);
-            byte[] sharedSecret = br.ReadAsByteArray((int)sharedSecretLength);
-            uint verifyTokenLength = br.ReadAsVarInt(out _);
-            byte[] verifyToken = br.ReadAsByteArray((int)verifyTokenLength);
-
-            return new EncryptionResponse
-            {
-                SharedSecretLength = sharedSecretLength,
-                SharedSecret = sharedSecret,
-                VerifyTokenLength = verifyTokenLength,
-                VerifyToken = verifyToken
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(SharedSecretLength, out _);
-            bw.WriteAsByteArray(SharedSecret);
-            bw.WriteAsVarInt(VerifyTokenLength, out _);
-            bw.WriteAsByteArray(VerifyToken);
-        }
     }
 }

+ 7 - 54
src/MineCase.Protocol/Protocol/Login/LoginStart.cs

@@ -6,77 +6,30 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Login
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x00)]
-    public sealed class LoginStart : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class LoginStart : IPacket
     {
         [SerializeAs(DataType.String)]
         public string Name;
-
-        public static LoginStart Deserialize(ref SpanReader br)
-        {
-            return new LoginStart
-            {
-                Name = br.ReadAsString(),
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsString(Name);
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x00)]
-    public sealed class LoginDisconnect : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class LoginDisconnect : IPacket
     {
-        [SerializeAs(DataType.Chat)]
+        [SerializeAs(DataType.String)]
         public string Reason;
-
-        public static LoginDisconnect Deserialize(ref SpanReader br)
-        {
-            return new LoginDisconnect
-            {
-                Reason = br.ReadAsString()
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.Write(Reason);
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x02)]
-    public sealed class LoginSuccess : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class LoginSuccess : IPacket
     {
         [SerializeAs(DataType.String)]
         public string UUID;
 
         [SerializeAs(DataType.String)]
         public string Username;
-
-        public static LoginSuccess Deserialize(ref SpanReader br)
-        {
-            return new LoginSuccess
-            {
-                UUID = br.ReadAsString(),
-                Username = br.ReadAsString()
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsString(UUID);
-            bw.WriteAsString(Username);
-        }
     }
 }

+ 3 - 18
src/MineCase.Protocol/Protocol/Login/SetCompression.cs

@@ -6,26 +6,11 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Login
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
-    [Packet(0x03)]
-    public sealed class SetCompression : ISerializablePacket
+    [Packet(Protocol.SetCompressionPacketId)]
+    [GenerateSerializer]
+    public sealed partial class SetCompression : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint Threshold;
-
-        public static SetCompression Deserialize(ref SpanReader br)
-        {
-            return new SetCompression
-            {
-                Threshold = br.ReadAsVarInt(out _),
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(Threshold, out _);
-        }
     }
 }

+ 3 - 7
src/MineCase.Protocol/Protocol/Packet.cs

@@ -9,9 +9,6 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     public class UncompressedPacket
     {
         [SerializeAs(DataType.VarInt)]
@@ -54,9 +51,6 @@ namespace MineCase.Protocol
         }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     public class CompressedPacket
     {
         [SerializeAs(DataType.VarInt)]
@@ -110,8 +104,10 @@ namespace MineCase.Protocol
         }
     }
 
-    public interface ISerializablePacket
+    public interface IPacket
     {
         void Serialize(BinaryWriter bw);
+
+        void Deserialize(ref SpanReader br);
     }
 }

+ 12 - 5
src/MineCase.Protocol/Protocol/PacketCompress.cs

@@ -9,22 +9,29 @@ using SharpCompress.Compressors.Deflate;
 
 namespace MineCase.Protocol
 {
-    public static class PacketCompress
+    public interface IPacketCompress
     {
-        public static UncompressedPacket Decompress(CompressedPacket packet, IBufferPoolScope<byte> bufferPool, uint threshold, UncompressedPacket targetPacket = null)
+        CompressedPacket Compress(UncompressedPacket packet, uint threshold);
+
+        UncompressedPacket Decompress(CompressedPacket packet, uint threshold);
+    }
+
+    public class PacketCompress : IPacketCompress
+    {
+        public UncompressedPacket Decompress(CompressedPacket packet, uint threshold)
         {
             if (packet.DataLength != 0 && packet.DataLength < threshold)
                 throw new InvalidDataException("Uncompressed data length is lower than threshold.");
             bool useCompression = packet.DataLength != 0;
             var dataLength = useCompression ? packet.DataLength : (uint)packet.CompressedData.Length;
 
-            targetPacket = targetPacket ?? new UncompressedPacket();
+            var targetPacket = new UncompressedPacket();
             using (var stream = new MemoryStream(packet.CompressedData))
             using (var br = new BinaryReader(useCompression ? (Stream)new ZlibStream(stream, CompressionMode.Decompress, CompressionLevel.BestSpeed) : stream))
             {
                 targetPacket.PacketId = br.ReadAsVarInt(out var packetIdLen);
 
-                targetPacket.Data = bufferPool.Rent((int)(dataLength - packetIdLen));
+                targetPacket.Data = new byte[dataLength - packetIdLen];
                 br.Read(targetPacket.Data.Array, targetPacket.Data.Offset, targetPacket.Data.Count);
             }
 
@@ -32,7 +39,7 @@ namespace MineCase.Protocol
             return targetPacket;
         }
 
-        public static CompressedPacket Compress(UncompressedPacket packet, IBufferPoolScope<byte> bufferPool, uint threshold)
+        public CompressedPacket Compress(UncompressedPacket packet, uint threshold)
         {
             var targetPacket = new CompressedPacket();
             using (var stream = new MemoryStream())

+ 20 - 0
src/MineCase.Protocol/Protocol/PacketDeserializer.cs

@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using MineCase.Serialization;
+
+namespace MineCase.Protocol
+{
+    public static class PacketDeserializer
+    {
+        public static T Deserialize<T>(ref SpanReader br)
+            where T : IPacket, new()
+        {
+            var packet = new T();
+            packet.Deserialize(ref br);
+            return packet;
+        }
+    }
+}

+ 2 - 12
src/MineCase.Protocol/Protocol/Play/Animation.cs

@@ -11,21 +11,11 @@ namespace MineCase.Protocol.Play
         Off = 1
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x2A)]
-    public sealed class ServerboundAnimation
+    [GenerateSerializer]
+    public sealed partial class ServerboundAnimation : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public Hand Hand;
-
-        public static ServerboundAnimation Deserialize(ref SpanReader br)
-        {
-            return new ServerboundAnimation
-            {
-                Hand = (Hand)br.ReadAsVarInt(out _)
-            };
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/BlockBreakAnimation.cs

@@ -3,11 +3,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x09)]
-    public sealed class BlockBreakAnimation : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class BlockBreakAnimation : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EntityID;
@@ -17,12 +15,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Byte)]
         public byte DestoryStage;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EntityID, out _);
-            bw.WriteAsPosition(BlockPosition);
-            bw.WriteAsByte(DestoryStage);
-        }
     }
 }

+ 2 - 10
src/MineCase.Protocol/Protocol/Play/BlockChange.cs

@@ -6,22 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x0C)]
-    public sealed class BlockChange : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class BlockChange : IPacket
     {
         [SerializeAs(DataType.Position)]
         public Position Location;
 
         [SerializeAs(DataType.VarInt)]
         public uint BlockId;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsPosition(Location);
-            bw.WriteAsVarInt(BlockId, out _);
-        }
     }
 }

+ 4 - 22
src/MineCase.Protocol/Protocol/Play/ChatMessage.cs

@@ -6,41 +6,23 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x03)]
-    public sealed class ServerboundChatMessage
+    [GenerateSerializer]
+    public sealed partial class ServerboundChatMessage : IPacket
     {
         [SerializeAs(DataType.String)]
         public string Message;
-
-        public static ServerboundChatMessage Deserialize(ref SpanReader br)
-        {
-            return new ServerboundChatMessage
-            {
-                Message = br.ReadAsString()
-            };
-        }
     }
 
     // TODO
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x0F)]
-    public sealed class ClientboundChatMessage : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class ClientboundChatMessage : IPacket
     {
         [SerializeAs(DataType.Chat)]
         public Chat JSONData;
 
         [SerializeAs(DataType.Byte)]
         public byte Position; // 0: chat (chat box), 1: system message (chat box), 2: game info (above hotbar).
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsChat(JSONData);
-            bw.WriteAsByte(Position);
-        }
     }
 }

+ 12 - 8
src/MineCase.Protocol/Protocol/Play/ChunkData.cs

@@ -9,11 +9,8 @@ using MineCase.World;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x22)]
-    public sealed class ChunkData : ISerializablePacket
+    public sealed class ChunkData : IPacket
     {
         [SerializeAs(DataType.Int)]
         public int ChunkX;
@@ -72,6 +69,11 @@ namespace MineCase.Protocol.Play
             return result;
         }
 
+        public void Deserialize(ref SpanReader br)
+        {
+            throw new NotSupportedException();
+        }
+
         public void Serialize(BinaryWriter bw)
         {
             bw.WriteAsInt(ChunkX);
@@ -99,10 +101,7 @@ namespace MineCase.Protocol.Play
         }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
-    public sealed class ChunkSection : ISerializablePacket
+    public sealed class ChunkSection : IPacket
     {
         [SerializeAs(DataType.Short)]
         public short BlockCount;
@@ -155,6 +154,11 @@ namespace MineCase.Protocol.Play
             return result;
         }
 
+        public void Deserialize(ref SpanReader br)
+        {
+            throw new NotImplementedException();
+        }
+
         public void Serialize(BinaryWriter bw)
         {
             DataArrayLength = (uint)DataArray.Length;

+ 2 - 17
src/MineCase.Protocol/Protocol/Play/ClickWindow.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x09)]
-    public sealed class ClickWindow
+    [GenerateSerializer]
+    public sealed partial class ClickWindow : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
@@ -29,18 +27,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Slot)]
         public Slot ClickedItem;
-
-        public static ClickWindow Deserialize(ref SpanReader br)
-        {
-            return new ClickWindow
-            {
-                WindowId = br.ReadAsByte(),
-                Slot = br.ReadAsShort(),
-                Button = br.ReadAsByte(),
-                ActionNumber = br.ReadAsShort(),
-                Mode = br.ReadAsVarInt(out _),
-                ClickedItem = br.ReadAsSlot()
-            };
-        }
     }
 }

+ 2 - 17
src/MineCase.Protocol/Protocol/Play/ClientSettings.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x05)]
-    public sealed class ClientSettings
+    [GenerateSerializer]
+    public sealed partial class ClientSettings : IPacket
     {
         [SerializeAs(DataType.String)]
         public string Locale;
@@ -29,18 +27,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.VarInt)]
         public uint MainHand;
-
-        public static ClientSettings Deserialize(ref SpanReader br)
-        {
-            return new ClientSettings
-            {
-                Locale = br.ReadAsString(),
-                ViewDistance = br.ReadAsByte(),
-                ChatMode = br.ReadAsVarInt(out _),
-                ChatColors = br.ReadAsBoolean(),
-                DisplayedSkinParts = br.ReadAsByte(),
-                MainHand = br.ReadAsVarInt(out _)
-            };
-        }
     }
 }

+ 2 - 12
src/MineCase.Protocol/Protocol/Play/ClientboundAnimation.cs

@@ -4,24 +4,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x06)]
-    public sealed class ClientboundAnimation : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class ClientboundAnimation : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EntityID;
 
         [SerializeAs(DataType.Byte)]
         public ClientboundAnimationId AnimationID;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            // TODO: check enum to byte.
-            byte animationID = (byte)AnimationID;
-            bw.WriteAsVarInt(EntityID, out _);
-            bw.WriteAsByte(animationID);
-        }
     }
 }

+ 4 - 21
src/MineCase.Protocol/Protocol/Play/CloseWindow.cs

@@ -6,36 +6,19 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x0A)]
-    public sealed class ServerboundCloseWindow
+    [GenerateSerializer]
+    public sealed partial class ServerboundCloseWindow : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
-
-        public static ServerboundCloseWindow Deserialize(ref SpanReader br)
-        {
-            return new ServerboundCloseWindow
-            {
-                WindowId = br.ReadAsByte()
-            };
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x14)]
-    public sealed class ClientboundCloseWindow : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class ClientboundCloseWindow : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsByte(WindowId);
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/CollectItem.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x56)]
-    public sealed class CollectItem : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class CollectItem : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint CollectedEntityId;
@@ -20,12 +18,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.VarInt)]
         public uint PickupItemCount;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(CollectedEntityId, out _);
-            bw.WriteAsVarInt(CollectorEntityId, out _);
-            bw.WriteAsVarInt(PickupItemCount, out _);
-        }
     }
 }

+ 4 - 25
src/MineCase.Protocol/Protocol/Play/ConfirmTransaction.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x06)]
-    public sealed class ServerboundConfirmTransaction
+    [GenerateSerializer]
+    public sealed partial class ServerboundConfirmTransaction : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
@@ -20,23 +18,11 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Boolean)]
         public bool Accepted;
-
-        public static ServerboundConfirmTransaction Deserialize(ref SpanReader br)
-        {
-            return new ServerboundConfirmTransaction
-            {
-                WindowId = br.ReadAsByte(),
-                ActionNumber = br.ReadAsShort(),
-                Accepted = br.ReadAsBoolean()
-            };
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x11)]
-    public sealed class ClientboundConfirmTransaction : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class ClientboundConfirmTransaction : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
@@ -46,12 +32,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Boolean)]
         public bool Accepted;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsByte(WindowId);
-            bw.WriteAsShort(ActionNumber);
-            bw.WriteAsBoolean(Accepted);
-        }
     }
 }

+ 3 - 9
src/MineCase.Protocol/Protocol/Play/DeclareCommands.cs

@@ -7,11 +7,8 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x12)]
-    public sealed class DeclareCommands : ISerializablePacket
+    public sealed class DeclareCommands : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint Count;
@@ -28,12 +25,9 @@ namespace MineCase.Protocol.Play
             bw.WriteAsVarInt(Count, out _);
         }
 
-        public static DeclareCommands Deserialize(ref SpanReader br)
+        public void Deserialize(ref SpanReader br)
         {
-            return new DeclareCommands
-            {
-                Count = br.ReadAsVarInt(out _),
-            };
+            Count = br.ReadAsVarInt(out _);
         }
     }
 }

+ 3 - 12
src/MineCase.Protocol/Protocol/Play/DestroyEntities.cs

@@ -6,23 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x38)]
-    public sealed class DestroyEntities : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class DestroyEntities : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint Count;
 
-        [SerializeAs(DataType.Array)]
+        [SerializeAs(DataType.VarIntArray, ArrayLengthMember = nameof(Count))]
         public uint[] EntityIds;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(Count, out _);
-            foreach (var eid in EntityIds)
-                bw.WriteAsVarInt(eid, out _);
-        }
     }
 }

+ 2 - 9
src/MineCase.Protocol/Protocol/Play/Entity.cs

@@ -7,18 +7,11 @@ using MineCase.Serialization;
 namespace MineCase.Protocol.Play
 {
     // FIXME: 1.15.2 no longer has this packet
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x25)]
-    public sealed class Entity : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class Entity : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/EntityAction.cs

@@ -20,7 +20,8 @@ namespace MineCase.Protocol.Play
     }
 
     [Packet(0x1B)]
-    public sealed class EntityAction
+    [GenerateSerializer]
+    public sealed partial class EntityAction : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EntityId;
@@ -30,15 +31,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.VarInt)]
         public uint JumpBoost;
-
-        public static EntityAction Deserialize(ref SpanReader br)
-        {
-            return new EntityAction
-            {
-                EntityId = br.ReadAsVarInt(out _),
-                ActionId = (ActionId)br.ReadAsVarInt(out _),
-                JumpBoost = br.ReadAsVarInt(out _)
-            };
-        }
     }
 }

+ 3 - 11
src/MineCase.Protocol/Protocol/Play/EntityHeadLook.cs

@@ -6,22 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x3C)]
-    public sealed class EntityHeadLook : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class EntityHeadLook : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
 
         [SerializeAs(DataType.Angle)]
-        public byte Yaw;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-            bw.WriteAsByte(Yaw);
-        }
+        public Angle Yaw;
     }
 }

+ 4 - 14
src/MineCase.Protocol/Protocol/Play/EntityLook.cs

@@ -7,30 +7,20 @@ using MineCase.Serialization;
 namespace MineCase.Protocol.Play
 {
     // FIXME : 1.15.2 does not have this packet
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x28)]
-    public sealed class EntityLook : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class EntityLook : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
 
         [SerializeAs(DataType.Angle)]
-        public byte Yaw;
+        public Angle Yaw;
 
         [SerializeAs(DataType.Angle)]
-        public byte Pitch;
+        public Angle Pitch;
 
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-            bw.WriteAsByte(Yaw);
-            bw.WriteAsByte(Pitch);
-            bw.WriteAsBoolean(OnGround);
-        }
     }
 }

+ 4 - 31
src/MineCase.Protocol/Protocol/Play/EntityLookAndRelativeMove.cs

@@ -7,11 +7,9 @@ using MineCase.Serialization;
 namespace MineCase.Protocol.Play
 {
     // FIXME : 1.15.2 does not have this packet
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x27)]
-    public sealed class EntityLookAndRelativeMove : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class EntityLookAndRelativeMove : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
@@ -26,37 +24,12 @@ namespace MineCase.Protocol.Play
         public short DeltaZ;
 
         [SerializeAs(DataType.Angle)]
-        public byte Yaw;
+        public Angle Yaw;
 
         [SerializeAs(DataType.Angle)]
-        public byte Pitch;
+        public Angle Pitch;
 
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public static EntityLookAndRelativeMove Deserialize(ref SpanReader br)
-        {
-            return new EntityLookAndRelativeMove
-            {
-                EID = br.ReadAsVarInt(out _),
-                DeltaX = br.ReadAsShort(),
-                DeltaY = br.ReadAsShort(),
-                DeltaZ = br.ReadAsShort(),
-                Yaw = br.ReadAsByte(),
-                Pitch = br.ReadAsByte(),
-                OnGround = br.ReadAsBoolean()
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-            bw.WriteAsShort(DeltaX);
-            bw.WriteAsShort(DeltaY);
-            bw.WriteAsShort(DeltaZ);
-            bw.WriteAsByte(Yaw);
-            bw.WriteAsByte(Pitch);
-            bw.WriteAsBoolean(OnGround);
-        }
     }
 }

+ 6 - 4
src/MineCase.Protocol/Protocol/Play/EntityMetadata.cs

@@ -6,11 +6,8 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x44)]
-    public sealed class EntityMetadata : ISerializablePacket
+    public sealed class EntityMetadata : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EntityId;
@@ -18,6 +15,11 @@ namespace MineCase.Protocol.Play
         [SerializeAs(DataType.ByteArray)]
         public byte[] Metadata;
 
+        public void Deserialize(ref SpanReader br)
+        {
+            throw new NotImplementedException();
+        }
+
         public void Serialize(BinaryWriter bw)
         {
             bw.WriteAsVarInt(EntityId, out _);

+ 2 - 13
src/MineCase.Protocol/Protocol/Play/EntityRelativeMove.cs

@@ -7,11 +7,9 @@ using MineCase.Serialization;
 namespace MineCase.Protocol.Play
 {
     // FIXME : 1.15.2 does not have this packet
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x26)]
-    public sealed class EntityRelativeMove : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class EntityRelativeMove : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
@@ -27,14 +25,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-            bw.WriteAsShort(DeltaX);
-            bw.WriteAsShort(DeltaY);
-            bw.WriteAsShort(DeltaZ);
-            bw.WriteAsBoolean(OnGround);
-        }
     }
 }

+ 4 - 17
src/MineCase.Protocol/Protocol/Play/EntityTeleport.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x57)]
-    public sealed class EntityTeleport : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class EntityTeleport : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
@@ -25,23 +23,12 @@ namespace MineCase.Protocol.Play
         public double Z;
 
         [SerializeAs(DataType.Angle)]
-        public byte Yaw;
+        public Angle Yaw;
 
         [SerializeAs(DataType.Angle)]
-        public byte Pitch;
+        public Angle Pitch;
 
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-            bw.WriteAsDouble(X);
-            bw.WriteAsDouble(Y);
-            bw.WriteAsDouble(Z);
-            bw.WriteAsAngle(Yaw);
-            bw.WriteAsAngle(Pitch);
-            bw.WriteAsBoolean(OnGround);
-        }
     }
 }

+ 2 - 12
src/MineCase.Protocol/Protocol/Play/HeldItemChange.cs

@@ -6,21 +6,11 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x23)]
-    public sealed class ServerboundHeldItemChange
+    [GenerateSerializer]
+    public sealed partial class ServerboundHeldItemChange : IPacket
     {
         [SerializeAs(DataType.Short)]
         public short Slot;
-
-        public static ServerboundHeldItemChange Deserialize(ref SpanReader br)
-        {
-            return new ServerboundHeldItemChange
-            {
-                Slot = br.ReadAsShort()
-            };
-        }
     }
 }

+ 2 - 17
src/MineCase.Protocol/Protocol/Play/JoinGame.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x26)]
-    public class JoinGame : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class JoinGame : IPacket
     {
         [SerializeAs(DataType.Int)]
         public int EID;
@@ -38,18 +36,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Boolean)]
         public bool EnableRespawnScreen;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsInt(EID);
-            bw.WriteAsByte(GameMode);
-            bw.WriteAsInt(Dimension);
-            bw.WriteAsLong(HashedSeed);
-            bw.WriteAsByte(MaxPlayers);
-            bw.WriteAsString(LevelType);
-            bw.WriteAsVarInt(ViewDistance, out _);
-            bw.WriteAsBoolean(ReducedDebugInfo);
-            bw.WriteAsBoolean(EnableRespawnScreen);
-        }
     }
 }

+ 4 - 21
src/MineCase.Protocol/Protocol/Play/KeepAlive.cs

@@ -6,36 +6,19 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x0F)]
-    public sealed class ServerboundKeepAlive
+    [GenerateSerializer]
+    public sealed partial class ServerboundKeepAlive : IPacket
     {
         [SerializeAs(DataType.Long)]
         public long KeepAliveId;
-
-        public static ServerboundKeepAlive Deserialize(ref SpanReader br)
-        {
-            return new ServerboundKeepAlive
-            {
-                KeepAliveId = br.ReadAsLong()
-            };
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x21)]
-    public sealed class ClientboundKeepAlive : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class ClientboundKeepAlive : IPacket
     {
         [SerializeAs(DataType.Long)]
         public long KeepAliveId;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsLong(KeepAliveId);
-        }
     }
 }

+ 6 - 4
src/MineCase.Protocol/Protocol/Play/OpenWindow.cs

@@ -6,11 +6,8 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x2F)]
-    public sealed class OpenWindow : ISerializablePacket
+    public sealed class OpenWindow : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
@@ -27,6 +24,11 @@ namespace MineCase.Protocol.Play
         [SerializeAs(DataType.Byte)]
         public byte? EntityId;
 
+        public void Deserialize(ref SpanReader br)
+        {
+            throw new NotImplementedException();
+        }
+
         public void Serialize(BinaryWriter bw)
         {
             bw.WriteAsByte(WindowId);

+ 2 - 17
src/MineCase.Protocol/Protocol/Play/PlayerBlockPlacement.cs

@@ -7,11 +7,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x2C)]
-    public sealed class PlayerBlockPlacement
+    [GenerateSerializer]
+    public sealed partial class PlayerBlockPlacement : IPacket
     {
         [SerializeAs(DataType.Position)]
         public Position Location;
@@ -30,18 +28,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Float)]
         public float CursorPositionZ;
-
-        public static PlayerBlockPlacement Deserialize(ref SpanReader br)
-        {
-            return new PlayerBlockPlacement
-            {
-                Location = br.ReadAsPosition(),
-                Face = (PlayerDiggingFace)br.ReadAsVarInt(out _),
-                Hand = (Hand)br.ReadAsVarInt(out _),
-                CursorPositionX = br.ReadAsFloat(),
-                CursorPositionY = br.ReadAsFloat(),
-                CursorPositionZ = br.ReadAsFloat()
-            };
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/PlayerDigging.cs

@@ -29,7 +29,8 @@ namespace MineCase.Protocol.Play
     }
 
     [Packet(0x1A)]
-    public sealed class PlayerDigging
+    [GenerateSerializer]
+    public sealed partial class PlayerDigging : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public PlayerDiggingStatus Status;
@@ -39,15 +40,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Byte)]
         public PlayerDiggingFace Face;
-
-        public static PlayerDigging Deserialize(ref SpanReader br)
-        {
-            return new PlayerDigging
-            {
-                Status = (PlayerDiggingStatus)br.ReadAsVarInt(out _),
-                Location = br.ReadAsPosition(),
-                Face = (PlayerDiggingFace)br.ReadAsByte()
-            };
-        }
     }
 }

+ 16 - 16
src/MineCase.Protocol/Protocol/Play/PlayerInfo.cs

@@ -7,12 +7,10 @@ using MineCase.Serialization;
 namespace MineCase.Protocol.Play
 {
     // In 1.12, it is PlayerListItem. Now it is PlayerInfo
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x34)]
-    public sealed class PlayerInfo<TAction> : ISerializablePacket
-        where TAction : PlayerInfoAction
+    [GenerateSerializer]
+    public sealed partial class PlayerInfo<TAction> : IPacket
+        where TAction : PlayerInfoAction, new()
     {
         [SerializeAs(DataType.VarInt)]
         public uint Action;
@@ -20,30 +18,27 @@ namespace MineCase.Protocol.Play
         [SerializeAs(DataType.VarInt)]
         public uint NumberOfPlayers;
 
-        [SerializeAs(DataType.Array)]
+        [SerializeAs(DataType.Array, ArrayLengthMember = nameof(NumberOfPlayers))]
         public TAction[] Players;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(Action, out _);
-            bw.WriteAsVarInt(NumberOfPlayers, out _);
-            if (NumberOfPlayers != 0)
-                bw.WriteAsArray(Players);
-        }
     }
 
-    public abstract class PlayerInfoAction : ISerializablePacket
+    public abstract partial class PlayerInfoAction : IPacket
     {
         [SerializeAs(DataType.UUID)]
         public Guid UUID;
 
+        public virtual void Deserialize(ref SpanReader br)
+        {
+            UUID = br.ReadAsUUID();
+        }
+
         public virtual void Serialize(BinaryWriter bw)
         {
             bw.WriteAsUUID(UUID);
         }
     }
 
-    public sealed class PlayerInfoAddPlayerAction : PlayerInfoAction
+    public sealed partial class PlayerInfoAddPlayerAction : PlayerInfoAction
     {
         [SerializeAs(DataType.String)]
         public string Name;
@@ -63,6 +58,11 @@ namespace MineCase.Protocol.Play
         [SerializeAs(DataType.Chat)]
         public string DisplayName;
 
+        public override void Deserialize(ref SpanReader br)
+        {
+            base.Deserialize(ref br);
+        }
+
         public override void Serialize(BinaryWriter bw)
         {
             base.Serialize(bw);

+ 2 - 14
src/MineCase.Protocol/Protocol/Play/PlayerLook.cs

@@ -7,11 +7,9 @@ using MineCase.Serialization;
 namespace MineCase.Protocol.Play
 {
     // FIXME : 1.15.2 does not have this packet
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x10)]
-    public sealed class PlayerLook
+    [GenerateSerializer]
+    public sealed partial class PlayerLook : IPacket
     {
         [SerializeAs(DataType.Float)]
         public float Yaw;
@@ -21,15 +19,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public static PlayerLook Deserialize(ref SpanReader br)
-        {
-            return new PlayerLook
-            {
-                Yaw = br.ReadAsFloat(),
-                Pitch = br.ReadAsFloat(),
-                OnGround = br.ReadAsBoolean()
-            };
-        }
     }
 }

+ 2 - 9
src/MineCase.Protocol/Protocol/Play/PlayerOnGround.cs

@@ -7,17 +7,10 @@ namespace MineCase.Protocol.Play
 {
     // FIXME : 1.15.2 does not have this packet
     [Packet(0x0D)]
-    public sealed class PlayerOnGround
+    [GenerateSerializer]
+    public sealed partial class PlayerOnGround : IPacket
     {
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public static PlayerOnGround Deserialize(ref SpanReader br)
-        {
-            return new PlayerOnGround
-            {
-                OnGround = br.ReadAsBoolean(),
-            };
-        }
     }
 }

+ 2 - 15
src/MineCase.Protocol/Protocol/Play/PlayerPosition.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x11)]
-    public sealed class PlayerPosition
+    [GenerateSerializer]
+    public sealed partial class PlayerPosition : IPacket
     {
         [SerializeAs(DataType.Double)]
         public double X;
@@ -23,16 +21,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public static PlayerPosition Deserialize(ref SpanReader br)
-        {
-            return new PlayerPosition
-            {
-                X = br.ReadAsDouble(),
-                FeetY = br.ReadAsDouble(),
-                Z = br.ReadAsDouble(),
-                OnGround = br.ReadAsBoolean()
-            };
-        }
     }
 }

+ 2 - 13
src/MineCase.Protocol/Protocol/Play/PluginMessage.cs

@@ -6,25 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x0A)]
-    public sealed class ServerboundPluginMessage
+    [GenerateSerializer]
+    public sealed partial class ServerboundPluginMessage : IPacket
     {
         [SerializeAs(DataType.String)]
         public string Channel;
 
         [SerializeAs(DataType.ByteArray)]
         public byte[] Data;
-
-        public static ServerboundPluginMessage Deserialize(ref SpanReader br)
-        {
-            return new ServerboundPluginMessage
-            {
-                Channel = br.ReadAsString(),
-                Data = br.ReadAsByteArray()
-            };
-        }
     }
 }

+ 4 - 32
src/MineCase.Protocol/Protocol/Play/PositionAndLook.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x36)]
-    public sealed class ClientboundPositionAndLook : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class ClientboundPositionAndLook : IPacket
     {
         [SerializeAs(DataType.Double)]
         public double X;
@@ -32,24 +30,11 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.VarInt)]
         public uint TeleportId;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsDouble(X);
-            bw.WriteAsDouble(Y);
-            bw.WriteAsDouble(Z);
-            bw.WriteAsFloat(Yaw);
-            bw.WriteAsFloat(Pitch);
-            bw.WriteAsByte(Flags);
-            bw.WriteAsVarInt(TeleportId, out _);
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x12)]
-    public sealed class ServerboundPositionAndLook
+    [GenerateSerializer]
+    public sealed partial class ServerboundPositionAndLook : IPacket
     {
         [SerializeAs(DataType.Double)]
         public double X;
@@ -68,18 +53,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Boolean)]
         public bool OnGround;
-
-        public static ServerboundPositionAndLook Deserialize(ref SpanReader br)
-        {
-            return new ServerboundPositionAndLook
-            {
-                X = br.ReadAsDouble(),
-                FeetY = br.ReadAsDouble(),
-                Z = br.ReadAsDouble(),
-                Yaw = br.ReadAsFloat(),
-                Pitch = br.ReadAsFloat(),
-                OnGround = br.ReadAsBoolean()
-            };
-        }
     }
 }

+ 2 - 13
src/MineCase.Protocol/Protocol/Play/PrepareCraftingGrid.cs

@@ -6,25 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x01)]
-    public sealed class PrepareCraftingGrid
+    [GenerateSerializer]
+    public sealed partial class PrepareCraftingGrid : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
 
         [SerializeAs(DataType.Short)]
         public short ActionNumber;
-
-        public static PrepareCraftingGrid Deserialize(ref SpanReader br)
-        {
-            return new PrepareCraftingGrid
-            {
-                WindowId = br.ReadAsByte(),
-                ActionNumber = br.ReadAsShort()
-            };
-        }
     }
 }

+ 2 - 23
src/MineCase.Protocol/Protocol/Play/Respawn.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x3B)]
-    public sealed class Respawn : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class Respawn : IPacket
     {
         [SerializeAs(DataType.Int)]
         public int Dimension;
@@ -23,24 +21,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.String)]
         public string LevelType;
-
-        public static Respawn Deserialize(ref SpanReader br)
-        {
-            return new Respawn
-            {
-                Dimension = br.ReadAsInt(),
-                HashedSeed = br.ReadAsLong(),
-                Gamemode = br.ReadAsByte(),
-                LevelType = br.ReadAsString()
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsInt(Dimension);
-            bw.WriteAsLong(HashedSeed);
-            bw.WriteAsByte(Gamemode);
-            bw.WriteAsString(LevelType);
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/SetExperience.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x48)]
-    public sealed class SetExperience : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class SetExperience : IPacket
     {
         [SerializeAs(DataType.Float)]
         public float ExperienceBar;
@@ -20,12 +18,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.VarInt)]
         public uint TotalExperience;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsFloat(ExperienceBar);
-            bw.WriteAsVarInt(Level, out _);
-            bw.WriteAsVarInt(TotalExperience, out _);
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/SetSlot.cs

@@ -7,11 +7,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x17)]
-    public sealed class SetSlot : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class SetSlot : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
@@ -21,12 +19,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Slot)]
         public Slot SlotData;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsByte(WindowId);
-            bw.WriteAsShort(Slot);
-            bw.WriteAsSlot(SlotData);
-        }
     }
 }

+ 5 - 24
src/MineCase.Protocol/Protocol/Play/SpawnMob.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x03)]
-    public sealed class SpawnMob : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class SpawnMob : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
@@ -31,13 +29,13 @@ namespace MineCase.Protocol.Play
         public double Z;
 
         [SerializeAs(DataType.Angle)]
-        public byte Pitch;
+        public Angle Pitch;
 
         [SerializeAs(DataType.Angle)]
-        public byte Yaw;
+        public Angle Yaw;
 
         [SerializeAs(DataType.Angle)]
-        public byte HeadPitch;
+        public Angle HeadPitch;
 
         [SerializeAs(DataType.Short)]
         public short VelocityX;
@@ -50,22 +48,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.ByteArray)]
         public byte[] Metadata;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-            bw.WriteAsUUID(EntityUUID);
-            bw.WriteAsByte(Type);
-            bw.WriteAsDouble(X);
-            bw.WriteAsDouble(Y);
-            bw.WriteAsDouble(Z);
-            bw.WriteAsByte(Yaw);
-            bw.WriteAsByte(Pitch);
-            bw.WriteAsByte(HeadPitch);
-            bw.WriteAsShort(VelocityX);
-            bw.WriteAsShort(VelocityY);
-            bw.WriteAsShort(VelocityZ);
-            bw.WriteAsByteArray(Metadata);
-        }
     }
 }

+ 4 - 22
src/MineCase.Protocol/Protocol/Play/SpawnObject.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x00)]
-    public sealed class SpawnObject : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class SpawnObject : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EID;
@@ -31,10 +29,10 @@ namespace MineCase.Protocol.Play
         public double Z;
 
         [SerializeAs(DataType.Angle)]
-        public byte Pitch;
+        public Angle Pitch;
 
         [SerializeAs(DataType.Angle)]
-        public byte Yaw;
+        public Angle Yaw;
 
         [SerializeAs(DataType.Int)]
         public int Data;
@@ -47,21 +45,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Short)]
         public short VelocityZ;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EID, out _);
-            bw.WriteAsUUID(ObjectUUID);
-            bw.WriteAsVarInt(Type, out _);
-            bw.WriteAsDouble(X);
-            bw.WriteAsDouble(Y);
-            bw.WriteAsDouble(Z);
-            bw.WriteAsByte(Pitch);
-            bw.WriteAsByte(Yaw);
-            bw.WriteAsInt(Data);
-            bw.WriteAsShort(VelocityX);
-            bw.WriteAsShort(VelocityY);
-            bw.WriteAsShort(VelocityZ);
-        }
     }
 }

+ 2 - 15
src/MineCase.Protocol/Protocol/Play/SpawnPlayer.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x05)]
-    public sealed class SpawnPlayer : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class SpawnPlayer : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint EntityId;
@@ -32,16 +30,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Angle)]
         public Angle Pitch;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt(EntityId, out _);
-            bw.WriteAsUUID(PlayerUUID);
-            bw.WriteAsDouble(X);
-            bw.WriteAsDouble(Y);
-            bw.WriteAsDouble(Z);
-            bw.WriteAsAngle(Yaw);
-            bw.WriteAsAngle(Pitch);
-        }
     }
 }

+ 2 - 12
src/MineCase.Protocol/Protocol/Play/TeleportConfirm.cs

@@ -6,21 +6,11 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x00)]
-    public sealed class TeleportConfirm
+    [GenerateSerializer]
+    public sealed partial class TeleportConfirm : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public uint TeleportId;
-
-        public static TeleportConfirm Deserialize(ref SpanReader br)
-        {
-            return new TeleportConfirm
-            {
-                TeleportId = br.ReadAsVarInt(out _)
-            };
-        }
     }
 }

+ 2 - 10
src/MineCase.Protocol/Protocol/Play/TimeUpdate.cs

@@ -6,22 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x4F)]
-    public sealed class TimeUpdate : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class TimeUpdate : IPacket
     {
         [SerializeAs(DataType.Long)]
         public long WorldAge;
 
         [SerializeAs(DataType.Long)]
         public long TimeOfDay;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsLong(WorldAge);
-            bw.WriteAsLong(TimeOfDay);
-        }
     }
 }

+ 2 - 10
src/MineCase.Protocol/Protocol/Play/UnloadChunk.cs

@@ -6,22 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x1E)]
-    public sealed class UnloadChunk : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class UnloadChunk : IPacket
     {
         [SerializeAs(DataType.Int)]
         public int ChunkX;
 
         [SerializeAs(DataType.Int)]
         public int ChunkZ;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsInt(ChunkX);
-            bw.WriteAsInt(ChunkZ);
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/UpdateHealth.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x49)]
-    public sealed class UpdateHealth : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class UpdateHealth : IPacket
     {
         [SerializeAs(DataType.Float)]
         public float Health;
@@ -20,12 +18,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Float)]
         public float FoodSaturation;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsFloat(Health);
-            bw.WriteAsVarInt(Food, out _);
-            bw.WriteAsFloat(FoodSaturation);
-        }
     }
 }

+ 2 - 19
src/MineCase.Protocol/Protocol/Play/UpdateViewPosition.cs

@@ -6,31 +6,14 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x41)]
-    public sealed class UpdateViewPosition : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class UpdateViewPosition : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public int ChunkX;
 
         [SerializeAs(DataType.VarInt)]
         public int ChunkZ;
-
-        public static UpdateViewPosition Deserialize(ref SpanReader br)
-        {
-            return new UpdateViewPosition
-            {
-                ChunkX = (int)br.ReadAsVarInt(out _),
-                ChunkZ = (int)br.ReadAsVarInt(out _),
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsVarInt((uint)ChunkX, out _);
-            bw.WriteAsVarInt((uint)ChunkZ, out _);
-        }
     }
 }

+ 15 - 17
src/MineCase.Protocol/Protocol/Play/UseEntity.cs

@@ -6,11 +6,8 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x0A)]
-    public sealed class UseEntity
+    public sealed class UseEntity : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public int Target;
@@ -30,26 +27,27 @@ namespace MineCase.Protocol.Play
         [SerializeAs(DataType.VarInt)]
         public int? Hand;
 
-        public static UseEntity Deserialize(ref SpanReader br)
+        public void Deserialize(ref SpanReader br)
         {
-            var packet = new UseEntity
-            {
-                Target = (int)br.ReadAsVarInt(out _),
-                Type = (int)br.ReadAsVarInt(out _)
-            };
+            Target = (int)br.ReadAsVarInt(out _);
+            Type = (int)br.ReadAsVarInt(out _);
 
             // Only if Type is interact at
-            if (packet.Type == 2)
+            if (Type == 2)
             {
-                packet.TargetX = br.ReadAsFloat();
-                packet.TargetY = br.ReadAsFloat();
-                packet.TargetZ = br.ReadAsFloat();
+                TargetX = br.ReadAsFloat();
+                TargetY = br.ReadAsFloat();
+                TargetZ = br.ReadAsFloat();
             }
 
             // Only if Type is interact or interact at
-            if (packet.Type == 0 || packet.Type == 2)
-                packet.Hand = (int)br.ReadAsVarInt(out _);
-            return packet;
+            if (Type == 0 || Type == 2)
+                Hand = (int)br.ReadAsVarInt(out _);
+        }
+
+        public void Serialize(BinaryWriter bw)
+        {
+            throw new NotImplementedException();
         }
     }
 }

+ 2 - 12
src/MineCase.Protocol/Protocol/Play/UseItem.cs

@@ -5,21 +5,11 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x2D)]
-    public sealed class UseItem
+    [GenerateSerializer]
+    public sealed partial class UseItem : IPacket
     {
         [SerializeAs(DataType.VarInt)]
         public Hand Hand;
-
-        public static UseItem Deserialize(ref SpanReader br)
-        {
-            return new UseItem
-            {
-                Hand = (Hand)br.ReadAsVarInt(out _)
-            };
-        }
     }
 }

+ 3 - 13
src/MineCase.Protocol/Protocol/Play/WindowItems.cs

@@ -7,11 +7,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x15)]
-    public sealed class WindowItems : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class WindowItems : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
@@ -19,15 +17,7 @@ namespace MineCase.Protocol.Play
         [SerializeAs(DataType.Short)]
         public short Count;
 
-        [SerializeAs(DataType.Array)]
+        [SerializeAs(DataType.SlotArray, ArrayLengthMember = nameof(Count))]
         public Slot[] Slots;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsByte(WindowId);
-            bw.WriteAsShort(Count);
-            foreach (var slot in Slots)
-                bw.WriteAsSlot(slot);
-        }
     }
 }

+ 2 - 11
src/MineCase.Protocol/Protocol/Play/WindowProperty.cs

@@ -6,11 +6,9 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Play
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x15)]
-    public sealed class WindowProperty : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class WindowProperty : IPacket
     {
         [SerializeAs(DataType.Byte)]
         public byte WindowId;
@@ -20,12 +18,5 @@ namespace MineCase.Protocol.Play
 
         [SerializeAs(DataType.Short)]
         public short Value;
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsByte(WindowId);
-            bw.WriteAsShort(Property);
-            bw.WriteAsShort(Value);
-        }
     }
 }

+ 2 - 0
src/MineCase.Protocol/Protocol/Protocol.cs

@@ -10,6 +10,8 @@ namespace MineCase.Protocol
 
         public const string VersionName = "1.15.2";
 
+        public const uint SetCompressionPacketId = 0x03;
+
         public static void ValidatePacketLength(uint length)
         {
             if (length > 16 * 1024)

+ 4 - 34
src/MineCase.Protocol/Protocol/Status/Ping.cs

@@ -6,49 +6,19 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Status
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x01)]
-    public sealed class Ping : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class Ping : IPacket
     {
         [SerializeAs(DataType.Long)]
         public long Payload;
-
-        public static Ping Deserialize(ref SpanReader br)
-        {
-            return new Ping
-            {
-                Payload = br.ReadAsLong(),
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsLong(Payload);
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x01)]
-    public sealed class Pong : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class Pong : IPacket
     {
         [SerializeAs(DataType.Long)]
         public long Payload;
-
-        public static Pong Deserialize(ref SpanReader br)
-        {
-            return new Pong
-            {
-                Payload = br.ReadAsLong(),
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsLong(Payload);
-        }
     }
 }

+ 4 - 30
src/MineCase.Protocol/Protocol/Status/Request.cs

@@ -6,44 +6,18 @@ using MineCase.Serialization;
 
 namespace MineCase.Protocol.Status
 {
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x00)]
-    public sealed class Request : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class Request : IPacket
     {
         public static readonly Request Empty = new Request();
-
-        public static Request Deserialize(ref SpanReader br)
-        {
-            return Empty;
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-        }
     }
 
-#if !NET46
-    [Orleans.Concurrency.Immutable]
-#endif
     [Packet(0x00)]
-    public sealed class Response : ISerializablePacket
+    [GenerateSerializer]
+    public sealed partial class Response : IPacket
     {
         [SerializeAs(DataType.String)]
         public string JsonResponse;
-
-        public static Response Deserialize(ref SpanReader br)
-        {
-            return new Response
-            {
-                JsonResponse = br.ReadAsString()
-            };
-        }
-
-        public void Serialize(BinaryWriter bw)
-        {
-            bw.WriteAsString(JsonResponse);
-        }
     }
 }

+ 13 - 3
src/MineCase.Protocol/Serialization/BinaryWriterExtensions.cs

@@ -43,9 +43,19 @@ namespace MineCase.Serialization
         public static void WriteAsIntArray(this BinaryWriter bw, int[] value)
         {
             foreach (var eachInt in value)
-            {
                 bw.WriteAsInt(eachInt);
-            }
+        }
+
+        public static void WriteAsVarIntArray(this BinaryWriter bw, uint[] value)
+        {
+            foreach (var eachInt in value)
+                bw.WriteAsVarInt(eachInt, out _);
+        }
+
+        public static void WriteAsSlotArray(this BinaryWriter bw, Slot[] value)
+        {
+            foreach (var slot in value)
+                bw.WriteAsSlot(slot);
         }
 
         public static void WriteAsString(this BinaryWriter bw, string value)
@@ -108,7 +118,7 @@ namespace MineCase.Serialization
         }
 
         public static void WriteAsArray<T>(this BinaryWriter bw, IReadOnlyList<T> array)
-            where T : ISerializablePacket
+            where T : IPacket
         {
             foreach (var item in array)
                 item.Serialize(bw);

+ 21 - 0
src/MineCase.Protocol/Serialization/GenerateSerializerAttribute.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Serialization
+{
+    public enum GenerateSerializerMethods
+    {
+        Serialize = 0,
+        Deserialize = 1,
+        Both = 2
+    }
+
+    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
+    public sealed class GenerateSerializerAttribute : Attribute
+    {
+        public GenerateSerializerMethods Methods { get; set; } = GenerateSerializerMethods.Both;
+    }
+}

+ 4 - 0
src/MineCase.Protocol/Serialization/SerializeAsAttribute.cs

@@ -28,6 +28,8 @@ namespace MineCase.Serialization
         ByteArray,
         IntArray,
         NbtArray,
+        VarIntArray,
+        SlotArray,
         Array
     }
 
@@ -36,6 +38,8 @@ namespace MineCase.Serialization
     {
         public DataType DataType { get; }
 
+        public string ArrayLengthMember { get; set; }
+
         public SerializeAsAttribute(DataType dataType)
         {
             DataType = dataType;

+ 76 - 18
src/MineCase.Protocol/Serialization/SpanReader.cs

@@ -1,14 +1,14 @@
 using System;
-using System.Collections.Generic;
+using System.Buffers.Binary;
 using System.IO;
 using System.IO.Pipelines;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Text;
-
 using MineCase.Nbt;
 using MineCase.Nbt.Serialization;
 using MineCase.Nbt.Tags;
+using MineCase.Protocol;
 
 namespace MineCase.Serialization
 {
@@ -30,6 +30,12 @@ namespace MineCase.Serialization
             _span = span;
         }
 
+        public Chat ReadAsChat()
+        {
+            string str = ReadAsString();
+            return Chat.Parse(str);
+        }
+
         public uint ReadAsVarInt(out int bytesRead)
         {
             int numRead = 0;
@@ -52,85 +58,95 @@ namespace MineCase.Serialization
             return result;
         }
 
+        public Angle ReadAsAngle()
+        {
+            return new Angle(ReadAsByte());
+        }
+
+        public Guid ReadAsUUID()
+        {
+            var bytes = ReadBytes(16);
+            return new Guid(bytes);
+        }
+
         public unsafe string ReadAsString()
         {
             var len = ReadAsVarInt(out _);
             var bytes = ReadBytes((int)len);
-            return Encoding.UTF8.GetString((byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(bytes)), bytes.Length);
+            return Encoding.UTF8.GetString(bytes);
         }
 
         public ushort ReadAsUnsignedShort()
         {
-            var value = _span.ReadBigEndian<ushort>();
+            var value = BinaryPrimitives.ReadUInt16BigEndian(_span);
             Advance(sizeof(ushort));
             return value;
         }
 
         public uint ReadAsUnsignedInt()
         {
-            var value = _span.ReadBigEndian<uint>();
+            var value = BinaryPrimitives.ReadUInt32BigEndian(_span);
             Advance(sizeof(uint));
             return value;
         }
 
         public ulong ReadAsUnsignedLong()
         {
-            var value = _span.ReadBigEndian<ulong>();
+            var value = BinaryPrimitives.ReadUInt64BigEndian(_span);
             Advance(sizeof(ulong));
             return value;
         }
 
         public int ReadAsInt()
         {
-            var value = _span.ReadBigEndian<int>();
+            var value = BinaryPrimitives.ReadInt32BigEndian(_span);
             Advance(sizeof(int));
             return value;
         }
 
         public long ReadAsLong()
         {
-            var value = _span.ReadBigEndian<long>();
+            var value = BinaryPrimitives.ReadInt64BigEndian(_span);
             Advance(sizeof(long));
             return value;
         }
 
         public byte PeekAsByte()
         {
-            var value = _span.ReadBigEndian<byte>();
-            return value;
+            return _span[0];
         }
 
         public byte ReadAsByte()
         {
-            var value = _span.ReadBigEndian<byte>();
+            var value = _span[0];
             Advance(sizeof(byte));
             return value;
         }
 
         public bool ReadAsBoolean()
         {
-            var value = _span.ReadBigEndian<bool>();
+            var value = Convert.ToBoolean(_span[0]);
             Advance(sizeof(bool));
             return value;
         }
 
         public short ReadAsShort()
         {
-            var value = _span.ReadBigEndian<short>();
+            var value = BinaryPrimitives.ReadInt16BigEndian(_span);
             Advance(sizeof(short));
             return value;
         }
 
         public float ReadAsFloat()
         {
-            var value = _span.ReadBigEndian<float>();
+            var value = BinaryPrimitives.ReadSingleBigEndian(_span);
             Advance(sizeof(float));
             return value;
         }
 
         public double ReadAsDouble()
         {
-            var value = _span.ReadBigEndian<double>();
+            var value = BinaryPrimitives.ReadDoubleBigEndian(_span);
             Advance(sizeof(double));
             return value;
         }
@@ -150,15 +166,42 @@ namespace MineCase.Serialization
 
         public int[] ReadAsIntArray(int length)
         {
+            var expectedLen = length * sizeof(int);
+            if (expectedLen > _span.Length)
+                throw new IndexOutOfRangeException();
+
             int[] ret = new int[length];
             for (int i = 0; i < length; ++i)
             {
-                ret[i] = ReadAsInt();
+                ret[i] = BinaryPrimitives.ReadInt32BigEndian(_span);
+                Advance(sizeof(int));
             }
 
             return ret;
         }
 
+        public uint[] ReadAsVarIntArray(int length)
+        {
+            var array = new uint[length];
+            var subReader = new SpanReader(_span);
+            for (int i = 0; i < array.Length; i++)
+                array[i] = subReader.ReadAsVarInt(out _);
+
+            _span = subReader._span;
+            return array;
+        }
+
+        public Slot[] ReadAsSlotArray(int length)
+        {
+            var array = new Slot[length];
+            var subReader = new SpanReader(_span);
+            for (int i = 0; i < array.Length; i++)
+                array[i] = subReader.ReadAsSlot();
+
+            _span = subReader._span;
+            return array;
+        }
+
         public NbtCompound ReadAsNbtTag()
         {
             NbtCompound nbt;
@@ -188,8 +231,7 @@ namespace MineCase.Serialization
 
         public Position ReadAsPosition()
         {
-            var value = _span.ReadBigEndian<ulong>();
-            Advance(sizeof(ulong));
+            var value = ReadAsUnsignedLong();
             return new Position
             {
                 X = SignBy26(value >> 38),
@@ -232,6 +274,22 @@ namespace MineCase.Serialization
             return slot;
         }
 
+        public T[] ReadAsArray<T>(int count)
+            where T : IPacket, new()
+        {
+            var array = new T[count];
+            var subReader = new SpanReader(_span);
+            for (int i = 0; i < array.Length; i++)
+            {
+                var item = new T();
+                item.Deserialize(ref subReader);
+                array[i] = item;
+            }
+
+            _span = subReader._span;
+            return array;
+        }
+
         private ReadOnlySpan<byte> ReadBytes(int length)
         {
             var bytes = _span.Slice(0, length);

+ 2 - 2
src/MineCase.Serialization/MineCase.Serialization.csproj

@@ -1,14 +1,14 @@
 <Project Sdk="Microsoft.NET.Sdk">
 
   <PropertyGroup>
-    <TargetFramework>netcoreapp3.1</TargetFramework>
+    <TargetFrameworks>net5.0</TargetFrameworks>
     <Configurations>Debug;Release;Appveyor;TravisCI</Configurations>
     <DebugType>full</DebugType>
     <DebugSymbols>true</DebugSymbols>
   </PropertyGroup>
 
   <ItemGroup>
-    <PackageReference Include="Microsoft.Orleans.Core" Version="3.1.0" />
+    <PackageReference Include="Microsoft.Orleans.Core" Version="3.2.0-rc2" />
     <PackageReference Include="MongoDB.Bson" Version="2.10.2" />
   </ItemGroup>
 

+ 1 - 1
src/MineCase.Server.Grains/Components/AddressByPartitionKeyComponent.cs

@@ -14,7 +14,7 @@ namespace MineCase.Server.Components
         public static readonly DependencyProperty<string> AddressByPartitionKeyProperty =
             DependencyProperty.Register("AddressByPartitionKey", typeof(AddressByPartitionKeyComponent), new PropertyMetadata<string>(string.Empty, OnAddressByPartitionKeyChanged));
 
-        public event EventHandler<(string oldKey, string newKey)> KeyChanged;
+        public event EventHandler<(string OldKey, string NewKey)> KeyChanged;
 
         public AddressByPartitionKeyComponent(string name = "addressByPartitionKey")
             : base(name)

+ 3 - 3
src/MineCase.Server.Grains/Components/GameTickComponent.cs

@@ -34,12 +34,12 @@ namespace MineCase.Server.Components
             AttachedObject.QueueOperation(TryUnsubscribe);
         }
 
-        private void OnAddressByPartitionKeyChanged(object sender, (string oldKey, string newKey) e)
+        private void OnAddressByPartitionKeyChanged(object sender, (string OldKey, string NewKey) e)
         {
             AttachedObject.QueueOperation(async () =>
             {
-                if (!string.IsNullOrEmpty(e.oldKey))
-                    await GrainFactory.GetGrain<ITickEmitter>(e.oldKey).Unsubscribe(AttachedObject);
+                if (!string.IsNullOrEmpty(e.OldKey))
+                    await GrainFactory.GetGrain<ITickEmitter>(e.OldKey).Unsubscribe(AttachedObject);
                 await TrySubscribe();
             });
         }

+ 3 - 3
src/MineCase.Server.Grains/Game/BlockEntities/Components/ChestComponent.cs

@@ -88,13 +88,13 @@ namespace MineCase.Server.Game.BlockEntities.Components
             if (NeighborEntity == null)
                 return AttachedObject.AsReference<IBlockEntity>();
 
-            async Task<(IBlockEntity entity, BlockWorldPos position)> GetPosition(IBlockEntity entity) =>
+            async Task<(IBlockEntity Entity, BlockWorldPos Position)> GetPosition(IBlockEntity entity) =>
                 (entity, await entity.GetPosition());
 
             // 按 X, Z 排序取最小
             return (from e in await Task.WhenAll(new[] { GetPosition(AttachedObject.AsReference<IBlockEntity>()), GetPosition(NeighborEntity) })
-                    orderby e.position.X, e.position.Z
-                    select e.entity).First();
+                    orderby e.Position.X, e.Position.Z
+                    select e.Entity).First();
         }
     }
 }

+ 4 - 4
src/MineCase.Server.Grains/Game/Blocks/ChestBlockHandler.cs

@@ -22,7 +22,7 @@ namespace MineCase.Server.Game.Blocks
         {
         }
 
-        public static readonly (int x, int z)[] CrossCoords = new[]
+        public static readonly (int X, int Z)[] CrossCoords = new[]
         {
             (-1, 0), (0, -1), (1, 0), (0, 1)
         };
@@ -32,7 +32,7 @@ namespace MineCase.Server.Game.Blocks
             bool hasNeighbor = false;
             foreach (var crossCoord in CrossCoords)
             {
-                var blockState = await world.GetBlockState(grainFactory, position.X + crossCoord.x, position.Y, position.Z + crossCoord.z);
+                var blockState = await world.GetBlockState(grainFactory, position.X + crossCoord.X, position.Y, position.Z + crossCoord.Z);
                 if (blockState.Id != (uint)BlockId) continue;
 
                 if (hasNeighbor) return false;
@@ -41,7 +41,7 @@ namespace MineCase.Server.Game.Blocks
                 // 再检查隔壁的隔壁是不是箱子
                 foreach (var crossCoord2 in CrossCoords)
                 {
-                    var blockState2 = await world.GetBlockState(grainFactory, position.X + crossCoord.x + crossCoord2.x, position.Y, position.Z + crossCoord.z + crossCoord2.z);
+                    var blockState2 = await world.GetBlockState(grainFactory, position.X + crossCoord.X + crossCoord2.X, position.Y, position.Z + crossCoord.Z + crossCoord2.Z);
                     if (blockState2.Id == (uint)BlockId) return false;
                 }
             }
@@ -79,7 +79,7 @@ namespace MineCase.Server.Game.Blocks
             BlockWorldPos? neighborPosition = null;
             foreach (var crossCoord in CrossCoords)
             {
-                var neighborPos = new BlockWorldPos(position.X + crossCoord.x, position.Y, position.Z + crossCoord.z);
+                var neighborPos = new BlockWorldPos(position.X + crossCoord.X, position.Y, position.Z + crossCoord.Z);
                 var neighborState = await world.GetBlockState(grainFactory, neighborPos);
                 if (neighborState.Id == (uint)BlockId)
                 {

+ 5 - 5
src/MineCase.Server.Grains/Game/Entities/Components/ActiveWorldPartitionComponent.cs

@@ -27,14 +27,14 @@ namespace MineCase.Server.Game.Entities.Components
                 .KeyChanged -= ActiveWorldPartitionComponent_KeyChanged;
         }
 
-        private void ActiveWorldPartitionComponent_KeyChanged(object sender, (string oldKey, string newKey) e)
+        private void ActiveWorldPartitionComponent_KeyChanged(object sender, (string OldKey, string NewKey) e)
         {
             AttachedObject.QueueOperation(async () =>
             {
-                if (!string.IsNullOrEmpty(e.oldKey))
-                    await GrainFactory.GetGrain<IWorldPartition>(e.oldKey).Leave(AttachedObject);
-                if (!string.IsNullOrEmpty(e.newKey))
-                    await GrainFactory.GetGrain<IWorldPartition>(e.newKey).Enter(AttachedObject);
+                if (!string.IsNullOrEmpty(e.OldKey))
+                    await GrainFactory.GetGrain<IWorldPartition>(e.OldKey).Leave(AttachedObject);
+                if (!string.IsNullOrEmpty(e.NewKey))
+                    await GrainFactory.GetGrain<IWorldPartition>(e.NewKey).Enter(AttachedObject);
             });
         }
     }

+ 3 - 3
src/MineCase.Server.Grains/Game/Entities/Components/BlockPlacementComponent.cs

@@ -35,12 +35,12 @@ namespace MineCase.Server.Game.Entities.Components
                 else
                 {
                     var heldItem = await AttachedObject.GetComponent<HeldItemComponent>().GetHeldItem();
-                    if (!heldItem.slot.IsEmpty)
+                    if (!heldItem.Slot.IsEmpty)
                     {
-                        var itemHandler = ItemHandler.Create(new ItemState { Id = (uint)heldItem.slot.BlockId, MetaValue = 0 });
+                        var itemHandler = ItemHandler.Create(new ItemState { Id = (uint)heldItem.Slot.BlockId, MetaValue = 0 });
                         if (itemHandler.IsPlaceable)
                         {
-                            await itemHandler.PlaceBy(AttachedObject, GrainFactory, world, location, heldItem.slot, face, cursorPosition);
+                            await itemHandler.PlaceBy(AttachedObject, GrainFactory, world, location, heldItem.Slot, face, cursorPosition);
                         }
                     }
                 }

+ 3 - 3
src/MineCase.Server.Grains/Game/Entities/Components/ColliderComponent.cs

@@ -37,13 +37,13 @@ namespace MineCase.Server.Game.Entities.Components
             AttachedObject.QueueOperation(TryUnsubscribe);
         }
 
-        private void AddressByPartitionKeyChanged(object sender, (string oldKey, string newKey) e)
+        private void AddressByPartitionKeyChanged(object sender, (string OldKey, string NewKey) e)
         {
             AttachedObject.QueueOperation(async () =>
             {
                 var shape = ColliderShape;
-                if (!string.IsNullOrEmpty(e.oldKey))
-                    await GrainFactory.GetGrain<ICollectableFinder>(e.oldKey).UnregisterCollider(AttachedObject);
+                if (!string.IsNullOrEmpty(e.OldKey))
+                    await GrainFactory.GetGrain<ICollectableFinder>(e.OldKey).UnregisterCollider(AttachedObject);
                 await TrySubscribe();
             });
         }

+ 1 - 1
src/MineCase.Server.Grains/Game/Entities/Components/DiggingComponent.cs

@@ -59,7 +59,7 @@ namespace MineCase.Server.Game.Entities.Components
             if (_diggingBlock != null)
             {
                 var heldItem = await AttachedObject.Ask(new AskHeldItem());
-                var itemHandler = ItemHandler.Create(new ItemState { Id = (uint)heldItem.slot.BlockId, MetaValue = 0 });
+                var itemHandler = ItemHandler.Create(new ItemState { Id = (uint)heldItem.Slot.BlockId, MetaValue = 0 });
 
                 var world = AttachedObject.GetWorld();
                 var usedTick = (await world.GetAge()) - _diggingStartTick;

+ 3 - 3
src/MineCase.Server.Grains/Game/Entities/Components/DiscoveryRegisterComponent.cs

@@ -30,12 +30,12 @@ namespace MineCase.Server.Game.Entities.Components
             AttachedObject.QueueOperation(TryUnsubscribe);
         }
 
-        private void AddressByPartitionKeyChanged(object sender, (string oldKey, string newKey) e)
+        private void AddressByPartitionKeyChanged(object sender, (string OldKey, string NewKey) e)
         {
             AttachedObject.QueueOperation(async () =>
             {
-                if (!string.IsNullOrEmpty(e.oldKey))
-                    await GrainFactory.GetGrain<IWorldPartition>(e.oldKey).UnsubscribeDiscovery(AttachedObject);
+                if (!string.IsNullOrEmpty(e.OldKey))
+                    await GrainFactory.GetGrain<IWorldPartition>(e.OldKey).UnsubscribeDiscovery(AttachedObject);
                 await TrySubscribe();
             });
         }

+ 1 - 1
src/MineCase.Server.Grains/Game/Entities/Components/EntityAiComponent.cs

@@ -335,7 +335,7 @@ namespace MineCase.Server.Game.Entities.Components
             }
         }
 
-        public static (float, float) VectorToYawAndPitch(Vector3 from, Vector3 to)
+        public static (float Yaw, float Pitch) VectorToYawAndPitch(Vector3 from, Vector3 to)
         {
             Vector3 v = to - from;
             v = Vector3.Normalize(v);

+ 3 - 3
src/MineCase.Server.Grains/Game/Entities/Components/HeldItemComponent.cs

@@ -6,7 +6,7 @@ using MineCase.Engine;
 
 namespace MineCase.Server.Game.Entities.Components
 {
-    internal class HeldItemComponent : Component<PlayerGrain>, IHandle<SetHeldItemIndex>, IHandle<AskHeldItem, (int index, Slot slot)>, IHandle<SetHeldItem>
+    internal class HeldItemComponent : Component<PlayerGrain>, IHandle<SetHeldItemIndex>, IHandle<AskHeldItem, (int Index, Slot Slot)>, IHandle<SetHeldItem>
     {
         public static readonly DependencyProperty<int> HeldItemIndexProperty =
             DependencyProperty.Register("HeldItemIndex", typeof(HeldItemComponent), new PropertyMetadata<int>(0));
@@ -18,7 +18,7 @@ namespace MineCase.Server.Game.Entities.Components
         {
         }
 
-        public async Task<(int index, Slot slot)> GetHeldItem()
+        public async Task<(int Index, Slot Slot)> GetHeldItem()
         {
             var inventory = AttachedObject.GetComponent<InventoryComponent>().GetInventoryWindow();
             var index = await inventory.GetHotbarGlobalIndex(AttachedObject, HeldItemIndex);
@@ -34,7 +34,7 @@ namespace MineCase.Server.Game.Entities.Components
             return Task.CompletedTask;
         }
 
-        Task<(int index, Slot slot)> IHandle<AskHeldItem, (int index, Slot slot)>.Handle(AskHeldItem message) =>
+        Task<(int Index, Slot Slot)> IHandle<AskHeldItem, (int Index, Slot Slot)>.Handle(AskHeldItem message) =>
             GetHeldItem();
 
         async Task IHandle<SetHeldItem>.Handle(SetHeldItem message)

+ 1 - 1
src/MineCase.Server.Grains/Game/Entities/Components/SlotContainerComponent.cs

@@ -14,7 +14,7 @@ namespace MineCase.Server.Game.Entities.Components
 
         private readonly int _slotsCount;
 
-        public event EventHandler<(int index, Slot slot)> SlotChanged;
+        public event EventHandler<(int Index, Slot Slot)> SlotChanged;
 
         public SlotContainerComponent(int slotsCount, string name = "slotContainer")
             : base(name)

+ 2 - 2
src/MineCase.Server.Grains/Game/Entities/Components/StandaloneHeldItemComponent.cs

@@ -6,7 +6,7 @@ using MineCase.Engine;
 
 namespace MineCase.Server.Game.Entities.Components
 {
-    internal class StandaloneHeldItemComponent : Component<EntityGrain>, IHandle<SetHeldItemIndex>, IHandle<AskHeldItem, (int index, Slot slot)>, IHandle<SetHeldItem>
+    internal class StandaloneHeldItemComponent : Component<EntityGrain>, IHandle<SetHeldItemIndex>, IHandle<AskHeldItem, (int Index, Slot Slot)>, IHandle<SetHeldItem>
     {
         public static readonly DependencyProperty<Slot> HeldItemProperty =
             DependencyProperty.Register("HeldItem", typeof(StandaloneHeldItemComponent), new PropertyMetadata<Slot>(Slot.Empty));
@@ -26,7 +26,7 @@ namespace MineCase.Server.Game.Entities.Components
             return Task.CompletedTask;
         }
 
-        Task<(int index, Slot slot)> IHandle<AskHeldItem, (int index, Slot slot)>.Handle(AskHeldItem message)
+        Task<(int Index, Slot Slot)> IHandle<AskHeldItem, (int Index, Slot Slot)>.Handle(AskHeldItem message)
         {
             return Task.FromResult((0, HeldItem));
         }

+ 2 - 2
src/MineCase.Server.Grains/Game/Entities/Components/SyncPlayerStateComponent.cs

@@ -172,9 +172,9 @@ namespace MineCase.Server.Game.Entities.Components
             AttachedObject.GetComponent<SlotContainerComponent>().SlotChanged += InventorySlotChanged;
         }
 
-        private void InventorySlotChanged(object sender, (int index, Slot slot) e)
+        private void InventorySlotChanged(object sender, (int Index, Slot Slot) e)
         {
-            AttachedObject.QueueOperation(() => _user.SetInventorySlot(e.index, e.slot));
+            AttachedObject.QueueOperation(() => _user.SetInventorySlot(e.Index, e.Slot));
         }
     }
 }

+ 1 - 1
src/MineCase.Server.Grains/Game/Items/ChestItemHandler.cs

@@ -32,7 +32,7 @@ namespace MineCase.Server.Game.Items
             for (int i = 0; i < ChestBlockHandler.CrossCoords.Length; i++)
             {
                 var crossCoord = ChestBlockHandler.CrossCoords[i];
-                var blockState = await world.GetBlockState(grainFactory, position.X + crossCoord.x, position.Y, position.Z + crossCoord.z);
+                var blockState = await world.GetBlockState(grainFactory, position.X + crossCoord.X, position.Y, position.Z + crossCoord.Z);
                 if (blockState.Id == (uint)BlockId.Chest)
                 {
                     neighborIdx = i;

+ 1 - 1
src/MineCase.Server.Grains/Game/Windows/InventoryWindowGrain.cs

@@ -38,7 +38,7 @@ namespace MineCase.Server.Game.Windows
         public Task UseItem(IPlayer player, int slotIndex)
         {
             var slotArea = GlobalSlotIndexToLocal(slotIndex);
-            return slotArea.slotArea.TryUseItem(player, slotArea.slotIndex);
+            return slotArea.SlotArea.TryUseItem(player, slotArea.SlotIndex);
         }
 
         public Task<Slot> GetHotbarItem(IPlayer player, int slotIndex)

+ 5 - 5
src/MineCase.Server.Grains/Game/Windows/SlotAreas/SlotArea.cs

@@ -281,11 +281,11 @@ namespace MineCase.Server.Game.Windows.SlotAreas
             foreach (var eachSlotIndex in dragSlotPath)
             {
                 var localSlot = GlobalSlotIndexToLocal(slotAreas, eachSlotIndex);
-                var eachSlot = await localSlot.slotArea.GetSlot(player, localSlot.slotIndex);
+                var eachSlot = await localSlot.SlotArea.GetSlot(player, localSlot.SlotIndex);
 
                 slot.ItemCount = (byte)Math.Min(MaxStackCount, eachSlot.ItemCount + averageNum);
 
-                await localSlot.slotArea.SetSlot(player, localSlot.slotIndex, slot);
+                await localSlot.SlotArea.SetSlot(player, localSlot.SlotIndex, slot);
 
                 if (eachSlot.IsEmpty)
                 {
@@ -337,11 +337,11 @@ namespace MineCase.Server.Game.Windows.SlotAreas
             foreach (var eachSlotIndex in dragSlotPath)
             {
                 var localSlot = GlobalSlotIndexToLocal(slotAreas, eachSlotIndex);
-                var eachSlot = await localSlot.slotArea.GetSlot(player, localSlot.slotIndex);
+                var eachSlot = await localSlot.SlotArea.GetSlot(player, localSlot.SlotIndex);
 
                 slot.ItemCount = (byte)Math.Min(MaxStackCount, eachSlot.ItemCount + averageNum);
 
-                await localSlot.slotArea.SetSlot(player, localSlot.slotIndex, slot);
+                await localSlot.SlotArea.SetSlot(player, localSlot.SlotIndex, slot);
 
                 if (eachSlot.IsEmpty)
                 {
@@ -419,7 +419,7 @@ namespace MineCase.Server.Game.Windows.SlotAreas
         }
 
         // TODO merge method in games/windows/WindowGrain.cs
-        protected (SlotArea slotArea, int slotIndex) GlobalSlotIndexToLocal(List<SlotArea> slotAreas, int slotIndex)
+        protected (SlotArea SlotArea, int SlotIndex) GlobalSlotIndexToLocal(List<SlotArea> slotAreas, int slotIndex)
         {
             for (int i = 0; i < slotAreas.Count; i++)
             {

Някои файлове не бяха показани, защото твърде много файлове са промени