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); }
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) ); }
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; } }
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); }
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))); }
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); }
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); }
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; } }
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; } }
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 }); }
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 }); }