示例#1
0
        public async void LoadObjects()
        {
            var objects = await ServerDB.SelectAllMapObjectsAsync(_mapID);

            if (objects?.Any() ?? false)
            {
                uint guid;
                foreach (var item in objects)
                {
                    if (item.ObjectID < 0)
                    {
                        guid = CreateNSObject(item);
                    }
                    else
                    {
                        guid = CreateNVObject(item);
                    }
                    ServerLogger.Log($"{_server.Name}({_mapID}): Created {(item.ObjectID < 0 ? "NS" : "NV")} object guid {guid:X8} at {item.Position}");
                }
            }
            if (!_nsObjects.ContainsKey(0))
            {
                ServerLogger.LogWarning($"{_server.Name}({_mapID}) default spawn point not found");
            }
        }
示例#2
0
        public void LoadObjects()
        {
            List <DB_WorldObject> objects;

            if (ServerDB.SelectAllMapObjects(_mapID, out objects) && objects != null)
            {
                uint guid;
                foreach (var item in objects)
                {
                    if (item.ObjectID < 0)
                    {
                        guid = CreateNSObject(item);
                    }
                    else
                    {
                        guid = CreateNVObject(item);
                    }
                    ServerLogger.Log($"{_server.Name}({_mapID}): Created {(item.ObjectID < 0 ? "NS" : "NV")} object guid {guid:X8} at {item.Position}");
                }
            }
            if (!_nsObjects.ContainsKey(0))
            {
                ServerLogger.LogWarn($"{_server.Name}({_mapID}) default spawn point not found");
            }
        }
        public static Assembly AssemblyResolveHandler(object sender, ResolveEventArgs args)
        {
            var logger = new ServerLogger();
            logger.Log(TraceEventType.Warning, "Resolving Assembly: " + args.Name);
            Assembly match = null;
            var argsParts = args.Name.Split(',');
            var targetToLower = (argsParts.Length > 0) ? argsParts[0].ToLower() : args.Name.ToLower();
            var basedir = AppDomain.CurrentDomain.BaseDirectory;
            var providersdir = Path.Combine(basedir, "Providers");
            var assemblypaths_all = Directory.GetFiles(providersdir)
                                .Where(q => q.ToLower().Contains(".dll"));

            var assemblypaths = assemblypaths_all
                .Where(q => q.ToLower().Contains(targetToLower)).ToList();

            var count = assemblypaths.Count;
            logger.Log(TraceEventType.Verbose, "Items found in Providers dir: {0}", count);

            foreach (var item in assemblypaths)
            {
                Assembly a1 = null;
                try { a1 = Assembly.LoadFile(item); }
                finally { }
                if (a1 != null)
                {
                    if (a1.FullName == args.Name)
                    {
                        match = a1;
                        break;
                    }

                    if (a1.FullName.StartsWith(args.Name))
                    {
                        match = a1;
                        break;
                    }
                }
            }

            if (match == null)
                logger.Log(TraceEventType.Warning, "NO Match found");
            else
                logger.Log(TraceEventType.Information, "Match found");

            logger = null;
            return match;
        }
示例#4
0
        public List <MapEntry> LoadMaps()
        {
            using var tr  = new StreamReader(@"Data/Maps.csv") as TextReader;
            using var csv = new CsvReader(tr, CultureInfo.CurrentCulture);

            var maps = csv.GetRecords <MapEntry>().ToList();

            ServerLogger.Log($"Loading maps: {maps.Count}");

            return(maps);
        }
示例#5
0
        private static void BuildCache()
        {
            ServerLogger.Log("Build path cache");

            nodeCache = new PathNode[MaxCacheSize];
            for (var i = 0; i < MaxCacheSize; i++)
            {
                var n = new PathNode(null, Position.Zero, 0);
                nodeCache[i] = n;
            }

            cachePos = MaxCacheSize;
        }
示例#6
0
        public Dictionary <string, List <MapConnector> > LoadConnectors(List <MapEntry> maps)
        {
            var connectors = new Dictionary <string, List <MapConnector> >();

            using var tr  = new StreamReader(@"Data/Connectors.csv") as TextReader;
            using var csv = new CsvReader(tr, CultureInfo.CurrentCulture);

            var connections = csv.GetRecords <CsvMapConnector>();
            var entryCount  = 0;

            foreach (var connector in connections)
            {
                if (string.IsNullOrWhiteSpace(connector.Source) || connector.Source.StartsWith("//") ||
                    connector.Source.StartsWith("#"))
                {
                    continue;
                }

                var con = new MapConnector()
                {
                    Map     = connector.Source,
                    SrcArea = Area.CreateAroundPoint(new Position(connector.X, connector.Y), connector.Width, connector.Height),
                    Target  = connector.Target,
                    DstArea = Area.CreateAroundPoint(new Position(connector.TargetX, connector.TargetY), connector.TargetWidth, connector.TargetHeight)
                };

                if (con.Map == null)
                {
                    continue;
                }

                if (!maps.Any(m => m.Code == con.Target))
                {
                    ServerLogger.LogWarning($"Connection on map {con.Map} goes to invalid map {con.Target}");
                    continue;
                }

                if (!connectors.ContainsKey(con.Map))
                {
                    connectors.Add(con.Map, new List <MapConnector>());
                }

                connectors[con.Map].Add(con);
                entryCount++;
            }

            ServerLogger.Log($"Loading connectors: {entryCount}");

            return(connectors);
        }
示例#7
0
        public MapSpawnDatabaseInfo LoadSpawnInfo()
        {
            var mapSpawns = new MapSpawnDatabaseInfo();

            mapSpawns.MapSpawnEntries = new Dictionary <string, List <MapSpawnEntry> >();

            using var tr  = new StreamReader(@"Data/MapSpawns.csv") as TextReader;
            using var csv = new CsvReader(tr, CultureInfo.CurrentCulture);

            var spawns = csv.GetRecords <CsvMapSpawnEntry>().ToList();

            var entryCount = 0;

            foreach (var spawn in spawns)
            {
                if (string.IsNullOrWhiteSpace(spawn.Map) || spawn.Map.StartsWith("//") || spawn.Map.StartsWith("#"))
                {
                    continue;
                }


                var entry = new MapSpawnEntry()
                {
                    X             = spawn.X,
                    Y             = spawn.Y,
                    Width         = spawn.Width,
                    Height        = spawn.Height,
                    Count         = spawn.Count,
                    Class         = spawn.Class,
                    SpawnTime     = spawn.SpawnTime,
                    SpawnVariance = spawn.Variance
                };


                if (!mapSpawns.MapSpawnEntries.ContainsKey(spawn.Map))
                {
                    mapSpawns.MapSpawnEntries.Add(spawn.Map, new List <MapSpawnEntry>());
                }

                mapSpawns.MapSpawnEntries[spawn.Map].Add(entry);
                entryCount++;
            }

            ServerLogger.Log($"Loading map spawn sets: {entryCount}");

            return(mapSpawns);
        }
示例#8
0
        private void Initialize()
        {
            ServerLogger.Log("Ragnarok Rebuild Zone Server, starting up!");


            DistanceCache.Init();
            DataManager.Initialize();

            world = new World();
            NetworkManager.Init(world);

            Profiler.Init(0.005f); //logs events for frames that take longer than 5ms

            Time.Start();

            GC.Collect();
            GCSettings.LatencyMode = GCLatencyMode.SustainedLowLatency;
        }
示例#9
0
        public static void ScanAndDisconnect()
        {
            var players        = State.Players;
            var disconnectList = State.DisconnectList;

            for (var i = 0; i < players.Count; i++)
            {
                if (players[i].ClientConnection.Status == NetConnectionStatus.Disconnected ||
                    players[i].ClientConnection.Status == NetConnectionStatus.Disconnecting)
                {
                    disconnectList.Add(players[i]);
                }
                else
                {
                    if (players[i].Character == null)
                    {
                        if (players[i].LastKeepAlive + 20 < Time.ElapsedTime)
                        {
                            disconnectList.Add(players[i]);
                        }
                    }
                    else
                    {
                        if (players[i].Character.IsActive && players[i].LastKeepAlive + 20 < Time.ElapsedTime)
                        {
                            disconnectList.Add(players[i]);
                        }
                        if (!players[i].Character.IsActive && players[i].LastKeepAlive + 120 < Time.ElapsedTime)
                        {
                            disconnectList.Add(players[i]);
                        }
                    }
                }
            }

            for (var i = 0; i < disconnectList.Count; i++)
            {
                var player = disconnectList[i];
                ServerLogger.Log($"[Network] Player {player.Entity} has disconnected, removing from world.");
                DisconnectPlayer(player);
            }

            disconnectList.Clear();
        }
示例#10
0
        public static void StartPolicyServer()
        {
            //policy server is required for web build to connect
            const string allPolicy =
                @"<?xml version='1.0'?>
<cross-domain-policy>
        <allow-access-from domain=""*"" to-ports=""*"" />
</cross-domain-policy>";

            State.PolicyServer = new SocketPolicyServer(allPolicy);
            int ret = State.PolicyServer.Start();

            if (ret != 0)
            {
                ServerLogger.Log("Failed to start policy server.");
            }
            else
            {
                ServerLogger.Log("Policy service started.");
            }
        }
示例#11
0
        public List <MonsterDatabaseInfo> LoadMonsterStats()
        {
            using var tr  = new StreamReader(@"Data/Monsters.csv") as TextReader;
            using var csv = new CsvReader(tr, CultureInfo.CurrentCulture);

            var monsters = csv.GetRecords <CsvMonsterData>().ToList();

            var obj = new List <MonsterDatabaseInfo>(monsters.Count);

            foreach (var monster in monsters)
            {
                if (monster.Id <= 0)
                {
                    continue;
                }

                obj.Add(new MonsterDatabaseInfo()
                {
                    Id                 = monster.Id,
                    Code               = monster.Code,
                    HP                 = monster.HP,
                    Range              = monster.Range > 0 ? monster.Range : 1,
                    ScanDist           = monster.ScanDist,
                    ChaseDist          = monster.ChaseDist,
                    AtkMin             = monster.AtkMin,
                    AtkMax             = monster.AtkMax,
                    AttackTime         = monster.AttackTime / 1000f,
                    HitTime            = monster.HitTime / 1000f,
                    RechargeTime       = monster.RechargeTime / 1000f,
                    MoveSpeed          = monster.MoveSpeed / 1000f,
                    SpriteAttackTiming = monster.SpriteAttackTiming / 1000f,
                    AiType             = (MonsterAiType)Enum.Parse(typeof(MonsterAiType), monster.MonsterAiType),
                    Name               = monster.Name
                });
            }

            ServerLogger.Log($"Loading monsters: {obj.Count}");

            return(obj);
        }
示例#12
0
        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            ServerLogger.RegisterLogger(logger);
            Initialize();

            var stopwatch = new Stopwatch();

            stopwatch.Start();

            var total = 0d;
            var max   = 0d;
            var spos  = 0;

            var totalNetwork = 0d;
            var totalEcs     = 0d;
            var totalWorld   = 0d;
            var maxNetwork   = 0d;
            var maxEcs       = 0d;
            var maxWorld     = 0d;

#if DEBUG
            var noticeTime = 5f;
#else
            var noticeTime = 60f;
#endif
            var lastLog = Time.ElapsedTime - noticeTime + 5f; //make the first check-in 5s after start no matter what

            while (!stoppingToken.IsCancellationRequested)
            {
                Time.Update();

                var startTime = Time.GetExactTime();

                NetworkManager.ProcessIncomingMessages();

                var networkTime = Time.GetExactTime();

                world.RunEcs();

                var ecsTime = Time.GetExactTime();

                world.Update();

                var worldTime = Time.GetExactTime();

                var elapsed = Time.GetExactTime() - startTime;
                //Console.WriteLine(elapsed);
                total += elapsed;

                Profiler.FinishFrame((float)elapsed);

                var nt = networkTime - startTime;
                var et = ecsTime - networkTime;
                var wt = worldTime - ecsTime;

                totalNetwork += nt;
                totalEcs     += et;
                totalWorld   += wt;

                if (max < elapsed)
                {
                    max = elapsed;
                }

                if (maxNetwork < nt)
                {
                    maxNetwork = nt;
                }
                if (maxEcs < et)
                {
                    maxEcs = et;
                }
                if (maxWorld < wt)
                {
                    maxWorld = wt;
                }

                spos++;


                var ms = (int)(elapsed * 1000) + 1;

                if (ms < 10)
                {
                    await Task.Delay(10 - ms, stoppingToken);
                }

                if (lastLog + noticeTime < Time.ElapsedTime)
                {
                    var avg = (total / spos);
                    //var fps = 1 / avg;
                    var players = NetworkManager.PlayerCount;

                    avg *= 1000d;

                    //var avgNetwork = (totalNetwork / spos) * 1000d;
                    //var avgEcs = (totalEcs / spos) * 1000d;
                    //var avgWorld = (totalWorld / spos) * 1000d;

#if DEBUG
                    var server = NetworkManager.State.Server;
                    ServerLogger.Log(
                        $"[Program] {players} players. Avg {avg:F2}ms / Peak {max * 1000:F2}ms "
                        + $"(Net/ECS/World: {maxNetwork * 1000:F2}/{maxEcs * 1000:F2}/{maxWorld:F2}) "
                        + $"Sent {server.Statistics.SentBytes}bytes/{server.Statistics.SentMessages}msg/{server.Statistics.SentPackets}packets");
#else
                    ServerLogger.Log(
                        $"[Program] {players} players. Avg {avg:F2}ms / Peak {max * 1000:F2}ms "
                        + $"(Net/ECS/World: {maxNetwork * 1000:F2}/{maxEcs * 1000:F2}/{maxWorld:F2})");
#endif
                    lastLog = Time.ElapsedTime;

                    total = 0;
                    max   = 0;
                    spos  = 0;

                    totalNetwork = 0;
                    totalWorld   = 0;
                    totalEcs     = 0;
                    maxNetwork   = 0;
                    maxWorld     = 0;
                    maxEcs       = 0;

                    NetworkManager.ScanAndDisconnect();
                }
            }

            logger.LogCritical("Oh no! We've dropped out of the processing loop! We will now shutdown.");
            appLifetime.StopApplication();
        }
示例#13
0
        public static void Init(World gameWorld)
        {
            State       = new ServerState();
            State.World = gameWorld;

            //policy server is required for web build, but since webGL doesn't support lidgren, it's disabled
            //StartPolicyServer();

            if (!DataManager.TryGetConfigInt("Port", out var port))
            {
                throw new Exception("Configuration does not have value for port!");
            }
            if (!DataManager.TryGetConfigInt("MaxConnections", out var maxConnections))
            {
                throw new Exception("Configuration does not have value for max connections!");
            }

            if (DataManager.TryGetConfigInt("Debug", out var debug))
            {
                State.DebugMode = debug == 1;
            }

#if DEBUG
            State.DebugMode = true;
#else
            ServerLogger.LogWarning("Server is started using debug mode config flag! Be sure this is what you want.");
#endif

            ServerLogger.Log($"Starting server listening on port {port}, with a maximum of {maxConnections} connections.");

            //Alright, now onto the regular server.
            State.Config      = new NetPeerConfiguration("RebuildZoneServer");
            State.Config.Port = port;
            State.Config.MaximumConnections = maxConnections;
            State.Config.EnableMessageType(NetIncomingMessageType.ConnectionApproval);

            State.Server = new NetServer(State.Config);
            State.Server.Start();

            var handlerCount = System.Enum.GetNames(typeof(PacketType)).Length;
            State.PacketHandlers = new Action <NetIncomingMessage> [handlerCount];

            foreach (var type in Assembly.GetAssembly(typeof(NetworkManager)).GetTypes()
                     .Where(t => t.IsClass && t.IsSubclassOf(typeof(ClientPacketHandler))))
            {
                var handler    = (ClientPacketHandler)Activator.CreateInstance(type);
                var packetType = handler.PacketType;
                handler.State = State;

                if (State.PacketHandlers[(int)packetType] != null)
                {
                    throw new Exception($"Duplicate packet handler exists for type {packetType}!");
                }

                State.PacketHandlers[(int)packetType] = handler.HandlePacket;
            }

            for (var i = 0; i < handlerCount; i++)
            {
                if (State.PacketHandlers[i] == null)
                {
                    ServerLogger.Debug($"No packet handler for packet type PacketType.{(PacketType) i} exists.");
                    State.PacketHandlers[i] = State.PacketHandlers[(int)PacketType.UnhandledPacket];
                }
            }

            ServerLogger.Log("Server started.");
        }
示例#14
0
        public World()
        {
            Instance = this;

            var initialMaxEntities = NextPowerOf2(initialEntityCount);

            if (initialMaxEntities < 1024)
            {
                initialMaxEntities = 1024;
            }

            ecsWorld = new EcsWorld(initialMaxEntities);

            ecsSystems = new EcsSystems(ecsWorld)
                         .Inject(this)
                         .Add(new MonsterSystem())
                         .Add(new CharacterSystem())
                         .Add(new PlayerSystem());

            ecsSystems.Init();

            if (DataManager.TryGetConfigValue("SingleMobTest", out var mobName))
            {
                DataManager.DoSingleMobTest(mobName);
            }

            var maps = DataManager.Maps;

            var entities = 0;

            for (var j = 0; j < maps.Count; j++)
            {
                var mapData = maps[j];
                try
                {
                    var map = new Map(this, mapData.Code, mapData.WalkData);
                    map.Id = j;

                    mapIdLookup.Add(mapData.Code, j);

                    var spawns = DataManager.GetSpawnsForMap(mapData.Code);

                    if (spawns != null)
                    {
                        for (var i = 0; i < spawns.Count; i++)
                        {
                            var s     = spawns[i];
                            var mobId = DataManager.GetMonsterIdForCode(s.Class);

                            for (var k = 0; k < s.Count; k++)
                            {
                                var m = CreateMonster(map, mobId, s.X, s.Y, s.Width, s.Height, s);
                                if (!m.IsNull())
                                {
                                    map.AddEntity(ref m);
                                    entities++;
                                }
                            }
                        }
                    }

                    var connectors = DataManager.GetMapConnectors(mapData.Code);

                    if (connectors != null)
                    {
                        for (var i = 0; i < connectors.Count; i++)
                        {
                            var c     = connectors[i];
                            var mobId = 1000;

                            var m = CreateMonster(map, mobId, c.SrcArea.MidX, c.SrcArea.MidY, 0, 0, null);
                            if (!m.IsNull())
                            {
                                map.AddEntity(ref m);
                            }
                        }
                    }

                    Maps.Add(map);
                }
                catch (Exception e)
                {
                    ServerLogger.LogError($"Failed to load map {mapData.Name} ({mapData.Code}) due to error while loading: {e.Message}");
                }
            }

            mapCount = maps.Count;

            ServerLogger.Log($"World started with {entities} entities.");
        }