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)); }
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 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); }
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); }
protected virtual IPacket GetMigratePacket(byte[] address, short port) { var packet = new UnstructuredOutgoingPacket(PacketSendOperations.MigrateCommand); packet.WriteBool(true); foreach (var b in address) { packet.WriteByte(b); } packet.WriteShort(port); return(packet); }
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); }
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); } }
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 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); })); }
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); }