コード例 #1
0
 public static IEntityHandle Player(string name, IGameServer server, IPosition pos)
 {
     var players = server.Services.ThrowOrGet<PlayerCatalogue>();
     var p = players.Create(SerializablePlayerModel.Default(name, server.Services.ThrowOrGet<SkillDb>()), MockSocketContext.Instance, MockPacketParser.Instance, new PacketHandlerCatalogue(server.Services));
     p.Get().GetTransform().Teleport(pos);
     return p;
 }
コード例 #2
0
 public NormalPlayerLogin(
     IServiceProvider services,
     string greeting,
     [NotNull] SerializablePlayerModel model,
     [NotNull] Socket connection,
     int signlinkUid)
 {
     Model       = model ?? throw new ArgumentNullException(nameof(model));
     Connection  = connection ?? throw new ArgumentNullException(nameof(connection));
     Catalogue   = services.ThrowOrGet <PlayerCatalogue>();
     Services    = services;
     Greeting    = greeting;
     SignlinkUid = signlinkUid;
 }
コード例 #3
0
        public IEntityHandle Create(
            [NotNull] SerializablePlayerModel model,
            [NotNull] ISocketContext socket,
            [NotNull] IPacketParser packetParser,
            [NotNull] IPacketHandlerCatalogue packets)
        {
            if (model == null)
            {
                throw new ArgumentNullException(nameof(model));
            }
            if (socket == null)
            {
                throw new ArgumentNullException(nameof(socket));
            }
            if (packetParser == null)
            {
                throw new ArgumentNullException(nameof(packetParser));
            }
            if (packets == null)
            {
                throw new ArgumentNullException(nameof(packets));
            }

            var id = GetId();

            if (id == InvalidPlayerId)
            {
                return(null);
            }

            Debug.Assert(InstanceLookup[id] == null);

            var entHandle = EntitySystem.Create($"Entity for player {model.Username}");
            var ent       = entHandle.Get();

            ent.Components.Add(new MessageLogComponent(ent));
            ent.Components.Add(new MessageNetworkSyncComponent(ent));

//#if DEBUG
            ent.Components.Add(new DebugStatNetworkSyncComponent(ent));
//#endif

            ent.Components.Add(new NetworkingComponent(ent, socket, packetParser));
            ent.Components.Add(new PacketDispatcherComponent(ent, packets));
            ent.Components.Add(new FlagAccumulatorComponent(ent));
            ent.Components.Add(new MarkedForDeathBroadcasterComponent(ent));

            var client = new ClientPositionComponent(ent);

            ent.Components.Add(client);
            ent.Components.Add <IClientPositionComponent>(client);

            ent.Components.Add(new RegionNetworkSyncComponent(ent));

            var health = new HealthComponent(ent);

            ent.Components.Add(health);
            ent.Components.Add <IHealthComponent>(health);

            var cmb = new CombatStatComponent(ent);

            ent.Components.Add(cmb);
            ent.Components.Add <ICombatStatComponent>(cmb);
            ent.Components.Add(new CombatStatNetworkSyncComponent(ent));

            var interf = new InterfaceComponent(ent);

            ent.Components.Add(interf);
            ent.Components.Add <IInterfaceComponent>(interf);
            ent.Components.Add(new InterfaceNetworkSyncComponent(ent));

            var skills = new SkillComponent(ent);

            ent.Components.Add(skills);
            ent.Components.Add <ISkillComponent>(skills);
            ent.Components.Add(new SkillNetworkSyncComponent(ent));

            var vision = new CappedVisionComponent(ent);

            ent.Components.Add(vision);
            ent.Components.Add <IVisionComponent>(vision);
            ent.Components.Add(new NearbyEntityWatcherComponent(ent));

            ent.Components.Add(new NpcNetworkSyncComponent(ent));
            ent.Components.Add(new PlayerNetworkSyncComponent(ent));
            ent.Components.Add(new GroundItemNetworkSyncComponent(ent));

            ent.Components.Add(new TileMovementComponent(ent));
            ent.Components.Add(new MovementActionComponent(ent));

            ent.Components.Add(new ItemActionDispatchComponent(ent));

            var inv = new PlayerInventoryComponent(ent,
                                                   new ListItemContainer(ent, model.Backpack),
                                                   new PlayerEquipmentContainer(ent, model.Equipment),
                                                   new ListItemContainer(ent, model.Bank));

            ent.Components.Add(inv);
            ent.Components.Add <IInventoryComponent>(inv);

            var player = new PlayerComponent(ent,
                                             model.Username,
                                             model.Apperance,
                                             true,
                                             model.TitleId,
                                             id,
                                             DestroyCallback);

            ent.Components.Add(player);
            ent.Components.Add <IPlayerComponent>(player);

            var check = ent.AreComponentRequirementsSatisfied(out var msg);

            if (!check)
            {
                throw new InvalidOperationException(msg);
            }

            // setup skills
            foreach (var skill in model.Skils)
            {
                skills.All.Add(skill.Key, new NormalSkillModel(skill.Key, skill.Value.Boost, skill.Value.Experience));
            }

            // setup health

            health.SetNewMaxHealth(skills.All[SkillDb.Hitpoints].Level);
            health.SetNewHealth(model.Health);

            InstanceLookup[id] = entHandle;
            _usernameLookup.Add(model.Username, entHandle);
            NumAlivePlayers++;

            // teleport player to pos
            ent.GetTransform().Teleport(model.PosX, model.PosY, model.PosZ);

            // init components
            ent.SendMessage(NotificationMessage.Initialize);

            return(entHandle);
        }
コード例 #4
0
        private async Task InitConnection(Socket socket)
        {
            try
            {
                const int loginMagic         = 10;
                const int reconnectMagic     = 18;
                const int normalConnectMagic = 16;
                const int crcCount           = 9;
                const int initMagicZeroCount = 8;
                const int initHandshakeMagic = 14;
                const int keyCount           = 4;
                const int randomKeySize      = sizeof(long);

                _log.Debug(this, "Initializing socket");

                var blob = new Blob(256);

                // initial handshake
                await SocketReceive(socket, blob, 2);

                var magic = blob.ReadByte();
                if (magic != initHandshakeMagic)
                {
                    _log.Debug(this, $"Killing socket due to back handshake magic ({magic})");
                    socket.Dispose();
                    return;
                }

                // another byte contains a bit of the username but we dont care about that
                blob.ReadCaret++;

                for (var i = 0; i < initMagicZeroCount; i++)
                {
                    blob.Write(0);
                }

                var sState = _server.GetState();
                if (sState.HasFlag(ServerStateFlags.PlayersFull))
                {
                    await KillBadConnection(socket, blob, InitResponseCode.WorldIsFull);

                    return;
                }
                if (sState.HasFlag(ServerStateFlags.LoginDisabled))
                {
                    await KillBadConnection(socket, blob, InitResponseCode.LoginServerOffline);

                    return;
                }

                // initMagicZeroCount can be any InitResponseCode
                blob.Write((byte)InitResponseCode.ContinueToCredentials);

                // write server isaac key
                var serverKey = new byte[randomKeySize];
                _rng.NextBytes(serverKey);
                blob.WriteBlock(serverKey, 0, randomKeySize);

                // send the packet
                await SocketSend(socket, blob);

                // receive login block
                // header
                await SocketReceive(socket, blob, blob.Buffer.Length);

                // todo : catch crypto exceptions
                var decrypted = _crypto.ProcessBlock(blob.Buffer, 0, blob.Buffer.Length);
                blob.Overwrite(decrypted, 0, 0);

                // verify login header magic
                magic = blob.ReadByte();
                if (magic != normalConnectMagic && magic != reconnectMagic)
                {
                    await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure,
                                            $"Invalid login block magic: {magic}");

                    return;
                }

                var isReconnecting = magic == reconnectMagic;

                //1 - length
                //2  - 255
                // skip 'em
                blob.ReadCaret += 2;

                // verify revision
                var revision = blob.ReadInt16();
                if (revision != _revision)
                {
                    await KillBadConnection(socket, blob, InitResponseCode.MustUpdate);

                    return;
                }

                var isLowMem = blob.ReadByte() == 1;

                // read crcs
                var crcs = new int[crcCount];
                for (var i = 0; i < crcCount; i++)
                {
                    crcs[i] = blob.ReadInt32();
                }

                // login block
                // check login magic
                magic = blob.ReadByte();
                if (magic != loginMagic)
                {
                    await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure,
                                            $"Invalid login magic: {magic}");

                    return;
                }

                // read client&server keys
                var keys = new int[keyCount];
                for (var i = 0; i < keyCount; i++)
                {
                    keys[i] = blob.ReadInt32();
                }

                var signlinkUid = blob.ReadInt32();

                // try read user/pass
                string username;
                string password;
                if (!blob.TryReadString(out username, PlayerComponent.MaxUsernameChars))
                {
                    await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure,
                                            "Overflow detected when reading username.");

                    return;
                }

                if (!blob.TryReadString(out password, PlayerComponent.MaxPasswordChars))
                {
                    await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure,
                                            "Overflow detected when reading password.");

                    return;
                }

                username = username.ToLowerInvariant();

                // check if user is logged in
                var loggedInPlayer = _players.Get(username);

                if (isReconnecting)
                {
                    // check if valid user
                    if (loggedInPlayer == null)
                    {
                        await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure,
                                                "Tried to reconnect to player that is not present in ent pool.");

                        return;
                    }

                    var net    = loggedInPlayer.Get().GetNetwork();
                    var player = loggedInPlayer.Get().AssertGetPlayer();
                    if (net == null)
                    {
                        await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure,
                                                "Reconnect player target exists with no network component.");

                        return;
                    }

                    // check if we can reconnect
                    if (!net.CanReinitialize(signlinkUid))
                    {
                        await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure,
                                                "Tried to reconnect but player is not available for reconnecting.");

                        return;
                    }

                    // check if the password matches
                    if (!_db.IsValidPassword(player.Username, password))
                    {
                        await KillBadConnection(socket, blob, InitResponseCode.InvalidCredentials);

                        return;
                    }

                    // all's good, queue reconnect.
                    blob.Write((byte)InitResponseCode.ReconnectDone);
                    _loginQueue.Enqueue(new ReconnectPlayerLogin(loggedInPlayer, socket, signlinkUid));
                }
                else
                {
                    if (loggedInPlayer != null)
                    {
                        await KillBadConnection(socket, blob, InitResponseCode.AccountAlreadyLoggedIn);

                        return;
                    }

                    SerializablePlayerModel model = null;
                    // figure out whether we need to serialize the acc or make anew one.
                    if (_db.PlayerExists(username))
                    {
                        // check pw
                        if (!_db.IsValidPassword(username, password))
                        {
                            await KillBadConnection(socket, blob, InitResponseCode.InvalidCredentials);

                            return;
                        }

                        model = _db.Load(username);
                        if (model == null)
                        {
                            _log.Warning(this, $"Failed loading player for {username}");
                            await KillBadConnection(socket, blob, InitResponseCode.GeneralFailure);

                            return;
                        }
                    }
                    else
                    {
                        model = SerializablePlayerModel.Default(username, _skills);
                        _db.SetPassword(username, password);
                    }

                    blob.Write((byte)InitResponseCode.LoginDone);
                    blob.Write(0); // is flagged
                    blob.Write((byte)model.TitleId);

                    var login = new NormalPlayerLogin(
                        _services,
                        _greeting,
                        model,
                        socket,
                        signlinkUid);

                    _loginQueue.Enqueue(login);
                }

                await SocketSend(socket, blob);

                socket.Blocking = false;
                _log.Debug(this, "Done socket init.");
            }
            catch (SocketException)
            {
                _log.Debug(this, "SocketException in Entry.");
            }
            catch (ObjectDisposedException)
            {
                _log.Debug(this, "ObjectDisposedException in Entry.");
            }
            catch (CryptoException cryptEx)
            {
                _log.Exception(this, "Crypto Exception in EntryPoint.", cryptEx);
            }
            catch (Exception ex)
            {
                _log.Exception(this, "Unhandled exception in EntryPoint.", ex);
                Debug.Fail(ex.ToString());
            }
        }