public static void AccountAuth(NetState state, PacketReader reader) { int accountID = reader.ReadInt32(); int loginID1 = reader.ReadInt32(); int loginID2 = reader.ReadInt32(); int unknown = reader.ReadInt16(); // offset 14 - 16 int iSex = reader.ReadByte(); EAccountSex sex = (EAccountSex)iSex; state.Account = World.GetAccount(accountID); if ( state.Account == null || state.Account.AccountState != EAccountState.Login || state.Account.LoginID1 != loginID1 || state.Account.LoginID2 != loginID2 || state.Account.Sex != sex ) { // Wrong data - hack attempt? state.Account = null; state.Send(new Response.CharacterResponseError((byte)0)); return; } // Mark as authed in character server state.Account.AccountState = EAccountState.Char; state.Account.LoadChars(); // Auth successfull, send a special packet containing the AccountID state.Send(new Response.CharacterResponseSuccess(state.Account)); // Send character list state.Send(new Response.CharacterList(state.Account)); }
/// <summary> /// <para>ID 0x0436</para> /// <para>Length 19</para> /// <para>First packet after selecting a character</para> /// </summary> public static void WantToConnect(NetState state, PacketReader reader) { int accountID = reader.ReadInt32(); int charID = reader.ReadInt32(); int loginID1 = reader.ReadInt32(); int clientTick = reader.ReadInt32(); byte iSex = reader.ReadByte(); EAccountSex sex = (EAccountSex)iSex; state.Account = World.GetAccount(accountID); if (state.Account == null || state.Account.AccountState != EAccountState.Char) { state.Disconnect(); return; } if (state.Account.LoginID1 != loginID1 || state.Account.Sex != sex) { state.Disconnect(); return; } if (state.Account.ActiveChar == null || state.Account.ActiveChar.ID != charID) { state.Disconnect(); return; } // Mark as authed state.Account.AccountState = EAccountState.World; state.Send(new Response.WorldAuthOK(state.Account)); }
/// First packet after selecting a character /// 0x0436 19: <accountID>.L <charID>.L <loginID1>.L <clientTick>.L <sex>.B public static void WantToConnect(NetState state, PacketReader reader) { int accountID = reader.ReadInt32(); int charID = reader.ReadInt32(); int loginID1 = reader.ReadInt32(); int clientTick = reader.ReadInt32(); byte iSex = reader.ReadByte(); EAccountSex sex = (EAccountSex)iSex; state.Account = (Account)World.Objects[EDatabaseType.Account, accountID]; if (state.Account == null || state.Account.AccountState != EAccountState.Char) { ServerConsole.DebugLine("Invalid account or account state: {0}", (state.Account != null ? state.Account.AccountState.ToString() : "null")); state.Disconnect(); return; } if (state.Account.LoginID1 != loginID1 || state.Account.Sex != sex) { ServerConsole.DebugLine("Invalid loginID or sex: {0} != {1}; {2} != {3}", state.Account.LoginID1, loginID1, state.Account.Sex, sex); state.Disconnect(); return; } if (state.Account.ActiveChar == null || state.Account.ActiveChar.ID != charID) { ServerConsole.DebugLine("Invalid active character or charID: {0}", (state.ActiveChar != null ? state.ActiveChar.ID.ToString() : "null")); state.Disconnect(); return; } // Seems to be valid, save the netstate state.Account.Netstate = state; long tick = Timer.Ticks; // Mark as authed state.Account.AccountState = EAccountState.World; // pc_setnew state.ActiveChar.Status.Sex = state.Account.Sex; state.ActiveChar.LoginID1 = loginID1; state.ActiveChar.LoginID2 = 0; state.ActiveChar.ClientTick = clientTick; state.ActiveChar.State.Active = false; //Is set to true after player is fully authed and loaded state.ActiveChar.CanLogTick = tick; // Required to prevent homunculus copuing a base speed of 0 state.ActiveChar.BattleStatus.Speed = (ushort)Global.DEFAULT_WALK_SPEED; // pc_authok if (state.ActiveChar.Status.HP == 0) { state.ActiveChar.SetDead(); } state.ActiveChar.State.ConnectNew = true; state.ActiveChar.FollowTimer = null; state.ActiveChar.InvisibleTimer = null; state.ActiveChar.NpcTimer = null; state.ActiveChar.PvpTimer = null; state.ActiveChar.CanUseItemTick = tick; state.ActiveChar.CanUseCashFoodTick = tick; state.ActiveChar.CanEquipTick = tick; state.ActiveChar.CanTalkTick = tick; state.ActiveChar.CanSendMailTick = tick; state.ActiveChar.SpiritTimer = new List <Timer>(); state.ActiveChar.AutoBonus.Clear(); state.ActiveChar.AutoBonus2.Clear(); state.ActiveChar.AutoBonus3.Clear(); if (Config.ItemAutoGet) { state.ActiveChar.State.Autoloot = 10000; } if (Config.DispExperience) { state.ActiveChar.State.Showexp = true; } if (Config.DispZeny) { state.ActiveChar.State.Showzeny = true; } if ((Config.DisplaySkillFail & 2) > 0) { state.ActiveChar.State.Showdelay = true; } // Check and move equip //pc_setinventorydata(sd); for (int i = 0; i < state.ActiveChar.Status.Inventory.Count; i++) { } //pc_setequipindex(sd); // status_change_init here! // Note: eAthena dosnt realy init the status here, just memset() all to 0 // TODO: why did i set StatusChange.Clear() HERE? confirm this.. state.ActiveChar.StatusChange.Clear(); // TODO: implement player commands (eAthenas @commands) //if ((battle_config.atc_gmonly == 0 || pc_isGM(sd)) && (pc_isGM(sd) >= get_atcommand_level(atcommand_hide))) // sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE); //else state.ActiveChar.Status.Option &= EStatusOption.Mask; state.ActiveChar.StatusChange.Option = state.ActiveChar.Status.Option; // This is the actual option used in battle // Set here because we need the inventory data for weapon sprite parsing state.ActiveChar.ViewData = WorldObjectViewData.GetViewData(state.ActiveChar.Status, (int)state.ActiveChar.Status.Class); // Set base timer for walkable units (from unit_setdata) // TODO: maybe this should be placed in a WorldObjectUnit-method to be used for every walkable unit.. state.ActiveChar.WalkTimer = null; state.ActiveChar.ActiveSkillTimer = null; state.ActiveChar.AttackTimer = null; state.ActiveChar.AttackableTick = state.ActiveChar.CanActTick = state.ActiveChar.CanMoveTick = tick; // clif_authok crap state.ActiveChar.GuildPosition = new Point2D(-1, -1); // Event timer state.ActiveChar.EventTimer = new List <Timer>(); // Rental Timer state.ActiveChar.RentalTimer = null; state.ActiveChar.HateMob = new short[3] { -1, -1, -1 }; // Character enters the map block // TODO: Position checking state.ActiveChar.Location.Map.OnEnter(state.ActiveChar); /* * if ((i = pc_setpos(sd, sd->status.last_point.map, sd->status.last_point.x, sd->status.last_point.y, CLR_OUTSIGHT)) != 0) { * ShowError("Last_point_map %s - id %d not found (error code %d)\n", mapindex_id2name(sd->status.last_point.map), sd->status.last_point.map, i); * * // try warping to a default map instead (church graveyard) * if (pc_setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) { * // if we fail again * clif_authfail_fd(sd->fd, 0); * return false; * } * } */ // Let the client know that the authendication was successfull state.Send(new WorldResponseAuthOK(state.Account)); // eA puts the "char logged in" message here.. // TODO: send friend list // TODO: message about expired accounts, night flag // TODO: request registry // or dont need an async load of registry? state.ActiveChar.DieCounter = -1; }