コード例 #1
0
        static async Task Main(string[] args)
        {
            var serilogger = new LoggerConfiguration()
                             .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day)
                             .CreateLogger();
            var loggerFactory = LoggerFactory.Create(builder =>
            {
                builder
                // .AddFilter("Microsoft", LogLevel.Warning)
                // .AddFilter("System", LogLevel.Warning)
                // .AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
                .AddSerilog(serilogger)
                .AddConsole();
            });

            _logger = loggerFactory.CreateLogger <Program>();

            // Register extensions to Json.NET Serialization
            JsonConvert.DefaultSettings = () => new JsonSerializerSettings
            {
                Converters = new List <JsonConverter>
                {
                    new MathJsonConverter(),
                    Converter.DateTimeConverter,
                    Converter.BinaryConverter,
                    Converter.GroupingConverter,
                    Converter.PocoExprConverter
                }
            };
            Converter.Serializer.Converters.Add(new MathJsonConverter());

            // Register extensions to MessagePack Serialization
            var resolver = CompositeResolver.Create(
                MathResolver.Instance,
                NativeGuidResolver.Instance,
                StandardResolver.Instance
                );
            var options = MessagePackSerializerOptions.Standard.WithResolver(resolver);

            MessagePackSerializer.DefaultOptions = options;

            var connection = R.Connection().Hostname("asgard.gamecult.games")
                             .Port(RethinkDBConstants.DefaultPort).Timeout(60).Connect();

            var cache = new DatabaseCache();

            // When entries are changed locally, push the changes to RethinkDB
            cache.OnDataUpdateLocal += async entry =>
            {
                var table  = entry.GetType().GetCustomAttribute <RethinkTableAttribute>()?.TableName ?? "Other";
                var result = await R.Db("Aetheria").Table(table).Update(entry).RunAsync(connection);

                _logger.Log(LogLevel.Information, $"Uploaded entry to RethinkDB: {entry.ID} result: {result}");
            };

            cache.OnDataInsertLocal += async entry =>
            {
                var table    = entry.GetType().GetCustomAttribute <RethinkTableAttribute>()?.TableName ?? "Other";
                var inserted = false;
                for (int i = 0; i < 5 && !inserted; i++)
                {
                    try
                    {
                        var result = await R.Db("Aetheria").Table(table).Insert(entry).RunAsync(connection);

                        _logger.Log(LogLevel.Information, $"Inserted entry to RethinkDB: {entry.ID} result: {result}");
                        inserted = true;
                    }
                    catch (Exception e)
                    {
                        _logger.LogError(e, e.Message);
                    }
                }
                if (!inserted)
                {
                    _logger.LogError("Failed to insert after 5 attempts!");
                }
            };

            cache.OnDataDeleteLocal += async entry =>
            {
                var table  = entry.GetType().GetCustomAttribute <RethinkTableAttribute>()?.TableName ?? "Other";
                var result = await R.Db("Aetheria").Table(table).Get(entry.ID).Delete().RunAsync(connection);

                _logger.Log(LogLevel.Information, $"Deleted entry from RethinkDB: {entry.ID} result: {result}");
            };

            // Get data from RethinkDB
            await GetTable("Items", connection, cache);
            await GetTable("Galaxy", connection, cache);
            await GetTable("Users", connection, cache);

            // Subscribe to changes from RethinkDB
            SubscribeTable("Items", connection, cache);
            SubscribeTable("Galaxy", connection, cache);
            SubscribeTable("Users", connection, cache);

            var server = new MasterServer(cache)
            {
                Logger = _logger
            };

            server.Start();

            var context = new GameContext(cache, s => _logger.Log(LogLevel.Information, s));

            context.MapLayers = cache.GetAll <GalaxyMapLayerData>().ToDictionary(m => m.Name);

            server.AddMessageListener <GalaxyRequestMessage>(galaxyRequest => galaxyRequest.Peer.Send(
                                                                 new GalaxyResponseMessage
            {
                Zones = cache.GetAll <ZoneData>().Select(zd =>
                                                         new GalaxyResponseZone
                {
                    Name     = zd.Name,
                    Position = zd.Position,
                    ZoneID   = zd.ID,
                    Links    = zd.Wormholes?.ToArray() ?? Array.Empty <Guid>()
                }).ToArray(),
                GlobalData  = context.GlobalData,
                StarDensity = context.MapLayers["StarDensity"]
            }));

            server.AddMessageListener <BlueprintsRequestMessage>(blueprintRequest => blueprintRequest.Peer.Send(
                                                                     new BlueprintsResponseMessage
            {
                Blueprints = cache.GetAll <BlueprintData>().ToArray()
            }));

            server.AddMessageListener <ZoneRequestMessage>(zoneRequest =>
            {
                var zone = cache.Get <ZoneData>(zoneRequest.ZoneID);

                // Zone has not been populated, generate the contents now!
                if (!zone.Visited)
                {
                    zone.Visited = true;
                    OrbitData[] orbits;
                    PlanetData[] planets;
                    ZoneGenerator.GenerateZone(
                        global: context.GlobalData,
                        zone: zone,
                        mapLayers: context.MapLayers.Values,
                        resources: cache.GetAll <SimpleCommodityData>().Where(i => i.ResourceDensity.Any()),
                        orbitData: out orbits,
                        planetsData: out planets);
                    cache.AddAll(orbits);
                    cache.AddAll(planets);
                    cache.Add(zone);
                }
                zoneRequest.Peer.Send(
                    new ZoneResponseMessage
                {
                    Zone     = zone,
                    Contents = zone.Orbits.Select(id => cache.Get(id))
                               .Concat(zone.Planets.Select(id => cache.Get(id)))
                               .Concat(zone.Stations.Select(id => cache.Get(id))).ToArray()
                });
            });

            Observable.Timer(DateTimeOffset.Now, TimeSpan.FromSeconds(60)).SubscribeOn(NewThreadScheduler.Default).Subscribe(_ =>
            {
                _logger.Log(LogLevel.Information, R.Now().Run <DateTime>(connection).ToString() as string);
            });

            while (true)
            {
                Thread.Sleep(100);
            }
        }