Bläddra i källkod

server state storage

JasonWang 6 år sedan
förälder
incheckning
fb653b6ddb

+ 21 - 0
src/MineCase.Core/Util/Event/AsyncEventHandler.cs

@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace MineCase.Util.Event
+{
+    public delegate Task AsyncEventHandler<TEventArgs>(object sender, TEventArgs e);
+
+    public static class AsyncEventHandlerExtensions
+    {
+        public static async Task InvokeSerial<TEventArgs>(this AsyncEventHandler<TEventArgs> handler, object sender, TEventArgs e)
+        {
+            if (handler != null)
+            {
+                foreach (AsyncEventHandler<TEventArgs> invoke in handler.GetInvocationList())
+                    await invoke(sender, e);
+            }
+        }
+    }
+}

+ 3 - 3
src/MineCase.Core/World/Dimension/DimensionType.cs

@@ -6,8 +6,8 @@ namespace MineCase.Core.World.Dimension
 {
     public enum DimensionType
     {
-        Overworld,
-        TheNether,
-        TheEnd,
+        Overworld = 1,
+        TheNether = 0,
+        TheEnd = 2,
     }
 }

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

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.World
+{
+    public sealed class GameTickArgs
+    {
+
+        public long WorldAge { get; set; }
+
+        public long TimeOfDay { get; set; }
+    }
+}

+ 19 - 0
src/MineCase.Core/World/WorldSettings.cs

@@ -0,0 +1,19 @@
+using MineCase.Core.World;
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.World
+{
+    public class WorldSettings
+    {
+        private readonly long _seed;
+        private readonly GameType _gameType;
+        private readonly bool _mapFeaturesEnabled;
+        private readonly bool _hardcoreEnabled;
+        private readonly WorldType _terrainType;
+        private bool _commandsAllowed;
+        private bool _bonusChestEnabled;
+       //  private JsonElement generatorOptions = new JsonObject();
+    }
+}

+ 29 - 0
src/MineCase.Core/World/WorldType.cs

@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Core.World
+{
+    public enum WordldTypeId
+    {
+        Default = 0,
+        Flat = 1,
+        LargeBiomes = 2,
+        Amplified = 3,
+        Customized = 4,
+        Buffet = 5,
+    }
+
+    public class WorldTypes
+    {
+
+    }
+
+    public class WorldType
+    {
+        private readonly int _id;
+        private readonly String _name;
+        private readonly int _version;
+        private bool _isCustomized;
+    }
+}

+ 10 - 1
src/MineCase.Server.Grains/Server/MinecraftServer.cs

@@ -2,11 +2,20 @@
 using System.Collections.Generic;
 using System.Text;
 using System.Threading.Tasks;
+using MineCase.Core.World.Dimension;
+using MineCase.Server.World;
 using Orleans;
+using Orleans.Providers;
 
 namespace MineCase.Server.Server
 {
-    public class MinecraftServer : Grain, IMinecraftServer
+    public class MinecraftServerState
+    {
+        public Dictionary<DimensionType, IWorld> Worlds { get; set; } = new Dictionary<DimensionType, IWorld>();
+    }
+
+    [StorageProvider(ProviderName = "MongoDBStore")]
+    public class MinecraftServer : Grain<MinecraftServerState>, IMinecraftServer
     {
         public Task<int> GetNetworkCompressionThreshold()
         {

+ 2 - 2
src/MineCase.Server.Grains/World/Biome/Biome.cs

@@ -1,7 +1,7 @@
-using MineCase.World.Biome;
-using System;
+using System;
 using System.Collections.Generic;
 using System.Text;
+using MineCase.World.Biome;
 
 namespace MineCase.Server.World.Biome
 {

+ 14 - 0
src/MineCase.Server.Grains/World/Chunk/ChunkProvider.cs

@@ -0,0 +1,14 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Server.World.Chunk
+{
+    public class ChunkProvider
+    {
+        public ChunkProvider(WorldAccessor world)
+        {
+
+        }
+    }
+}

+ 24 - 1
src/MineCase.Server.Grains/World/World.cs

@@ -1,12 +1,35 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using System.Threading.Tasks;
 using Orleans;
 
 namespace MineCase.Server.World
 {
-    public class World : Grain, IWorld
+
+    public class WorldState
+    {
+        public long WorldAge { get; set; }
+
+        public uint NextAvailEId { get; set; }
+    }
+
+    public class World : Grain<WorldState>, IWorld
     {
+        public override async Task OnActivateAsync()
+        {
+            await base.OnActivateAsync();
+        }
+
+        public override async Task OnDeactivateAsync()
+        {
+            await WriteStateAsync();
+            await base.OnDeactivateAsync();
+        }
 
+        public Task<long> GetAge()
+        {
+            return Task.FromResult(State.WorldAge);
+        }
     }
 }

+ 17 - 0
src/MineCase.Server.Grains/World/WorldAccessor.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using Orleans;
+
+namespace MineCase.Server.World
+{
+    public class WorldAccessor
+    {
+        private IGrainFactory _grainFactory;
+
+        public WorldAccessor(IGrainFactory grainFactory)
+        {
+            _grainFactory = grainFactory;
+        }
+    }
+}

+ 64 - 0
src/MineCase.Server.Grains/World/WorldPartition.cs

@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Threading.Tasks;
+using MineCase.Server.World;
+using MineCase.Util.Event;
+using MineCase.Util.Math;
+using MineCase.World;
+using Orleans;
+
+namespace MineCase.Server.Grains.World
+{
+    public class WorldPartitionState
+    {
+    }
+
+    public class WorldPartition : Grain<WorldPartitionState>, IWorldPartition
+    {
+        private IDisposable _tickTimer;
+        private long _worldAge;
+
+        private static readonly long _updateMs = 50;
+
+        private IWorld _world = null;
+
+        public event AsyncEventHandler<GameTickArgs> Tick;
+
+        public override async Task OnActivateAsync()
+        {
+            await base.OnActivateAsync();
+
+            (string worldKey, ChunkPos chunkPos) = this.GetWorldAndChunkPos();
+            _world = GrainFactory.GetGrain<IWorld>(worldKey);
+        }
+
+        public override async Task OnDeactivateAsync()
+        {
+            await WriteStateAsync();
+            await base.OnDeactivateAsync();
+        }
+
+        public async Task StartTick()
+        {
+            _tickTimer?.Dispose();
+            _worldAge = await _world.GetAge();
+
+            _tickTimer = RegisterTimer(OnTick, null, TimeSpan.Zero, TimeSpan.FromMilliseconds(_updateMs));
+        }
+
+        public async Task OnTick(object arg)
+        {
+            var e = new GameTickArgs { WorldAge = _worldAge, TimeOfDay = _worldAge % 24000 };
+            await Tick.InvokeSerial(this, e);
+            _worldAge++;
+        }
+
+        public Task StopTick()
+        {
+            _tickTimer?.Dispose();
+            _tickTimer = null;
+            return Task.CompletedTask;
+        }
+    }
+}

+ 5 - 0
src/MineCase.Server.Interfaces/MineCase.Server.Interfaces.csproj

@@ -31,4 +31,9 @@
     <ProjectReference Include="..\MineCase.Protocol\MineCase.Protocol.csproj" />
   </ItemGroup>
 
+  <ItemGroup>
+    <Folder Include="World\Chunk\" />
+    <Folder Include="World\Biome\" />
+  </ItemGroup>
+
 </Project>

+ 46 - 0
src/MineCase.Server.Interfaces/World/IAddressByPartition.cs

@@ -0,0 +1,46 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using MineCase.Util.Math;
+using MineCase.World;
+using Orleans;
+using Orleans.Runtime;
+
+namespace MineCase.Server.World
+{
+    public interface IAddressByPartition : IGrainWithStringKey
+    {
+    }
+
+    public static class AddressByPartitionExtensions
+    {
+        public static string MakeAddressByPartitionKey(this IWorld world, ChunkPos chunkWorldPos)
+        {
+            return $"{world.GetPrimaryKeyString()},{chunkWorldPos.X},{chunkWorldPos.Z}";
+        }
+
+        public static TGrainInterface GetPartitionGrain<TGrainInterface>(this IGrainFactory grainFactory, IWorld world, ChunkPos chunkWorldPos)
+            where TGrainInterface : IAddressByPartition
+        {
+            return grainFactory.GetGrain<TGrainInterface>(MakeAddressByPartitionKey(world, chunkWorldPos));
+        }
+
+        public static TGrainInterface GetPartitionGrain<TGrainInterface>(this IGrainFactory grainFactory, IAddressByPartition another)
+            where TGrainInterface : IAddressByPartition
+        {
+            return grainFactory.GetGrain<TGrainInterface>(another.GetPrimaryKeyString());
+        }
+
+        public static ChunkPos GetChunkPos(this IAddressByPartition addressByPartition)
+        {
+            var key = addressByPartition.GetPrimaryKeyString().Split(',');
+            return new ChunkPos(int.Parse(key[1]), int.Parse(key[2]));
+        }
+
+        public static (string worldKey, ChunkPos chunkPos) GetWorldAndChunkPos(this IAddressByPartition addressByPartition)
+        {
+            var key = addressByPartition.GetPrimaryKeyString().Split(',');
+            return (key[0], new ChunkPos(int.Parse(key[1]), int.Parse(key[2])));
+        }
+    }
+}

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

@@ -1,11 +1,13 @@
 using System;
 using System.Collections.Generic;
 using System.Text;
+using System.Threading.Tasks;
 using Orleans;
 
 namespace MineCase.Server.World
 {
     public interface IWorld : IGrainWithStringKey
     {
+        Task<long> GetAge();
     }
 }

+ 10 - 0
src/MineCase.Server.Interfaces/World/IWorldPartition.cs

@@ -0,0 +1,10 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace MineCase.Server.World
+{
+    public interface IWorldPartition : IAddressByPartition
+    {
+    }
+}