public void ReadFromPacket(IPacketReader reader) { MobID = reader.ReadInt(); HitAction = reader.ReadByte(); var info = reader.ReadByte(); ForeAction = (byte)(info & 0x7F); IsMobFacingLeft = (info >> 7 & 1) > 0; FrameIdx = reader.ReadByte(); _ = reader.ReadByte(); // v258 & 0x7F | v25 _ = reader.ReadShort(); // dAx[5] _ = reader.ReadShort(); // dAx[4] _ = reader.ReadShort(); // dAx[3] _ = reader.ReadShort(); // dAx[2] Delay = reader.ReadShort(); for (var i = 0; i < Damage.Length; i++) { Damage[i] = reader.ReadInt(); } _ = reader.ReadInt(); // mob crc }
public void ReadFromPacket(IPacketReader reader) { _ = reader.ReadByte(); // FieldKey _ = reader.ReadInt(); // dr0 _ = reader.ReadInt(); // dr1 var attackInfo = reader.ReadByte(); DamagePerMob = attackInfo >> 0 & 0xF; MobCount = attackInfo >> 4 & 0xF; _ = reader.ReadInt(); // dr2 _ = reader.ReadInt(); // dr3 SkillID = reader.ReadInt(); _ = reader.ReadBool(); // unk _ = reader.ReadInt(); // dr rand _ = reader.ReadInt(); // crc _ = reader.ReadInt(); // skillLevel crc _ = reader.ReadInt(); // skillLevel crc Keydown = 0; // TODO keydownskill check - int keydown var skillFlags = reader.ReadByte(); IsFinalAfterSlashBlast = (skillFlags & 0x0) > 0; IsShadowPartner = (skillFlags & 8) > 0; IsSerialAttack = (skillFlags & 32) > 0; var actionInfo = reader.ReadShort(); Action = actionInfo & 0x7FFF; IsFacingLeft = (actionInfo >> 15 & 1) > 0; _ = reader.ReadInt(); // action crc? ActionType = reader.ReadByte(); ActionSpeed = reader.ReadByte(); ActionTime = reader.ReadInt(); Phase = reader.ReadInt(); // BattleMage? for (var i = 0; i < MobCount; i++) { Mobs.Add(reader.Read(new ClientAttackMobInfo(DamagePerMob))); } _ = reader.ReadPoint2D(); // unk // TODO grenade readpoint2d }
public override async Task Handle(LoginStageUser user, IPacketReader packet) { _ = packet.ReadByte(); // WorldID _ = packet.ReadByte(); // Unknown1 var response = new UnstructuredOutgoingPacket(PacketSendOperations.CheckUserLimitResult); response.WriteByte(0); // TODO: bWarningLevel response.WriteByte(0); // TODO: bPopulateLevel await user.Dispatch(response); }
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; } }
public bool GetBit() { if (Position == 8) { Buffer = _packetReader.ReadByte(); Position = 0; } int value = Buffer; Buffer = (byte)(2 * value); Position++; return((value >> 7) != 0); }
public static byte[] LogonChallenge(IPacketReader packet) { packet.ReadBytes(32); //Skip to username BUsername = packet.ReadBytes(packet.ReadByte()); //Read username string username = Encoding.ASCII.GetString(BUsername); byte[] x; using (SHA1 sha = new SHA1CryptoServiceProvider()) { byte[] user = Encoding.ASCII.GetBytes(username.ToUpper() + ":" + Password.ToUpper()); byte[] res = Salt.Concat(sha.ComputeHash(user, 0, user.Length)).ToArray(); x = sha.ComputeHash(res, 0, res.Length).Reverse().ToArray(); } byte[] b = new byte[20]; new Random().NextBytes(b); RB = b.Reverse().ToArray(); G = new BigInteger(new byte[] { 7 }); V = G.ModPow(new BigInteger(x), new BigInteger(RN)); K = new BigInteger(new byte[] { 3 }); BigInteger temp = (K * V) + G.ModPow(new BigInteger(RB), new BigInteger(RN)); B = temp % new BigInteger(RN); IEnumerable <byte> result = new byte[3]; //Opcode, 0, Success result = result.Concat(B.GetBytes(32).Reverse()); result = result.Concat(new byte[] { 1, 7, 32 }); //1, G, 32 result = result.Concat(N); result = result.Concat(Salt); result = result.Concat(new byte[16]); //unknown, Security Flag return(result.ToArray()); }
protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet) { _ = packet.ReadInt(); var type = (ItemInventoryType)packet.ReadByte(); var response = new UnstructuredOutgoingPacket(PacketSendOperations.GatherItemResult); response.WriteBool(false); response.WriteByte((byte)type); await user.ModifyInventory(i => i[type].Gather(), true); await user.Dispatch(response); }
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); }
public void HandleCharCreate(ref IPacketReader packet, ref IWorldManager manager) { string name = packet.ReadString(); Character cha = new Character() { Name = name.ToUpperFirst(), Race = packet.ReadByte(), Class = packet.ReadByte(), Gender = packet.ReadByte(), Skin = packet.ReadByte(), Face = packet.ReadByte(), HairStyle = packet.ReadByte(), HairColor = packet.ReadByte(), FacialHair = packet.ReadByte() }; // HACK neutral panda faction template doesn't work if (cha.Race == (byte)Races.PANDAREN_NEUTRAL) { cha.Race = (byte)Races.PANDAREN_ALLI; } var result = manager.Account.Characters.Where(x => x.Build == Sandbox.Instance.Build); PacketWriter writer = new PacketWriter(Sandbox.Instance.Opcodes[global::Opcodes.SMSG_CHAR_CREATE], "SMSG_CHAR_CREATE"); if (result.Any(x => x.Name.Equals(cha.Name, StringComparison.CurrentCultureIgnoreCase))) { writer.WriteUInt8(0x32); // Duplicate name manager.Send(writer); return; } cha.Guid = (ulong)(manager.Account.Characters.Count + 1); cha.Location = new Location(-8949.95f, -132.493f, 83.5312f, 0, 0); cha.RestedState = (byte)new Random().Next(1, 2); cha.SetDefaultValues(); manager.Account.Characters.Add(cha); manager.Account.Save(); // Success writer.WriteUInt8(0x2F); manager.Send(writer); }
protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet) { _ = packet.ReadInt(); var type = (ItemInventoryType)packet.ReadByte(); var from = packet.ReadShort(); var to = packet.ReadShort(); var number = packet.ReadShort(); if (to == 0) { await user.ModifyInventory(exclRequest : true); // TODO: drops return; } // TODO: checks await user.ModifyInventory(i => i[type].Move(from, to), true); }
public static byte[] LogonChallenge(IPacketReader packet) { packet.Position = 11; ClientBuild = packet.ReadUInt16(); packet.Position = 33; // Skip to username BUsername = packet.ReadBytes(packet.ReadByte()); // Read username string username = Encoding.ASCII.GetString(BUsername); byte[] x; using (SHA1 sha = new SHA1CryptoServiceProvider()) { byte[] user = Encoding.ASCII.GetBytes(username.ToUpper() + ":" + Password.ToUpper()); byte[] res = Salt.Concat(sha.ComputeHash(user, 0, user.Length)).ToArray(); x = sha.ComputeHash(res, 0, res.Length).Reverse().ToArray(); } byte[] b = new byte[20]; new Random().NextBytes(b); RB = b.Reverse().ToArray(); G = new BigInteger(new byte[] { 7 }); V = G.ModPow(new BigInteger(x), new BigInteger(RN)); K = new BigInteger(new byte[] { 3 }); BigInteger temp = (K * V) + G.ModPow(new BigInteger(RB), new BigInteger(RN)); B = temp % new BigInteger(RN); int size = ClientBuild < 5428 ? 118 : 119; byte[] result = new byte[size]; Array.Copy(B.GetBytes(32).Reverse().ToArray(), 0, result, 3, 32); result[35] = 1; result[36] = 7; result[37] = 32; Array.Copy(N, 0, result, 38, N.Length); Array.Copy(Salt, 0, result, 70, Salt.Length); return(result); }
protected override async Task Handle( GameStageUser stageUser, IFieldObjUser user, IPacketReader packet ) { var channelID = packet.ReadByte(); // TODO checks, error handling var gameServerRequest = new DescribeServerByMetadataRequest(); gameServerRequest.Metadata.Add("Type", Enum.GetName(ServerStageType.Game)); gameServerRequest.Metadata.Add("WorldID", stageUser.Stage.WorldID.ToString()); var gameServers = (await stageUser.Stage.ServerRegistry.DescribeByMetadata(gameServerRequest)).Servers .OrderBy(g => g.Metadata["ChannelID"]) .ToList(); var gameServer = gameServers[channelID]; await stageUser.MigrateTo(gameServer); }
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); }
protected override Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet) { var v3 = packet.ReadInt(); if (v3 > 0) { return(Task.CompletedTask); } var count = packet.ReadInt(); for (var i = 0; i < count; i++) { var key = packet.ReadInt(); user.Character.FunctionKeys[key] = new CharacterFunctionKey { Type = packet.ReadByte(), Action = packet.ReadInt() }; } return(Task.CompletedTask); }
public static byte[] LogonChallenge(IPacketReader packet) { packet.Position = 11; ClientBuild = packet.ReadUInt16(); packet.Position = 33; // Skip to username BUsername = packet.ReadBytes(packet.ReadByte()); // Read username byte[] credshash; using (SHA1 sha = new SHA1CryptoServiceProvider()) { string username = Encoding.ASCII.GetString(BUsername); byte[] credentials = Encoding.ASCII.GetBytes(username.ToUpper() + ":" + Password.ToUpper()); byte[] tmp = Salt.Concat(sha.ComputeHash(credentials)).ToArray(); credshash = sha.ComputeHash(tmp).Reverse().ToArray(); } RB = new byte[20]; new Random().NextBytes(RB); G = new BigInteger(new byte[] { 7 }); V = G.ModPow(new BigInteger(credshash), new BigInteger(RN)); K = new BigInteger(new byte[] { 3 }); B = ((K * V) + G.ModPow(new BigInteger(RB), new BigInteger(RN))) % new BigInteger(RN); // create packet data byte[] result = new byte[GetLogonChallengeSize()]; Array.Copy(B.GetBytes(32).Reverse().ToArray(), 0, result, 3, 32); result[35] = 1; result[36] = 7; result[37] = 32; Array.Copy(N, 0, result, 38, N.Length); Array.Copy(Salt, 0, result, 70, Salt.Length); return(result); }
public void ReadFromPacket(IPacketReader reader) { _position = reader.ReadPoint2D(); _vPosition = reader.ReadPoint2D(); var size = reader.ReadByte(); for (var i = 0; i < size; i++) { var attribute = (MoveFragmentAttribute)reader.ReadByte(); switch (attribute) { case MoveFragmentAttribute.Normal: case MoveFragmentAttribute.HangOnBack: case MoveFragmentAttribute.FallDown: case MoveFragmentAttribute.Wings: case MoveFragmentAttribute.MobAttackRush: case MoveFragmentAttribute.MobAttackRushStop: _fragments.Add(new NormalMoveFragment(attribute, reader)); break; case MoveFragmentAttribute.Jump: case MoveFragmentAttribute.Impact: case MoveFragmentAttribute.StartWings: case MoveFragmentAttribute.MobToss: case MoveFragmentAttribute.DashSlide: case MoveFragmentAttribute.MobLadder: case MoveFragmentAttribute.MobRightAngle: case MoveFragmentAttribute.MobStopNodeStart: case MoveFragmentAttribute.MobBeforeNode: _fragments.Add(new JumpMoveFragment(attribute, reader)); break; case MoveFragmentAttribute.FlashJump: case MoveFragmentAttribute.RocketBooster: case MoveFragmentAttribute.BackStepShot: case MoveFragmentAttribute.MobPowerKnockBack: case MoveFragmentAttribute.VerticalJump: case MoveFragmentAttribute.CustomImpact: case MoveFragmentAttribute.CombatStep: case MoveFragmentAttribute.Hit: case MoveFragmentAttribute.TimeBombAttack: case MoveFragmentAttribute.SnowballTouch: case MoveFragmentAttribute.BuffZoneEffect: _fragments.Add(new ActionMoveFragment(attribute, reader)); break; case MoveFragmentAttribute.Immediate: case MoveFragmentAttribute.Teleport: case MoveFragmentAttribute.Assaulter: case MoveFragmentAttribute.Assassination: case MoveFragmentAttribute.Rush: case MoveFragmentAttribute.SitDown: _fragments.Add(new TeleportMoveFragment(attribute, reader)); break; case MoveFragmentAttribute.StartFallDown: _fragments.Add(new StartFallDownMoveFragment(attribute, reader)); break; case MoveFragmentAttribute.FlyingBlock: _fragments.Add(new FlyingBlockMoveFragment(attribute, reader)); break; case MoveFragmentAttribute.StatChange: _fragments.Add(new StatChangeMoveFragment(attribute, reader)); break; } } _fragments.ForEach(f => f.Apply(this)); }
protected override void ReadData(IPacketReader reader) { _moveAction = (MoveActionType)reader.ReadByte(); _elapse = reader.ReadShort(); }
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); }
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; } }
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); }
protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet) { var type = (ConversationRequestType)packet.ReadByte(); if (!user.IsConversing) { return; } var context = user.CurrentConversation.Context; if (type == ConversationRequestType.AskQuiz || type == ConversationRequestType.AskSpeedQuiz) { await context.Respond( new ConversationResponse <string>(type, packet.ReadString()) ); return; } var answer = packet.ReadByte(); if ( type != ConversationRequestType.Say && type != ConversationRequestType.AskYesNo && type != ConversationRequestType.AskAccept && answer == byte.MinValue || (type == ConversationRequestType.Say || type == ConversationRequestType.AskYesNo || type == ConversationRequestType.AskAccept) && answer == byte.MaxValue ) { await user.EndConversation(); return; } switch (type) { case ConversationRequestType.AskText: case ConversationRequestType.AskBoxText: await context.Respond( new ConversationResponse <string>(type, packet.ReadString()) ); break; case ConversationRequestType.AskNumber: case ConversationRequestType.AskMenu: case ConversationRequestType.AskSlideMenu: await context.Respond( new ConversationResponse <int>(type, packet.ReadInt()) ); break; case ConversationRequestType.AskAvatar: case ConversationRequestType.AskMemberShopAvatar: await context.Respond( new ConversationResponse <byte>(type, packet.ReadByte()) ); break; case ConversationRequestType.AskYesNo: case ConversationRequestType.AskAccept: await context.Respond( new ConversationResponse <bool>(type, Convert.ToBoolean(answer)) ); break; default: await context.Respond( new ConversationResponse <byte>(type, answer) ); 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; } }
protected override async Task Handle(GameStageUser stageUser, IFieldObjUser user, IPacketReader packet) { var stage = stageUser.Stage; var service = stage.PartyService; var type = (PartyResultCode)packet.ReadByte(); switch (type) { case PartyResultCode.InviteParty_Sent: case PartyResultCode.InviteParty_AlreadyInvited: case PartyResultCode.InviteParty_AlreadyInvitedByInviter: break; // Do nothing case PartyResultCode.InviteParty_Accepted: { var serviceRequest = new InviteClaimRequest { Type = InviteType.Party, Invited = user.ID }; var serviceResponse = await stage.InviteService.Claim(serviceRequest); if (serviceResponse.Result == InviteServiceResult.Ok) { var result = PartyResultCode.JoinParty_Done; var response = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult); var party = stage.GetUser(serviceResponse.Invite.Inviter)?.FieldUser?.Party?.ID; if (party == null) { result = PartyResultCode.JoinParty_UnknownUser; } else { var joinRequest = new PartyJoinRequest { Party = party.Value, 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 joinResponse = await service.Join(joinRequest); if (joinResponse.Result == PartyServiceResult.Ok) { return; } if (joinResponse.Result == PartyServiceResult.FailedAlreadyInParty) { result = PartyResultCode.JoinParty_AlreadyJoined; } if (joinResponse.Result == PartyServiceResult.FailedFullParty) { result = PartyResultCode.JoinParty_AlreadyFull; } } response.WriteByte((byte)result); await user.Dispatch(response); } break; } case PartyResultCode.InviteParty_Rejected: { if (user.Party != null) { return; } var serviceRequest = new InviteClaimRequest { Type = InviteType.Party, Invited = user.ID }; var serviceResponse = await stage.InviteService.Claim(serviceRequest); if (serviceResponse.Result == InviteServiceResult.Ok) { var inviter = serviceResponse.Invite.Inviter; var dispatch = new UnstructuredOutgoingPacket(PacketSendOperations.PartyResult) .WriteByte((byte)PartyResultCode.ServerMsg) .WriteBool(true) .WriteString($"'{user.Character.Name}' rejected the party invitation request."); var dispatchRequest = new DispatchToCharactersRequest { Data = ByteString.CopyFrom(dispatch.Buffer) }; dispatchRequest.Characters.Add(inviter); await stage.DispatchService.DispatchToCharacters(dispatchRequest); } break; } default: stage.Logger.LogWarning($"Unhandled party result type: {type}"); break; } }
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); }