Пример #1
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);
        }
Пример #2
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)
                );
        }
Пример #3
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            _ = packet.ReadInt();

            var type = (GroupMessageType)packet.ReadByte();

            var recipientCount = packet.ReadByte();
            var recipients     = new int[recipientCount];

            for (var i = 0; i < recipientCount; i++)
            {
                recipients[i] = packet.ReadInt();
            }

            var text = packet.ReadString();

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

                var partyChat = new UnstructuredOutgoingPacket(PacketSendOperations.GroupMessage);

                partyChat.WriteByte((byte)GroupMessageType.Party);
                partyChat.WriteString(user.Character.Name);
                partyChat.WriteString(text);

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

                dispatchRequest.Characters.Add(user.Party.Members
                                               .Select(m => m.ID)
                                               .Where(m => m != user.ID)
                                               );

                await stageUser.Stage.DispatchService.DispatchToCharacters(dispatchRequest);

                break;
            }

            default:
                stageUser.Stage.Logger.LogWarning($"Unhandled group message type: {type}");
                break;
            }
        }
Пример #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)
        {
            _ = 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)));
        }
Пример #6
0
        public override async Task Handle(LoginStageUser user, IPacketReader packet)
        {
            var name = packet.ReadString();

            var result = await user.Stage.CharacterRepository.CheckExistsByName(name);

            var response = new UnstructuredOutgoingPacket(PacketSendOperations.CheckDuplicatedIDResult);

            response.WriteString(name);
            response.WriteBool(result);

            await user.Dispatch(response);
        }
Пример #7
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);
        }
Пример #8
0
        protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet)
        {
            var stage = stageUser.Stage;
            var flag  = (WhisperFlags)packet.ReadByte();

            switch (flag)
            {
            case WhisperFlags.Whisper | WhisperFlags.Request:
            {
                _ = packet.ReadInt();
                var name = packet.ReadString();
                var text = packet.ReadString();

                if (name.Equals(user.Character.Name, StringComparison.CurrentCultureIgnoreCase))
                {
                    return;
                }

                var allowed = false;
                var target  = await stage.CharacterRepository.RetrieveByName(name);

                var response = new UnstructuredOutgoingPacket(PacketSendOperations.Whisper);

                if (target != null)
                {
                    var sessionRequest = new DescribeSessionByCharacterRequest {
                        Character = target.ID
                    };
                    var sessionResponse = await stage.SessionRegistry.DescribeByCharacter(sessionRequest);

                    if (sessionResponse.Session.State == SessionState.LoggedIn)
                    {
                        allowed = true;
                    }
                }

                response.WriteByte((byte)(WhisperFlags.Whisper | WhisperFlags.Result));
                response.WriteString(allowed ? target.Name : name);
                response.WriteBool(allowed);

                if (allowed)
                {
                    var whisper = new UnstructuredOutgoingPacket(PacketSendOperations.Whisper)
                                  .WriteByte((byte)(WhisperFlags.Whisper | WhisperFlags.Receive))
                                  .WriteString(user.Character.Name)
                                  .WriteByte((byte)stage.ChannelID)
                                  .WriteBool(false) // bFromAdmin
                                  .WriteString(text);
                    var whisperRequest = new DispatchToCharactersRequest {
                        Data = ByteString.CopyFrom(whisper.Buffer)
                    };

                    whisperRequest.Characters.Add(target.ID);

                    await stage.DispatchService.DispatchToCharacters(whisperRequest);
                }

                await user.Dispatch(response);

                break;
            }

            default:
                stage.Logger.LogWarning($"Unhandled whisper flag: {flag}");
                break;
            }
        }
Пример #9
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;
            }
        }
Пример #10
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
            });
        }
Пример #11
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
            });
        }