Beispiel #1
0
        private static async Task Main(string[] args)
        {
            if (args.Length != 2)
            {
                throw new ArgumentException("Expected 2 argument.");
            }

            if (!Guid.TryParse(args[0], out var id))
            {
                throw new ArgumentException($"{args[0]} is not a valid GUID");
            }

            ServerSpecification specification;

            await using (var ctx = new NovaContext())
            {
                specification = await ctx.Specifications.FirstOrDefaultAsync(c => c.Id == id);

                if (specification == default)
                {
                    throw new ArgumentException($"{args[0]} is not a valid server specification ID");
                }
            }

            var server = new Server(specification.Id);

            await server.ConfigureAsync(args[1]);

            Logger.Information($"Starting server {server.Port}...");

            await server.Start();
        }
Beispiel #2
0
        public async Task ConfigureAsync(string configFile)
        {
            var serializer = new XmlSerializer(typeof(Configuration));

            await using var fs = File.OpenRead(configFile);

            Logger.Config = Config = (Configuration)serializer.Deserialize(fs);

            if (!File.Exists(configFile))
            {
                throw new ArgumentException($"{configFile} config file does not exist.");
            }

            if (!string.IsNullOrWhiteSpace(Config.ResourcesConfiguration?.GameResourceFolder))
            {
                Resources = new LocalResources(Config);
            }

            ServerSpecification specification;

            await using (var ctx = new NovaContext())
            {
                specification = await ctx.Specifications.FirstAsync(s => s.Id == Id);
            }

            Port = specification.Port;

            _server = new RakNetServer(Port, "3.25 ND1");
        }
Beispiel #3
0
        private static async Task AnswerRequest(WorldServerRequest request, ushort instanceId)
        {
            await using var ctx = new NovaContext();

            var req = await ctx.WorldServerRequests.FirstAsync(r => r.Id == request.Id);

            req.SpecificationId = await StartWorld(request.ZoneId, default, instanceId);
Beispiel #4
0
        private static async Task Main(string[] args)
        {
            await OpenConfig();

            await using (var ctx = new NovaContext())
            {
                await ctx.EnsureUpdatedAsync();

                foreach (var specification in ctx.Specifications)
                {
                    ctx.Specifications.Remove(specification);
                }

                foreach (var request in ctx.WorldServerRequests)
                {
                    ctx.WorldServerRequests.Remove(request);
                }

                await ctx.SaveChangesAsync();
            }

            await StartAuthentication();
            await StartCharacter();

            Console.CancelKeyPress += ShutdownProcesses;

            AppDomain.CurrentDomain.ProcessExit += ShutdownProcesses;

            await HandleRequests();
        }
Beispiel #5
0
        public async Task HandleMinifigureListRequest(MinifigureListRequestPacket packet, Connection connection)
        {
            await using var ctx = new NovaContext();

            if (connection.Username == default)
            {
                // Not yet validated

                return;
            }

            var account = await ctx.Accounts
                          .Include(a => a.Characters)
                          .FirstOrDefaultAsync(a => a.Username == connection.Username);

            if (account == default)
            {
                connection.Send(new MinifigureListResponsePacket());

                return;
            }

            account.Characters.Sort((u2, u1) =>
                                    DateTimeOffset.Compare(DateTimeOffset.FromUnixTimeSeconds(u1.LastActivity),
                                                           DateTimeOffset.FromUnixTimeSeconds(u2.LastActivity)));

            connection.Send(new MinifigureListResponsePacket
            {
                Characters = account.Characters
            });
        }
Beispiel #6
0
        private static async Task HandleRequest(WorldServerRequest request)
        {
            await using var ctx = new NovaContext();

            if (request.State == WorldServerRequestState.Unanswered)
            {
                //
                // Search for available server
                //

                foreach (var worldServer in WorldServers.Where(w => w.ZoneId == request.ZoneId))
                {
                    var specification = await ctx.Specifications.FirstAsync(s => s.Id == worldServer.Id);

                    if (specification.ActiveUserCount >= specification.MaxUserCount)
                    {
                        continue;
                    }

                    var req = await ctx.WorldServerRequests.FirstAsync(r => r.Id == request.Id);

                    req.SpecificationId = specification.Id;

                    req.State = WorldServerRequestState.Complete;

                    await ctx.SaveChangesAsync();

                    return;
                }

                //
                // Start new server
                //

                ushort instanceId = 0;

                for (var i = 0; i < ushort.MaxValue; i++)
                {
                    if (WorldServers.Any(w => w.InstanceId == instanceId))
                    {
                        instanceId++;

                        continue;
                    }

                    await AnswerRequest(request, instanceId);

                    break;
                }
            }
        }
Beispiel #7
0
        private static async Task HandleRequests()
        {
            while (true)
            {
                await Task.Delay(100);

                await using var ctx = new NovaContext();

                //
                // Cleanup
                //

                for (var index = 0; index < WorldServers.Count; index++)
                {
                    var worldServer = WorldServers[index];

                    if (worldServer.Process.HasExited)
                    {
                        WorldServers.RemoveAt(index);
                    }
                    else
                    {
                        var specifications = await ctx.Specifications.FirstAsync(w => w.Id == worldServer.Id);

                        if (specifications.ActiveUserCount != default)
                        {
                            worldServer.EmptyTime = default;

                            continue;
                        }

                        worldServer.EmptyTime++;

                        if (worldServer.EmptyTime != 10000)
                        {
                            continue;
                        }

                        // Evil, but works
                        worldServer.Process.Kill();

                        WorldServers.RemoveAt(index);
                    }
                }

                foreach (var request in ctx.WorldServerRequests)
                {
                    await HandleRequest(request);
                }
            }
        }
Beispiel #8
0
        public async Task HandleMinifigureCreation(CreateMinifigurePacket packet, Connection connection)
        {
            Logger.Information($"Creating character: {packet.MinifigureName}");

            await using var ctx = new NovaContext();

            var account = await ctx.Accounts
                          .Include(a => a.Characters)
                          .FirstOrDefaultAsync(a => a.Username == connection.Username);

            if (account == default)
            {
                connection.Send(new MinifigureListResponsePacket());

                return;
            }

            if (await ctx.Characters.AnyAsync(c => c.Name == packet.MinifigureName))
            {
                connection.Send(new CreateMinifigureResponsePacket
                {
                    ResponseCode = 3
                });

                return;
            }

            account.Characters.Add(new Character
            {
                Name       = packet.MinifigureName,
                ShirtColor = packet.ShirtColor,
                ShirtStyle = packet.ShirtStyle,
                PantsColor = packet.PantsColor,
                Eyebrows   = packet.Eyebrows,
                Eyes       = packet.Eyes,
                Rh         = packet.Rh,
                Lh         = packet.Lh,
                HairColor  = packet.HairColor,
                HairStyle  = packet.HairStyle,
                Mouth      = packet.Mouth,
                ObjectId   = IdUtilities.GenerateObjectId()
            });

            await ctx.SaveChangesAsync();

            connection.Send(new CreateMinifigureResponsePacket
            {
                ResponseCode = 0
            });

            await HandleMinifigureListRequest(default, connection);
Beispiel #9
0
        public static async Task RequestWorldServerAsync(ZoneId zoneId, Action <int> callback)
        {
            var id = Guid.NewGuid();

            await using (var ctx = new NovaContext())
            {
                await ctx.WorldServerRequests.AddAsync(new WorldServerRequest
                {
                    Id     = id,
                    ZoneId = zoneId
                });

                await ctx.SaveChangesAsync();
            }

            var _ = Task.Run(async() =>
            {
                var timeout = 1000;

                while (timeout != default)
                {
                    await using var ctx = new NovaContext();

                    var request = await ctx.WorldServerRequests.FirstAsync(r => r.Id == id);

                    if (request.State != WorldServerRequestState.Complete)
                    {
                        timeout--;

                        await Task.Delay(100).ConfigureAwait(false);

                        continue;
                    }

                    Logger.Information($"Request completed {id} {request.SpecificationId}");

                    ctx.WorldServerRequests.Remove(request);

                    await ctx.SaveChangesAsync();

                    var specification = await ctx.Specifications.FirstAsync(s => s.Id == request.SpecificationId);

                    callback(specification.Port);
                    return;
                }

                Logger.Error($"Request {id} timed out");
            });
        }
        public async Task HandleClientLogin(ClientLoginInfoPacket packet, Connection connection)
        {
            await using var ctx = new NovaContext();

            var account = await ctx.Accounts.FirstOrDefaultAsync(a => a.Username == packet.Username);

            if (account == default)
            {
                await ctx.Accounts.AddAsync(new Account
                {
                    Username = packet.Username,
                    Hash     = BCrypt.Net.BCrypt.EnhancedHashPassword(packet.Password)
                });

                await ctx.SaveChangesAsync();

                Logger.Information($"Created new account: {packet.Username}");

                connection.Send(new ClientLoginReplyPacket
                {
                    ResultCode    = LoginResultCode.Success,
                    NewServerIp   = "127.0.0.1",
                    NewServerPort = 2002
                });

                return;
            }

            if (!BCrypt.Net.BCrypt.EnhancedVerify(packet.Password, account.Hash))
            {
                connection.Send(new ClientLoginReplyPacket
                {
                    ResultCode    = LoginResultCode.IncorrectInfo,
                    NewServerIp   = "127.0.0.1",
                    NewServerPort = 1001
                });

                Logger.Information($"{packet.Username} failed to login");

                return;
            }

            connection.Send(new ClientLoginReplyPacket
            {
                ResultCode    = LoginResultCode.Success,
                NewServerIp   = "127.0.0.1",
                NewServerPort = 2002
            });
        }
Beispiel #11
0
        public Visma(int company)
        {
            this.company  = company;
            this._context = GetContext();

            vismaConnection = GetSqlConnection();

            otrivitTA            = new DataSetTableAdapters.OTRIVITableAdapter();
            otrivitTA.Connection = vismaConnection;

            varastoTA            = new DataSetTableAdapters.VARASTOTableAdapter();
            varastoTA.Connection = vismaConnection;

            hinnastoTA            = new DataSetTableAdapters.HINNASTOTableAdapter();
            hinnastoTA.Connection = vismaConnection;
        }
Beispiel #12
0
        /// <summary>
        /// Get Context object to Nova Visma instance.
        /// </summary>
        /// <returns></returns>
        public NovaContext GetContext()
        {
            string vismaServer   = ConfigurationSettings.AppSettings["Visma.Server"];
            string vismaUsername = ConfigurationSettings.AppSettings["Visma.Server"];
            string vismaPassword = ConfigurationSettings.AppSettings["Visma.Password"];
            int    vismaCompany  = this.company;

            NovaContext context;

            if (string.IsNullOrEmpty(vismaUsername) || string.IsNullOrEmpty(vismaPassword))
            {
                context = new NovaContext(vismaServer, vismaCompany);
            }
            else
            {
                context = new NovaContext(vismaServer, vismaUsername, vismaPassword, vismaCompany);
            }

            Nova.Configuration.Settings.SetDataConnectionString(context.CompanyConnectionString);

            return(context);
        }
        public async Task HandleClientLoaded(ClientLoadCompletePacket packet, Connection connection)
        {
            await using var ctx = new NovaContext();

            var account = await ctx.Accounts
                          .Include(a => a.Characters)
                          .FirstOrDefaultAsync(a => a.Username == connection.Username);

            if (account == default)
            {
                connection.Send(new DisconnectNotifyPacket
                {
                    ErrorCode = 1
                });

                return;
            }

            var character = account.Characters.FirstOrDefault(c => c.ObjectId == account.SelectedCharacter);

            if (character == default)
            {
                connection.Send(new DisconnectNotifyPacket
                {
                    ErrorCode = 1
                });

                return;
            }

            SendCharacterData(connection, character);

            connection.Send(new CharacterEndMarkerPacket
            {
                ServerOnline = true
            });
        }
Beispiel #14
0
        public async Task Start()
        {
            await using var ctx = new NovaContext();

            await ctx.EnsureUpdatedAsync();

            _server.Start();

            RegisterAssembly(typeof(Server).Assembly);
            RegisterAssembly(Assembly.GetEntryAssembly());

            _server.NewConnection += point =>
            {
                var connection = new Connection(point, _server);

                Connections.Add(connection);

                OnConnection?.Invoke(connection);
            };

            _server.Disconnection += point =>
            {
                var connection = Connections.FirstOrDefault(c => c.EndPoint.Equals(point));

                if (connection == default)
                {
                    return;
                }

                Connections.Remove(connection);

                OnDisconnect?.Invoke(connection);
            };

            _server.PacketReceived += (point, bytes) =>
            {
                var connection = Connections.FirstOrDefault(c => c.EndPoint.Equals(point));

                if (connection == default)
                {
                    Logger.Warning($"{point} is not connected but we still got data from them!");

                    return;
                }

                using var stream = new MemoryStream(bytes);

                using var reader = new BitReader(stream);

                var id = (MessageIdentifiers)reader.Read <byte>();

                if (id != MessageIdentifiers.UserPacketEnum)
                {
                    Logger.Error($"Invalid packet: {id}");

                    return;
                }

                HandlePacket(reader, connection);

                reader.BaseStream.Position = 0;

                OnPacket?.Invoke(connection, reader);
            };

            var request = ctx.WorldServerRequests.FirstOrDefault(w => w.SpecificationId == Id);

            if (request != default)
            {
                Logger.Information($"Request found for {Id}");

                request.State = WorldServerRequestState.Complete;

                await ctx.SaveChangesAsync();
            }

            await ctx.DisposeAsync();

            while (true)
            {
                var command = Console.ReadLine();
            }
        }
        public async Task HandleWorldLogin(WorldLoginPacket packet, Connection connection)
        {
            await using var ctx = new NovaContext();

            var account = await ctx.Accounts
                          .Include(a => a.Characters)
                          .FirstOrDefaultAsync(a => a.Username == connection.Username);

            if (account == default)
            {
                connection.Send(new DisconnectNotifyPacket
                {
                    ErrorCode = 1
                });

                return;
            }

            var character = account.Characters.FirstOrDefault(c => c.ObjectId == packet.MinifigureId);

            if (character == default)
            {
                connection.Send(new DisconnectNotifyPacket
                {
                    ErrorCode = 1
                });

                return;
            }

            if (character.LastZoneId == 0)
            {
                character.LastZoneId = ZoneId.VentureExplorer;
            }

            account.SelectedCharacter = character.ObjectId;

            character.LastActivity = DateTimeOffset.Now.ToUnixTimeSeconds();

            await ctx.SaveChangesAsync();

            if (Server.Port == 2002)
            {
                await Server.RequestWorldServerAsync(character.LastZoneId, port =>
                {
                    connection.Send(new TransferToWorldPacket
                    {
                        Ip   = "127.0.0.1",
                        Port = (ushort)port
                    });
                });

                return;
            }

            connection.Send(new LoadStaticZonePacket
            {
                ZoneId       = (ushort)character.LastZoneId,
                ZoneRevision = 5864,
                Instance     = 0,
                Clone        = 1
            });
        }
Beispiel #16
0
        public async Task HandleClientValidation(ValidateClientPacket packet, Connection connection)
        {
            await using var ctx = new NovaContext();

            var account = await ctx.Accounts
                          .Include(a => a.Characters)
                          .FirstOrDefaultAsync(a => a.Username == packet.Username);

            if (account == default)
            {
                connection.Send(new DisconnectNotifyPacket
                {
                    ErrorCode = 1
                });

                return;
            }

            Logger.Debug($"Client validating as: {packet.Username}");

            connection.Username = packet.Username;

            if (Server.Port == 2002)
            {
                if (!account.Characters.Any())
                {
                    return;
                }

                account.Characters.Sort((u2, u1) =>
                                        DateTimeOffset.Compare(DateTimeOffset.FromUnixTimeSeconds(u1.LastActivity),
                                                               DateTimeOffset.FromUnixTimeSeconds(u2.LastActivity)));

                connection.Send(new MinifigureListResponsePacket
                {
                    Characters = account.Characters.ToList()
                });

                return;
            }

            var character = account.Characters.FirstOrDefault(c => c.ObjectId == account.SelectedCharacter);

            if (character == null)
            {
                connection.Send(new DisconnectNotifyPacket
                {
                    ErrorCode = 1
                });

                return;
            }

            connection.Send(new LoadStaticZonePacket
            {
                ZoneId       = (ushort)character.LastZoneId,
                ZoneRevision = 5864,
                Instance     = 0,
                Clone        = 1
            });

            Logger.Information($"Sending {character.Name} to {character.LastZoneId}");
        }