コード例 #1
0
        public async Task <PartyUpdateChangeLevelOrJobResponse> UpdateChangeLevelOrJob(PartyUpdateChangeLevelOrJobRequest request)
        {
            var source = new CancellationTokenSource();

            source.CancelAfter(PartyLockTimeoutDuration);

            var @lock = await _locker.AcquireAsync(PartyLockKey, cancellationToken : source.Token);

            if (@lock != null)
            {
                var result = PartyServiceResult.Ok;
                var party  = await _repository.RetrieveByMember(request.Character);

                var member = party?.Members?.FirstOrDefault(m => m.ID == request.Character);

                if (party == null || member == null)
                {
                    result = PartyServiceResult.FailedNotInParty;
                }

                if (result == PartyServiceResult.Ok)
                {
                    var targets = party.Members.Select(m => m.ID).ToImmutableList();
                    var packet  = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);

                    member.Level = request.Level;
                    member.Job   = request.Job;

                    await _repository.Update(party);

                    packet.WriteByte((byte)PartyResultCode.ChangeLevelOrJob);
                    packet.WriteInt(member.ID);
                    packet.WriteInt(member.Level);
                    packet.WriteInt(member.Job);

                    var dispatchRequest = new DispatchToCharactersRequest {
                        Data = ByteString.CopyFrom(packet.Buffer)
                    };

                    dispatchRequest.Characters.Add(targets);

                    await _dispatcher.DispatchToCharacters(dispatchRequest);

                    await _messenger.PublishAsync(new PartyUpdateEvent { Party = party });
                }

                await @lock.ReleaseAsync();

                return(new PartyUpdateChangeLevelOrJobResponse {
                    Result = result
                });
            }

            return(new PartyUpdateChangeLevelOrJobResponse {
                Result = PartyServiceResult.FailedTimeout
            });
        }
コード例 #2
0
        public async Task UpdateAvatar()
        {
            var avatarPacket = new UnstructuredOutgoingPacket(PacketSendOperations.UserAvatarModified);

            avatarPacket.WriteInt(ID);
            avatarPacket.WriteByte(0x1); // Flag
            avatarPacket.WriteCharacterLook(Character);

            avatarPacket.WriteBool(false);
            avatarPacket.WriteBool(false);
            avatarPacket.WriteBool(false);
            avatarPacket.WriteInt(0);

            await FieldSplit.Dispatch(this, avatarPacket);
        }
コード例 #3
0
        public override IPacket GetLeaveFieldPacket()
        {
            var packet = new UnstructuredOutgoingPacket(PacketSendOperations.NpcLeaveField);

            packet.WriteInt(ID);
            return(packet);
        }
コード例 #4
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            _ = packet.ReadInt();
            var targetID = packet.ReadInt();
            var target   = user.Watching
                           .SelectMany(w => w.GetObjects <IFieldObjUser>())
                           .Where(o => o.ID == targetID)
                           .FirstOrDefault();

            if (target == null)
            {
                return;
            }

            var response = new UnstructuredOutgoingPacket(PacketSendOperations.CharacterInfo);

            response.WriteInt(target.ID);
            response.WriteByte(target.Character.Level);
            response.WriteShort(target.Character.Job);
            response.WriteShort(target.Character.POP);

            response.WriteByte(0);

            response.WriteString(target?.Guild?.Name ?? "");
            response.WriteString("");  // sAlliance

            response.WriteByte(0);     // Medal?

            response.WriteBool(false); // Pets

            response.WriteByte(0);     // TamingMobInfo
            response.WriteByte(0);     // Wishlist

            response.WriteInt(0);      // MedalAchievementInfo
            response.WriteShort(0);

            var chairs = target.Character.Inventories[ItemInventoryType.Install].Items
                         .Select(kv => kv.Value)
                         .Select(i => i.TemplateID)
                         .Where(i => i / 10000 == 301)
                         .ToList();

            response.WriteInt(chairs.Count);
            chairs.ForEach(i => response.WriteInt(i));

            await user.Dispatch(response);
        }
コード例 #5
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            var emotion      = packet.ReadInt();
            var duration     = packet.ReadInt();
            var byItemOption = packet.ReadBool();

            // TODO item option check

            var response = new UnstructuredOutgoingPacket(PacketSendOperations.UserEmotion);

            response.WriteInt(user.ID);
            response.WriteInt(emotion);
            response.WriteInt(duration);
            response.WriteBool(byItemOption);

            await user.FieldSplit.Dispatch(user, response);
        }
コード例 #6
0
ファイル: ShopDialog.cs プロジェクト: Kaioru/Edelstein
        public Task Enter(IFieldObjUser user)
        {
            var items = Info.Items.Values
                        .OrderBy(i => i.ID)
                        .ToList();
            var packet = new UnstructuredOutgoingPacket(PacketSendOperations.OpenShopDlg);

            packet.WriteInt(TemplateID);
            packet.WriteShort((short)items.Count);

            items.ForEach(i =>
            {
                packet.WriteInt(i.TemplateID);
                packet.WriteInt(i.Price);
                packet.WriteByte(i.DiscountRate);
                packet.WriteInt(i.TokenTemplateID);
                packet.WriteInt(i.TokenPrice);
                packet.WriteInt(i.ItemPeriod);
                packet.WriteInt(i.LevelLimited);

                if (GameConstants.IsRechargeableItem(i.TemplateID))
                {
                    packet.WriteDouble(i.UnitPrice);
                }
                else
                {
                    packet.WriteShort((short)i.Quantity);
                }

                packet.WriteShort(i.MaxPerSlot);
            });

            return(user.Dispatch(packet));
        }
コード例 #7
0
        public async Task <PartyChangeBossResponse> ChangeBoss(PartyChangeBossRequest request)
        {
            var source = new CancellationTokenSource();

            source.CancelAfter(PartyLockTimeoutDuration);

            var @lock = await _locker.AcquireAsync(PartyLockKey, cancellationToken : source.Token);

            if (@lock != null)
            {
                var result = PartyServiceResult.Ok;
                var party  = await _repository.RetrieveByMember(request.Character);

                if (party == null)
                {
                    result = PartyServiceResult.FailedNotInParty;
                }
                else if (party.Boss == request.Character)
                {
                    result = PartyServiceResult.FailedAlreadyBoss;
                }

                if (result == PartyServiceResult.Ok)
                {
                    var targets = party.Members.Select(m => m.ID).ToImmutableList();
                    var packet  = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);

                    party.Boss = request.Character;

                    await _repository.Update(party);

                    packet.WriteByte((byte)PartyResultCode.ChangePartyBoss_Done);
                    packet.WriteInt(request.Character);
                    packet.WriteBool(request.IsDisconnect);

                    var dispatchRequest = new DispatchToCharactersRequest {
                        Data = ByteString.CopyFrom(packet.Buffer)
                    };

                    dispatchRequest.Characters.Add(targets);

                    await _dispatcher.DispatchToCharacters(dispatchRequest);

                    await _messenger.PublishAsync(new PartyUpdateEvent { Party = party });
                }

                await @lock.ReleaseAsync();

                return(new PartyChangeBossResponse {
                    Result = result
                });
            }

            return(new PartyChangeBossResponse {
                Result = PartyServiceResult.FailedTimeout
            });
        }
コード例 #8
0
        protected override IPacket GetMigratePacket(byte[] address, short port)
        {
            var packet = new UnstructuredOutgoingPacket(PacketSendOperations.SelectCharacterResult);

            packet.WriteByte(0);
            packet.WriteByte(0);

            foreach (var b in address)
            {
                packet.WriteByte(b);
            }
            packet.WriteShort(port);

            packet.WriteInt(Character.ID);
            packet.WriteByte(0);
            packet.WriteInt(0);

            return(packet);
        }
コード例 #9
0
        public override async Task Handle(LoginStageUser user, IPacketReader packet)
        {
            var worldTemplates = (await Task.WhenAll(user.Stage.Info.Worlds
                                                     .Select(w => user.Stage.WorldTemplates.Retrieve(w))))
                                 .Where(w => w != null)
                                 .OrderBy(w => w.ID)
                                 .ToList();

            foreach (var world in worldTemplates)
            {
                var response = new UnstructuredOutgoingPacket(PacketSendOperations.WorldInformation);

                response.WriteByte((byte)world.ID);
                response.WriteString(world.Name);
                response.WriteByte(world.State);
                response.WriteString(""); // WorldEventDesc
                response.WriteShort(0);   // WorldEventEXP_WSE, WorldSpecificEvent
                response.WriteShort(0);   // WorldEventDrop_WSE, WorldSpecificEvent
                response.WriteBool(world.BlockCharCreation);

                var channelServerRequest = new DescribeServerByMetadataRequest();

                channelServerRequest.Metadata.Add("Type", Enum.GetName(ServerStageType.Game));
                channelServerRequest.Metadata.Add("WorldID", world.ID.ToString());

                var channelServers = (await user.Stage.ServerRegistry.DescribeByMetadata(channelServerRequest)).Servers
                                     .OrderBy(c => c.Id)
                                     .ToList();

                response.WriteByte((byte)channelServers.Count);

                foreach (var channel in channelServers)
                {
                    response.WriteString(channel.Metadata["ID"]);
                    response.WriteInt(0); // TODO: UserNo
                    response.WriteByte(Convert.ToByte(channel.Metadata["WorldID"]));
                    response.WriteByte(Convert.ToByte(channel.Metadata["ChannelID"]));
                    response.WriteBool(false); // TODO: AdultChannel
                }

                response.WriteShort(0); // TODO: Balloon
                await user.Dispatch(response);
            }

            await user.Dispatch(
                new UnstructuredOutgoingPacket(PacketSendOperations.WorldInformation)
                .WriteByte(0xFF)
                );

            await user.Dispatch(
                new UnstructuredOutgoingPacket(PacketSendOperations.LatestConnectedWorld)
                .WriteInt(user.Account.LatestConnectedWorld ?? 0)
                );
        }
コード例 #10
0
        protected override IPacket GetChangeControllerPacket(bool setAsController)
        {
            var packet = new UnstructuredOutgoingPacket(PacketSendOperations.NpcChangeController);

            packet.WriteBool(setAsController);
            packet.WriteInt(ID);

            if (setAsController)
            {
                WriteData(packet);
            }
            return(packet);
        }
コード例 #11
0
        public override void ChannelActive(IChannelHandlerContext context)
        {
            var random    = new Random();
            var newSocket = new NettySocket(
                context.Channel,
                (uint)random.Next(),
                (uint)random.Next()
                );
            var newSession = _acceptor.SessionInitializer.Initialize(newSocket);
            var handshake  = new UnstructuredOutgoingPacket();

            handshake.WriteShort(_acceptor.Version);
            handshake.WriteString(_acceptor.Patch);
            handshake.WriteInt((int)newSocket.SeqRecv);
            handshake.WriteInt((int)newSocket.SeqSend);
            handshake.WriteByte(_acceptor.Locale);

            _ = newSocket.Dispatch(handshake);

            context.Channel.GetAttribute(NettyAttributes.SocketKey).Set(newSocket);
            context.Channel.GetAttribute(NettyAttributes.SessionKey).Set(newSession);

            lock (_acceptor) _acceptor.Sessions.Add(newSession.Socket.ID, newSession);
        }
コード例 #12
0
ファイル: GameStage.cs プロジェクト: Kaioru/Edelstein
        public override async Task Enter(GameStageUser user)
        {
            await base.Enter(user);

            var field = await FieldRepository.Retrieve(user.Character.FieldID);

            var fieldUser = new FieldObjUser(user);

            var guildLoadResponse = await GuildService.LoadByCharacter(new GuildLoadByCharacterRequest { Character = user.Character.ID });

            var partyLoadResponse = await PartyService.LoadByCharacter(new PartyLoadByCharacterRequest { Character = user.Character.ID });

            if (guildLoadResponse.Guild != null)
            {
                fieldUser.Guild = new Guild(guildLoadResponse.Guild);
            }
            if (partyLoadResponse.Party != null)
            {
                fieldUser.Party = new Party(partyLoadResponse.Party);
            }

            user.FieldUser = fieldUser;

            await field.Enter(fieldUser);

            var functionKeyPacket  = new UnstructuredOutgoingPacket(PacketSendOperations.FuncKeyMappedInit);
            var quickSlotKeyPacket = new UnstructuredOutgoingPacket(PacketSendOperations.QuickslotMappedInit);

            functionKeyPacket.WriteBool(false);

            for (var i = 0; i < 90; i++)
            {
                var key = user.Character.FunctionKeys[i];

                functionKeyPacket.WriteByte(key?.Type ?? 0);
                functionKeyPacket.WriteInt(key?.Action ?? 0);
            }

            quickSlotKeyPacket.WriteBool(false);

            for (var i = 0; i < 8; i++)
            {
                quickSlotKeyPacket.WriteInt(user.Character.QuickSlotKeys[i].Key);
            }

            _ = user.Dispatch(functionKeyPacket);
            _ = user.Dispatch(quickSlotKeyPacket);
        }
コード例 #13
0
        public override async Task Handle(LoginStageUser user, IPacketReader packet)
        {
            var spw         = packet.ReadString();
            var characterID = packet.ReadInt();

            var result    = LoginResultCode.Success;
            var response  = new UnstructuredOutgoingPacket(PacketSendOperations.DeleteCharacterResult);
            var character = await user.Stage.CharacterRepository.Retrieve(characterID);

            if (!BCrypt.Net.BCrypt.EnhancedVerify(spw, user.Account.SPW))
            {
                result = LoginResultCode.IncorrectSPW;
            }
            if (character == null || character.AccountWorldID != user.AccountWorld.ID)
            {
                result = LoginResultCode.DBFail;
            }

            var guild = (await user.Stage.GuildService.LoadByCharacter(new GuildLoadByCharacterRequest {
                Character = characterID
            })).Guild;
            var party = (await user.Stage.PartyService.LoadByCharacter(new PartyLoadByCharacterRequest {
                Character = characterID
            })).Party;

            if (result == LoginResultCode.Success)
            {
                // TODO: guild withdraw if not master

                if (party != null)
                {
                    _ = user.Stage.PartyService.Withdraw(new PartyWithdrawRequest {
                        Character = characterID
                    });
                }

                await user.Stage.CharacterRepository.Delete(characterID);
            }

            response.WriteInt(characterID);
            response.WriteByte((byte)result);

            await user.Dispatch(response);
        }
コード例 #14
0
        public async Task ModifySecondaryStats(Action <IModifySecondaryStatContext> action = null, bool exclRequest = false)
        {
            var context = new ModifySecondaryStatContext(SecondaryStats as SecondaryStats);

            action?.Invoke(context);
            await UpdateStats();

            if (context.ResetHistory.ToDictionary().Any())
            {
                var resetLocalPacket  = new UnstructuredOutgoingPacket(PacketSendOperations.TemporaryStatReset);
                var resetRemotePacket = new UnstructuredOutgoingPacket(PacketSendOperations.UserTemporaryStatReset);

                resetLocalPacket.WriteSecondaryStatsFlag(context.ResetHistory);
                resetLocalPacket.WriteBool(false); // IsMovementAffectingStat

                resetRemotePacket.WriteInt(ID);
                resetRemotePacket.WriteSecondaryStatsFlag(context.ResetHistory);

                await Dispatch(resetLocalPacket);

                await FieldSplit.Dispatch(resetRemotePacket);
            }

            if (context.SetHistory.ToDictionary().Any())
            {
                var setLocalPacket  = new UnstructuredOutgoingPacket(PacketSendOperations.TemporaryStatSet);
                var setRemotePacket = new UnstructuredOutgoingPacket(PacketSendOperations.UserTemporaryStatSet);

                setLocalPacket.WriteSecondaryStatsToLocal(context.SetHistory);
                setLocalPacket.WriteShort(0);    // tDelay
                setLocalPacket.WriteBool(false); // IsMovementAffectingStat

                setRemotePacket.WriteInt(ID);
                setRemotePacket.WriteSecondaryStatsToLocal(context.SetHistory);
                setRemotePacket.WriteShort(0); // tDelay

                await Dispatch(setLocalPacket);

                await FieldSplit.Dispatch(setRemotePacket);
            }
        }
コード例 #15
0
ファイル: UserChatHandler.cs プロジェクト: Kaioru/Edelstein
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            _ = packet.ReadInt();
            var message     = packet.ReadString();
            var onlyBalloon = packet.ReadBool();

            if (message.StartsWith("!") || message.StartsWith("@")) // TODO: config?
            {
                await stageUser.Stage.CommandProcessor.Process(user, message.Substring(1));

                return;
            }

            var chatPacket1 = new UnstructuredOutgoingPacket(PacketSendOperations.UserChat);

            chatPacket1.WriteInt(user.ID);
            chatPacket1.WriteBool(user.Account.GradeCode > 0 || user.Account.SubGradeCode > 0); // TODO: proper gm chat checks
            chatPacket1.WriteString(message);
            chatPacket1.WriteBool(onlyBalloon);

            await user.FieldSplit.Dispatch(chatPacket1);

            if (onlyBalloon)
            {
                return;
            }

            var chatPacket2 = new UnstructuredOutgoingPacket(PacketSendOperations.UserChatNLCPQ);

            chatPacket2.WriteInt(user.ID);
            chatPacket2.WriteBool(user.Account.GradeCode > 0 || user.Account.SubGradeCode > 0); // TODO: proper gm chat checks
            chatPacket2.WriteString(message);
            chatPacket2.WriteBool(onlyBalloon);
            chatPacket2.WriteString(user.Character.Name);

            await Task.WhenAll(user.Field
                               .GetUsers()
                               .Except(user.FieldSplit.GetWatchers())
                               .Select(u => u.Dispatch(chatPacket2)));
        }
コード例 #16
0
        protected override async Task Handle(
            GameStageUser stageUser,
            IFieldObjUser user,
            IPacketReader packet
            )
        {
            _ = packet.ReadLong();
            _ = packet.ReadByte();
            _ = packet.ReadLong();
            _ = packet.ReadInt();
            _ = packet.ReadInt();
            _ = packet.ReadInt();

            var path     = packet.Read(new MovePath());
            var movement = new UnstructuredOutgoingPacket(PacketSendOperations.UserMove);

            movement.WriteInt(user.ID);
            movement.Write(path);

            await user.Move(path);

            await user.FieldSplit.Dispatch(user, movement);
        }
コード例 #17
0
        protected override async Task Handle(
            GameStageUser stageUser,
            IFieldObjUser controller,
            IFieldObjNPC controlled,
            IPacketReader packet
            )
        {
            var movement = new UnstructuredOutgoingPacket(PacketSendOperations.NpcMove);

            movement.WriteInt(controlled.ID);
            movement.WriteByte(packet.ReadByte()); // TODO: actions
            movement.WriteByte(packet.ReadByte());

            if (controlled.Info.Move)
            {
                var path = packet.Read(new MovePath());

                movement.Write(path);
                await controlled.Move(path);
            }

            await controlled.FieldSplit.Dispatch(movement);
        }
コード例 #18
0
        public IPacket GetSetFieldPacket()
        {
            var packet = new UnstructuredOutgoingPacket(PacketSendOperations.SetField);

            packet.WriteShort(0); // ClientOpt

            packet.WriteInt(GameStage.ChannelID);
            packet.WriteInt(GameStage.WorldID);

            packet.WriteBool(true); // sNotifierMessage._m_pStr
            packet.WriteBool(!IsInstantiated);
            packet.WriteShort(0);   // nNotifierCheck, loops

            if (!IsInstantiated)
            {
                packet.WriteUInt(Damage.InitSeed1);
                packet.WriteUInt(Damage.InitSeed2);
                packet.WriteUInt(Damage.InitSeed3);

                packet.WriteCharacterData(Character);

                packet.WriteInt(0);
                for (var i = 0; i < 3; i++)
                {
                    packet.WriteInt(0);
                }
            }
            else
            {
                packet.WriteByte(0);
                packet.WriteInt(Character.FieldID);
                packet.WriteByte(Character.FieldPortal);
                packet.WriteInt(Character.HP);
                packet.WriteBool(false);
            }

            packet.WriteDateTime(DateTime.Now);

            return(packet);
        }
コード例 #19
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            var clientAttackInfo = packet.Read(new ClientAttackInfo());

            var skill       = (Skill)clientAttackInfo.SkillID;
            var skillLevel  = clientAttackInfo.SkillID > 0 ? user.Character.GetSkillLevel(clientAttackInfo.SkillID) : 0;
            var damageType  = Type == AttackType.Magic ? DamageType.Magic : DamageType.Physical;
            var damageApply = new List <Tuple <IFieldObjMob, int> >();

            if (Type == AttackType.Melee)
            {
                // TODO bmage blows
            }

            if (Type == AttackType.Body)
            {
                // TODO teleport mastery
            }

            var operation = (PacketSendOperations)((int)PacketSendOperations.UserMeleeAttack + (int)Type);
            var response  = new UnstructuredOutgoingPacket(operation);

            response.WriteInt(user.ID);
            response.WriteByte((byte)(clientAttackInfo.DamagePerMob | 16 * clientAttackInfo.MobCount));
            response.WriteByte(user.Character.Level);

            response.WriteByte((byte)skillLevel);
            if (skillLevel > 0)
            {
                response.WriteInt(clientAttackInfo.SkillID);
            }

            response.WriteByte((byte)(
                                   1 * Convert.ToByte(clientAttackInfo.IsFinalAfterSlashBlast) |
                                   8 * Convert.ToByte(clientAttackInfo.IsShadowPartner) |
                                   16 * 0 |
                                   32 * Convert.ToByte(clientAttackInfo.IsSerialAttack)
                                   ));
            response.WriteShort((short)(
                                    clientAttackInfo.Action & 0x7FFF |
                                    Convert.ToByte(clientAttackInfo.IsFacingLeft) << 15)
                                );

            if (clientAttackInfo.Action <= 0x110)
            {
                response.WriteByte(0); // nMastery
                response.WriteByte(0); // v82
                response.WriteInt(0);  // bMovingShoot

                clientAttackInfo.Mobs.ForEach(m =>
                {
                    var critical    = new bool[clientAttackInfo.DamagePerMob];
                    var damage      = new int[clientAttackInfo.DamagePerMob];
                    var totalDamage = m.Damage.Sum();
                    var mob         = user.Field.GetObject <IFieldObjMob>(m.MobID);

                    response.WriteInt(m.MobID);
                    response.WriteByte(m.HitAction);

                    if (mob != null)
                    {
                        var equipInventory   = user.Character.Inventories[ItemInventoryType.Equip];
                        var serverAttackInfo = new AttackInfo(user, mob)
                        {
                            WeaponID = equipInventory.Items.ContainsKey((short)BodyPart.Weapon)
                                ? equipInventory.Items[(short)BodyPart.Weapon].TemplateID
                                : 0,
                            BulletID   = 0,
                            SkillID    = clientAttackInfo.SkillID,
                            SkillLevel = skillLevel
                        };

                        var calculatedDamage = damageType == DamageType.Physical
                            ? user.Damage.CalculateCharacterPDamage(serverAttackInfo)
                            : user.Damage.CalculateCharacterMDamage(serverAttackInfo);
                        var calculatedTotalDamage = calculatedDamage.Select(d => d.Damage).Sum();

                        // TODO cheatdetector?
                        if (clientAttackInfo.DamagePerMob != calculatedDamage.Length)
                        {
                            user.Message($"Attack count mismatch: {clientAttackInfo.DamagePerMob} : {calculatedDamage.Length}");
                            return;
                        }
                        if (totalDamage != calculatedTotalDamage)
                        {
                            user.Message($"Client damage: {string.Join(" + ", m.Damage.Select(m => $"{m}"))} = {totalDamage}");
                            user.Message($"Server damage: {string.Join(" + ", calculatedDamage.Select(m => $"{m.Damage}"))} = {calculatedTotalDamage}");
                        }

                        damageApply.Add(Tuple.Create(mob, calculatedTotalDamage));

                        for (var i = 0; i < clientAttackInfo.DamagePerMob; i++)
                        {
                            critical[i] = calculatedDamage[i].IsCritical;
                            damage[i]   = calculatedDamage[i].Damage;
                        }
                    }
                    else
                    {
                        user.Damage.SkipCalculationForCharacterDamage();
                    }

                    for (var i = 0; i < clientAttackInfo.DamagePerMob; i++)
                    {
                        response.WriteBool(critical[i]);
                        response.WriteInt(damage[i]);
                    }
                });
            }

            // TODO Keydown

            await user.FieldSplit.Dispatch(user, response);

            await Task.WhenAll(damageApply.Select(async a =>
            {
                var(mob, damage) = a;

                mob.Controller = user;
                await mob.Damage(user, damage);
            }));
        }
コード例 #20
0
        protected override async Task Handle(
            GameStageUser stageUser,
            IFieldObjUser controller,
            IFieldObjMob controlled,
            IPacketReader packet
            )
        {
            if (controlled.HP <= 0)
            {
                return;
            }

            var mobCtrlSN = packet.ReadShort();
            var v7        = packet.ReadByte();         //v85 = nDistance | 4 * (v184 | 2 * ((unsigned __int8)retaddr | 2 * v72)); [ CONFIRMED ]

            var oldSplit           = (v7 & 0xF0) != 0; //this is a type of CFieldSplit
            var mobMoveStartResult = (v7 & 0xF) != 0;

            var curSplit        = packet.ReadByte();
            var illegalVelocity = packet.ReadInt();
            var v8 = packet.ReadByte();

            var cheatedRandom   = (v8 & 0xF0) != 0;
            var cheatedCtrlMove = (v8 & 0xF) != 0;

            var multiTargetForBall = packet.ReadInt();

            for (var i = 0; i < multiTargetForBall; i++)
            {
                packet.ReadLong();                                          // int, int
            }
            var randTimeForAreaAttack = packet.ReadInt();

            for (var i = 0; i < randTimeForAreaAttack; i++)
            {
                packet.ReadInt();
            }

            packet.ReadInt(); // HackedCode
            packet.ReadInt(); // idk
            packet.ReadInt(); // HackedCodeCrc
            packet.ReadInt(); // idk

            var path = packet.Read(new MovePath());

            await controlled.Move(path);

            var response = new UnstructuredOutgoingPacket(PacketSendOperations.MobCtrlAck);

            response.WriteInt(controlled.ID);
            response.WriteShort(mobCtrlSN);
            response.WriteBool(mobMoveStartResult);
            response.WriteShort((short)controlled.MP); // nMP
            response.WriteByte(0);                     // SkillCommand
            response.WriteByte(0);                     // SLV

            await controller.Dispatch(response);

            var movement = new UnstructuredOutgoingPacket(PacketSendOperations.MobMove);

            movement.WriteInt(controlled.ID);
            movement.WriteBool(false); // NotForceLandingWhenDiscard
            movement.WriteBool(false); // NotChangeAction
            movement.WriteBool(false); // NextAttackPossible
            movement.WriteBool(false); // Left
            movement.WriteInt(illegalVelocity);

            movement.WriteInt(0); // MultiTargetForBall
            movement.WriteInt(0); // RandTimeForAreaAttack

            movement.Write(path);

            await controlled.Field.Dispatch(controller, movement);
        }
コード例 #21
0
        public override async Task Handle(LoginStageUser user, IPacketReader packet)
        {
            var name      = packet.ReadString();
            var race      = packet.ReadInt();
            var subJob    = packet.ReadShort();
            var face      = packet.ReadInt();
            var hair      = packet.ReadInt();
            var hairColor = packet.ReadInt();
            var skin      = packet.ReadInt();
            var coat      = packet.ReadInt();
            var pants     = packet.ReadInt();
            var shoes     = packet.ReadInt();
            var weapon    = packet.ReadInt();
            var gender    = packet.ReadByte();

            var result   = LoginResultCode.Success;
            var response = new UnstructuredOutgoingPacket(PacketSendOperations.CreateNewCharacterResult);

            var world = await user.Stage.WorldTemplates.Retrieve((int)user.SelectedWorldID);

            if (world.BlockCharCreation)
            {
                result = LoginResultCode.NotConnectableWorld;
            }

            var serverRequest = new DescribeServerByMetadataRequest();

            serverRequest.Metadata.Add("Type", Enum.GetName(ServerStageType.Game));
            serverRequest.Metadata.Add("WorldID", user.SelectedWorldID.ToString());
            serverRequest.Metadata.Add("ChannelID", user.SelectedChannelID.ToString());

            var server = (await user.Stage.ServerRegistry.DescribeByMetadata(serverRequest)).Servers.FirstOrDefault();

            if (server == null)
            {
                result = LoginResultCode.NotConnectableWorld;
            }

            response.WriteByte((byte)result);

            if (result == LoginResultCode.Success)
            {
                var character = new Character
                {
                    AccountWorldID = user.AccountWorld.ID,
                    Name           = name,
                    Job            = 0, // TODO: race -> job
                    Face           = face,
                    Hair           = hair + hairColor,
                    Skin           = (byte)skin,
                    Gender         = gender,
                    FieldID        = 310000000, // TODO: start maps
                    FieldPortal    = 0,
                    SubJob         = 0          // TODO: race -> subjob
                };
                var context = new ModifyMultiInventoryContext(character.Inventories, user.Stage.ItemTemplates);

                context.Set(BodyPart.Clothes, coat);
                context.Set(BodyPart.Shoes, shoes);
                context.Set(BodyPart.Weapon, weapon);
                if (pants > 0)
                {
                    context.Set(BodyPart.Pants, pants);
                }

                await user.Stage.CharacterRepository.Insert(character);

                user.Character = character;
                user.Stage.Logger.LogDebug($"Created new {race} character: {name} (ID: {character.ID})");

                response.WriteCharacterStats(character);
                response.WriteCharacterLook(character);
                response.WriteBool(false);
                response.WriteBool(false);
            }
            else
            {
                response.WriteInt(0);
            }

            await user.Dispatch(response);
        }
コード例 #22
0
        public async Task <PartyWithdrawResponse> Withdraw(PartyWithdrawRequest request)
        {
            var source = new CancellationTokenSource();

            source.CancelAfter(PartyLockTimeoutDuration);

            var @lock = await _locker.AcquireAsync(PartyLockKey, cancellationToken : source.Token);

            if (@lock != null)
            {
                var result = PartyServiceResult.Ok;
                var party  = await _repository.RetrieveByMember(request.Character);

                var member = party?.Members?.FirstOrDefault(m => m.ID == request.Character);

                if (party == null || member == null)
                {
                    result = PartyServiceResult.FailedNotInParty;
                }

                if (result == PartyServiceResult.Ok)
                {
                    var targets   = party.Members.ToList();
                    var isDisband = request.Character == party.Boss;

                    if (isDisband)
                    {
                        party.Members.Clear();
                        await _repository.Delete(party);
                    }
                    else
                    {
                        party.Members.Remove(member);
                        await _repository.Update(party);
                    }

                    await Task.WhenAll(targets.Select(async m =>
                    {
                        var packet = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);

                        packet.WriteByte((byte)PartyResultCode.WithdrawParty_Done);
                        packet.WriteInt(party.ID);
                        packet.WriteInt(request.Character);
                        packet.WriteBool(!isDisband);

                        if (!isDisband)
                        {
                            packet.WriteBool(request.IsKick);
                            packet.WriteString(member.Name);
                            packet.WritePartyData(party, m.Channel);
                        }

                        var dispatchRequest = new DispatchToCharactersRequest {
                            Data = ByteString.CopyFrom(packet.Buffer)
                        };

                        dispatchRequest.Characters.Add(m.ID);

                        await _dispatcher.DispatchToCharacters(dispatchRequest);
                    }));

                    await _messenger.PublishAsync(new PartyUpdateEvent { Party = party });
                }

                await @lock.ReleaseAsync();

                return(new PartyWithdrawResponse {
                    Result = result
                });
            }

            return(new PartyWithdrawResponse {
                Result = PartyServiceResult.FailedTimeout
            });
        }
コード例 #23
0
        public override async Task Handle(LoginStageUser user, IPacketReader packet)
        {
            _ = packet.ReadByte(); // Unknown1

            var worldID   = packet.ReadByte();
            var channelID = packet.ReadByte();

            var result   = LoginResultCode.Success;
            var response = new UnstructuredOutgoingPacket(PacketSendOperations.SelectWorldResult);

            var gameServerRequest = new DescribeServerByMetadataRequest();

            gameServerRequest.Metadata.Add("Type", Enum.GetName(ServerStageType.Game));
            gameServerRequest.Metadata.Add("WorldID", worldID.ToString());

            var gameServers = (await user.Stage.ServerRegistry.DescribeByMetadata(gameServerRequest)).Servers
                              .OrderBy(g => g.Metadata["ChannelID"])
                              .ToList();

            if (channelID > gameServers.Count)
            {
                result = LoginResultCode.NotConnectableWorld;
            }

            response.WriteByte((byte)result);

            if (result == LoginResultCode.Success)
            {
                var gameServer   = gameServers[channelID];
                var accountWorld = await user.Stage.AccountWorldRepository.RetrieveByAccountAndWorld(user.Account.ID, worldID);

                if (accountWorld == null)
                {
                    accountWorld = new AccountWorld
                    {
                        AccountID = user.Account.ID,
                        WorldID   = worldID
                    };

                    await user.Stage.AccountWorldRepository.Insert(accountWorld);
                }

                user.State             = LoginState.SelectCharacter;
                user.AccountWorld      = accountWorld;
                user.SelectedWorldID   = Convert.ToByte(gameServer.Metadata["WorldID"]);
                user.SelectedChannelID = Convert.ToByte(gameServer.Metadata["ChannelID"]);

                var characters = (await user.Stage.CharacterRepository.RetrieveAllByAccountWorld(accountWorld.ID)).ToList();

                response.WriteByte((byte)characters.Count);
                characters.ForEach(c =>
                {
                    response.WriteCharacterStats(c);
                    response.WriteCharacterLook(c);

                    response.WriteBool(false);
                    response.WriteBool(false);
                });

                response.WriteBool(!string.IsNullOrEmpty(user.Account.SPW)); // bLoginOpt TODO: proper bLoginOpt stuff
                response.WriteInt(accountWorld.SlotCount);
                response.WriteInt(0);
            }

            await user.Dispatch(response);
        }
コード例 #24
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            var stage   = stageUser.Stage;
            var service = stage.PartyService;
            var type    = (PartyRequestCode)packet.ReadByte();

            switch (type)
            {
            case PartyRequestCode.CreateNewParty:
            {
                if (user.Party != null)
                {
                    return;
                }

                var result   = PartyResultCode.CreateNewParty_Done;
                var response = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);
                var contract = new PartyCreateRequest
                {
                    Member = new PartyMemberContract
                    {
                        Id      = user.ID,
                        Name    = user.Character.Name,
                        Job     = user.Character.Job,
                        Level   = user.Character.Level,
                        Channel = stage.ChannelID,
                        Field   = user.Field.ID
                    }
                };
                var serviceResponse = await service.Create(contract);

                var serviceResult = serviceResponse.Result;

                if (serviceResult == PartyServiceResult.FailedAlreadyInParty)
                {
                    result = PartyResultCode.CreateNewParty_AlreadyJoined;
                }
                else if (serviceResult != PartyServiceResult.Ok)
                {
                    result = PartyResultCode.CreateNewParty_Unknown;
                }

                response.WriteByte((byte)result);

                if (result == PartyResultCode.CreateNewParty_Done)
                {
                    response.WriteInt(serviceResponse.Party.Id);
                    response.WriteInt(0);                     // TownPortal-TownID
                    response.WriteInt(0);                     // TownPortal-FieldID
                    response.WriteInt(0);                     // TownPortal-SkillID
                    response.WritePoint2D(new Point2D(0, 0)); //TownPortal-Position
                }

                await user.Dispatch(response);

                break;
            }

            case PartyRequestCode.WithdrawParty:
            {
                if (user.Party == null)
                {
                    return;
                }

                var result   = PartyResultCode.WithdrawParty_Done;
                var response = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);
                var contract = new PartyWithdrawRequest {
                    Character = user.ID, IsKick = false
                };
                var serviceResponse = await service.Withdraw(contract);

                var serviceResult = serviceResponse.Result;

                if (serviceResult == PartyServiceResult.FailedNotInParty)
                {
                    result = PartyResultCode.WithdrawParty_NotJoined;
                }
                else if (serviceResult != PartyServiceResult.Ok)
                {
                    result = PartyResultCode.WithdrawParty_Unknown;
                }

                response.WriteByte((byte)result);

                if (result == PartyResultCode.WithdrawParty_Done)
                {
                    return;
                }

                await user.Dispatch(response);

                break;
            }

            case PartyRequestCode.InviteParty:
            {
                if (user.Party == null)
                {
                    var contract = new PartyCreateRequest
                    {
                        Member = new PartyMemberContract
                        {
                            Id      = user.ID,
                            Name    = user.Character.Name,
                            Job     = user.Character.Job,
                            Level   = user.Character.Level,
                            Channel = stage.ChannelID,
                            Field   = user.Field.ID
                        }
                    };
                    var serviceResponse = await service.Create(contract);

                    var serviceResult = serviceResponse.Result;

                    if (serviceResult != PartyServiceResult.Ok)
                    {
                        return;
                    }

                    var createResponse = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);

                    createResponse.WriteByte((byte)PartyResultCode.CreateNewParty_Done);
                    createResponse.WriteInt(serviceResponse.Party.Id);
                    createResponse.WriteInt(0);                     // TownPortal-TownID
                    createResponse.WriteInt(0);                     // TownPortal-FieldID
                    createResponse.WriteInt(0);                     // TownPortal-SkillID
                    createResponse.WritePoint2D(new Point2D(0, 0)); //TownPortal-Position

                    await user.Dispatch(createResponse);
                }

                if (user?.Party?.Boss != user.ID)
                {
                    return;
                }

                var name      = packet.ReadString();
                var result    = PartyResultCode.InviteParty_Sent;
                var response  = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);
                var character = await stage.CharacterRepository.RetrieveByName(name);

                if (character == null || user.Character.ID == character.ID)
                {
                    result = PartyResultCode.InviteParty_BlockedUser;
                }
                if ((await service.LoadByCharacter(new PartyLoadByCharacterRequest {
                        Character = character.ID
                    })).Party != null)
                {
                    result = PartyResultCode.JoinParty_AlreadyJoined;
                }
                else
                {
                    var serviceResponse = await stage.InviteService.Register(new InviteRegisterRequest
                        {
                            Invite = new InviteContract
                            {
                                Type    = InviteType.Party,
                                Invited = character.ID,
                                Inviter = user.ID
                            }
                        });

                    if (serviceResponse.Result != InviteServiceResult.Ok)
                    {
                        result = PartyResultCode.InviteParty_AlreadyInvited;
                    }
                }

                response.WriteByte((byte)result);

                if (result == PartyResultCode.InviteParty_Sent)
                {
                    var invitation        = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);
                    var invitationRequest = new DispatchToCharactersRequest();

                    invitation.WriteByte((byte)PartyRequestCode.InviteParty);
                    invitation.WriteInt(user.Character.ID);
                    invitation.WriteString(user.Character.Name);
                    invitation.WriteInt(user.Character.Level);
                    invitation.WriteInt(user.Character.Job);
                    invitation.WriteByte(0);         // PartyOpt

                    invitationRequest.Data = ByteString.CopyFrom(invitation.Buffer);
                    invitationRequest.Characters.Add(character.ID);

                    await stage.DispatchService.DispatchToCharacters(invitationRequest);

                    response.WriteString(character.Name);
                }

                await user.Dispatch(response);

                break;
            }

            case PartyRequestCode.KickParty:
            {
                if (user.Party == null)
                {
                    return;
                }
                if (user.Party.Boss != user.ID)
                {
                    return;
                }

                var id = packet.ReadInt();

                if (!user.Party.Members.Any(m => m.ID == id))
                {
                    return;
                }
                if (id == user.ID)
                {
                    return;
                }

                var result   = PartyResultCode.WithdrawParty_Done;
                var response = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);
                var contract = new PartyWithdrawRequest {
                    Character = id, IsKick = true
                };
                var serviceResponse = await service.Withdraw(contract);

                var serviceResult = serviceResponse.Result;

                if (serviceResult == PartyServiceResult.FailedNotInParty)
                {
                    result = PartyResultCode.WithdrawParty_NotJoined;
                }
                else if (serviceResult != PartyServiceResult.Ok)
                {
                    result = PartyResultCode.WithdrawParty_Unknown;
                }

                response.WriteByte((byte)result);

                if (result == PartyResultCode.WithdrawParty_Done)
                {
                    return;
                }

                await user.Dispatch(response);

                break;
            }

            case PartyRequestCode.ChangePartyBoss:
            {
                if (user.Party == null || user.Party.Boss != user.ID)
                {
                    return;
                }

                var id = packet.ReadInt();

                if (!user.Party.Members.Any(m => m.ID == id))
                {
                    return;
                }
                if (id == user.ID)
                {
                    return;
                }

                var result   = PartyResultCode.ChangePartyBoss_Done;
                var response = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);
                var contract = new PartyChangeBossRequest {
                    Character = id
                };
                var serviceResponse = await service.ChangeBoss(contract);

                var serviceResult = serviceResponse.Result;

                if (serviceResult != PartyServiceResult.Ok)
                {
                    result = PartyResultCode.WithdrawParty_Unknown;
                }

                response.WriteByte((byte)result);

                if (result == PartyResultCode.ChangePartyBoss_Done)
                {
                    return;
                }

                await user.Dispatch(response);

                break;
            }

            default:
                stage.Logger.LogWarning($"Unhandled party request type: {type}");
                break;
            }
        }
コード例 #25
0
        public override IPacket GetEnterFieldPacket()
        {
            var packet = new UnstructuredOutgoingPacket(PacketSendOperations.UserEnterField);

            packet.WriteInt(ID);

            packet.WriteByte(Character.Level);
            packet.WriteString(Character.Name);

            packet.WriteString(Guild?.Name ?? "");
            packet.WriteShort(Guild?.MarkBg ?? 0);
            packet.WriteByte(Guild?.MarkBgColor ?? 0);
            packet.WriteShort(Guild?.Mark ?? 0);
            packet.WriteByte(Guild?.MarkColor ?? 0);

            packet.WriteSecondaryStatsToRemote(SecondaryStats);

            packet.WriteShort(Character.Job);
            packet.WriteCharacterLook(Character);

            packet.WriteInt(0);
            packet.WriteInt(0);
            packet.WriteInt(0);
            packet.WriteInt(0);
            packet.WriteInt(0);
            packet.WriteInt(0);

            packet.WritePoint2D(Position);
            packet.WriteByte((byte)Action);
            packet.WriteShort((short)(Foothold?.ID ?? 0));
            packet.WriteByte(0);

            packet.WriteBool(false);
            packet.WriteBool(false);
            packet.WriteBool(false);

            packet.WriteBool(false);

            packet.WriteInt(0);
            packet.WriteInt(0);
            packet.WriteInt(0);

            packet.WriteByte(0);

            packet.WriteBool(false);

            packet.WriteBool(false);
            packet.WriteBool(false);
            packet.WriteBool(false);

            packet.WriteByte(0);

            packet.WriteByte(0);
            packet.WriteInt(0);

            return(packet);
        }
コード例 #26
0
        public async Task <PartyJoinResponse> Join(PartyJoinRequest request)
        {
            var source = new CancellationTokenSource();

            source.CancelAfter(PartyLockTimeoutDuration);

            var @lock = await _locker.AcquireAsync(PartyLockKey, cancellationToken : source.Token);

            if (@lock != null)
            {
                var result = PartyServiceResult.Ok;
                var party  = await _repository.Retrieve(request.Party);

                if (await _repository.RetrieveByMember(request.Member.Id) != null)
                {
                    result = PartyServiceResult.FailedAlreadyInParty;
                }
                if (party == null)
                {
                    result = PartyServiceResult.FailedNonExistentParty;
                }
                else if (party.Members.Any(m => m.ID == request.Member.Id))
                {
                    result = PartyServiceResult.FailedAlreadyInParty;
                }
                else if (party.Members.Count >= 6)
                {
                    result = PartyServiceResult.FailedFullParty;
                }

                if (result == PartyServiceResult.Ok)
                {
                    party.Members.Add(new PartyMemberRecord(request.Member));

                    await _repository.Update(party);

                    await Task.WhenAll(party.Members.Select(async m =>
                    {
                        var packet = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult);

                        packet.WriteByte((byte)PartyResultCode.JoinParty_Done);
                        packet.WriteInt(party.ID);
                        packet.WriteString(request.Member.Name);
                        packet.WritePartyData(party, m.Channel);

                        var dispatchRequest = new DispatchToCharactersRequest {
                            Data = ByteString.CopyFrom(packet.Buffer)
                        };

                        dispatchRequest.Characters.Add(m.ID);

                        await _dispatcher.DispatchToCharacters(dispatchRequest);
                    }));

                    await _messenger.PublishAsync(new PartyUpdateEvent { Party = party });
                }

                await @lock.ReleaseAsync();

                return(new PartyJoinResponse {
                    Result = result, Party = party?.ToContract()
                });
            }

            return(new PartyJoinResponse {
                Result = PartyServiceResult.FailedTimeout
            });
        }