public void HandlePacket(GameClient client, GSPacketIn packet) { // for 1.115c+ The First client packet Changes. if (client.Version < GameClient.eClientVersion.Version1115) { int rc4 = packet.ReadByte(); byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); client.MajorBuild = (byte)packet.ReadByte(); client.MinorBuild = (byte)packet.ReadByte(); client.MinorRev = packet.ReadString(1); if (rc4 == 1) { //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(client.PacketProcessor.Encoding.SBox); packet.Read(client.PacketProcessor.Encoding.SBox, 0, 256); client.PacketProcessor.Encoding.EncryptionState = eEncryptionState.PseudoRC4Encrypted; //DOLConsole.WriteLine(client.Socket.RemoteEndPoint.ToString()+": SBox set!"); //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(((PacketEncoding168)client.PacketProcessor.Encoding).SBox); } else { //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } } else { // if the DataSize is above 7 then the RC4 key is bundled if (packet.DataSize > 7) { if (Properties.CLIENT_ENABLE_ENCRYPTION_RC4) { var length = packet.ReadIntLowEndian(); var key = new byte[length]; packet.Read(key, 0, (int)length); client.PacketProcessor.Encoding.SBox = key; client.PacketProcessor.Encoding.EncryptionState = eEncryptionState.PseudoRC4Encrypted; } return; } // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // the next 4 bytes are the game.dll version but not in string form // ie: 01 01 19 61 = 1.125a // this version is handled elsewhere before being sent here. packet.Skip(3); // skip the numbers in the version client.MinorRev = packet.ReadString(1); // get the minor revision letter // 1125d support packet.Skip(2); // build //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(4); // Skip the first 4 bytes packet.Skip(1); string charName = packet.ReadString(28); // TODO Character handling if (charName.Equals("noname")) { client.Out.SendSessionID(); } else { // SH: Also load the player if client player is NOT null but their charnames differ!!! // only load player when on charscreen and player is not loaded yet // packet is sent on every region change (and twice after "play" was pressed) if (((client.Player == null && client.Account.Characters != null) || (client.Player != null && client.Player.Name.ToLower() != charName.ToLower())) && client.ClientState == GameClient.eClientState.CharScreen) { bool charFound = false; for (int i = 0; i < client.Account.Characters.Length; i++) { if (client.Account.Characters[i] != null && client.Account.Characters[i].Name == charName) { charFound = true; // Notify Character Selection Event, last hope to fix any bad data before Loading. GameEventMgr.Notify(DatabaseEvent.CharacterSelected, new CharacterEventArgs(client.Account.Characters[i], client)); client.LoadPlayer(i); break; } } if (charFound == false) { client.Player = null; client.ActiveCharIndex = -1; } else { // Log character play AuditMgr.AddAuditEntry(client, AuditType.Character, AuditSubtype.CharacterLogin, string.Empty, charName); } } client.Out.SendSessionID(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client.Version >= GameClient.eClientVersion.Version1126 && packet.DataSize > 7) { // 1126 only sends the RC4 key in the second F4 packet // put your RC4 code in here return; } // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // the next 4 bytes are the game.dll version but not in string form // ie: 01 01 19 61 = 1.125a // this version is handled elsewhere before being sent here. packet.Skip(3); // skip the numbers in the version client.MinorRev = packet.ReadString(1); // get the minor revision letter // 1125d support // if the DataSize is above 7 then the RC4 key is bundled if (packet.DataSize > 7) { // put your RC4 code in here //client.UsingRC4 = true; // use this if you are using RC4 return; } client.ClientId = packet.ReadShort(); // Send the crypt key response to the client client.Out.SendVersionAndCryptKey(); }
public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(4); int slot = packet.ReadShort(); InventoryItem item = client.Player.Inventory.GetItem((eInventorySlot)slot); if (item != null) { if (item.IsIndestructible) { client.Out.SendMessage(String.Format("You can't destroy {0}!", item.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (item.Id_nb == "ARelic") { client.Out.SendMessage("You cannot destroy a relic!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (client.Player.Inventory.EquippedItems.Contains(item)) { client.Out.SendMessage("You cannot destroy an equipped item!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (client.Player.Inventory.RemoveItem(item)) { client.Out.SendMessage("You destroy the " + item.Name + ".", eChatType.CT_System, eChatLoc.CL_SystemWindow); InventoryLogging.LogInventoryAction(client.Player, "(destroy)", eInventoryActionType.Other, item.Template, item.Count); } } }
public void HandlePacket(GameClient client, GSPacketIn packet) { // we don't handle Encryption for 1.115c // the rc4 secret can't be unencrypted from RSA. // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // if the DataSize is above 7 then the RC4 key is bundled // this is stored in case we find a way to handle encryption someday ! if (packet.DataSize > 7) { packet.Skip(6); ushort length = packet.ReadShortLowEndian(); packet.Read(client.PacketProcessor.Encoding.SBox, 0, length); // ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; } // Send the crypt key to the client client.Out.SendVersionAndCryptKey(); }
public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(4); int slot = packet.ReadShort(); InventoryItem item = client.Player.Inventory.GetItem((eInventorySlot)slot); if (item != null) { if (item.IsIndestructible) { client.Out.SendMessage(String.Format("You can't destroy {0}!", item.GetName(0, false)), eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (item.Id_nb == "ARelic") { client.Out.SendMessage("You cannot destroy a relic!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (client.Player.Inventory.EquippedItems.Contains(item)) { client.Out.SendMessage("You cannot destroy an equipped item!", eChatType.CT_System, eChatLoc.CL_SystemWindow); return; } if (client.Player.Inventory.RemoveItem(item)) { client.Out.SendMessage("You destroy the " + item.Name + ".", eChatType.CT_System, eChatLoc.CL_SystemWindow); InventoryLogging.LogInventoryAction(client.Player, "(destroy)", eInventoryActionType.Other, item.Template, item.Count); } } }
/// <summary> /// Called when the packet has been received /// </summary> /// <param name="client">Client that sent the packet</param> /// <param name="packet">Packet data</param> /// <returns>Non zero if function was successfull</returns> public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(4); //Skip the first 4 bytes client.PingTime = DateTime.Now.Ticks; ulong timestamp = packet.ReadInt(); client.Out.SendPingReply(timestamp, packet.Sequence); }
public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(1); if (client.Version < GameClient.eClientVersion.Version1127) { packet.Skip(7); } string cmdLine = packet.ReadString(255); if (!ScriptMgr.HandleCommand(client, cmdLine)) { if (cmdLine[0] == '&') { cmdLine = "/" + cmdLine.Remove(0, 1); } client.Out.SendMessage($"No such command ({cmdLine})", eChatType.CT_System, eChatLoc.CL_SystemWindow); } }
/// <summary> /// Called when the packet has been received /// </summary> /// <param name="client">Client that sent the packet</param> /// <param name="packet">Packet data</param> /// <returns>Non zero if function was successfull</returns> public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(4); //Skip the first 4 bytes long pingDiff = (DateTime.Now.Ticks - client.PingTime)/1000; client.PingTime = DateTime.Now.Ticks; ulong timestamp = packet.ReadInt(); client.Out.SendPingReply(timestamp,packet.Sequence); }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null || client.Player == null) return; if ((client.Player.TargetObject is IGameInventoryObject) == false) return; MarketSearch.SearchData search = new MarketSearch.SearchData(); search.name = packet.ReadString(64); search.slot = (int)packet.ReadInt(); search.skill = (int)packet.ReadInt(); search.resist = (int)packet.ReadInt(); search.bonus = (int)packet.ReadInt(); search.hp = (int)packet.ReadInt(); search.power = (int)packet.ReadInt(); search.proc = (int)packet.ReadInt(); search.qtyMin = (int)packet.ReadInt(); search.qtyMax = (int)packet.ReadInt(); search.levelMin = (int)packet.ReadInt(); search.levelMax = (int)packet.ReadInt(); search.priceMin = (int)packet.ReadInt(); search.priceMax = (int)packet.ReadInt(); search.visual = (int)packet.ReadInt(); search.page = (byte)packet.ReadByte(); byte unk1 = (byte)packet.ReadByte(); short unk2 = (short)packet.ReadShort(); byte unk3 = 0; byte unk4 = 0; byte unk5 = 0; byte unk6 = 0; byte unk7 = 0; byte unk8 = 0; if (client.Version >= GameClient.eClientVersion.Version198) { // Dunnerholl 2009-07-28 Version 1.98 introduced new options to Market search. 12 Bytes were added, but only 7 are in usage so far in my findings. // update this, when packets change and keep in mind, that this code reflects only the 1.98 changes search.armorType = search.page; // page is now used for the armorType (still has to be logged, i just checked that 2 means leather, 0 = standard search.damageType = (byte)packet.ReadByte(); // 1=crush, 2=slash, 3=thrust unk3 = (byte)packet.ReadByte(); unk4 = (byte)packet.ReadByte(); unk5 = (byte)packet.ReadByte(); search.playerCrafted = (byte)packet.ReadByte(); // 1 = show only Player crafted, 0 = all // 3 bytes unused packet.Skip(3); search.page = (byte)packet.ReadByte(); // page is now sent here unk6 = (byte)packet.ReadByte(); unk7 = (byte)packet.ReadByte(); unk8 = (byte)packet.ReadByte(); } search.clientVersion = client.Version.ToString(); (client.Player.TargetObject as IGameInventoryObject).SearchInventory(client.Player, search); }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client?.Player == null) { return; } if ((client.Player.TargetObject is IGameInventoryObject) == false) { return; } MarketSearch.SearchData search = new MarketSearch.SearchData { name = packet.ReadString(64), slot = (int)packet.ReadInt(), skill = (int)packet.ReadInt(), resist = (int)packet.ReadInt(), bonus = (int)packet.ReadInt(), hp = (int)packet.ReadInt(), power = (int)packet.ReadInt(), proc = (int)packet.ReadInt(), qtyMin = (int)packet.ReadInt(), qtyMax = (int)packet.ReadInt(), levelMin = (int)packet.ReadInt(), levelMax = (int)packet.ReadInt(), priceMin = (int)packet.ReadInt(), priceMax = (int)packet.ReadInt(), visual = (int)packet.ReadInt(), page = (byte)packet.ReadByte() }; packet.ReadByte(); // unk packet.ReadShort(); // unk // Dunnerholl 2009-07-28 Version 1.98 introduced new options to Market search. 12 Bytes were added, but only 7 are in usage so far in my findings. // update this, when packets change and keep in mind, that this code reflects only the 1.98 changes search.armorType = search.page; // page is now used for the armorType (still has to be logged, i just checked that 2 means leather, 0 = standard search.damageType = (byte)packet.ReadByte(); // 1=crush, 2=slash, 3=thrust packet.ReadByte(); // unk packet.ReadByte(); // unk packet.ReadByte(); // unk search.playerCrafted = (byte)packet.ReadByte(); // 1 = show only Player crafted, 0 = all // 3 bytes unused packet.Skip(3); search.page = (byte)packet.ReadByte(); // page is now sent here packet.ReadByte(); // unk packet.ReadByte(); // unk packet.ReadByte(); // unk search.clientVersion = client.Version.ToString(); (client.Player.TargetObject as IGameInventoryObject).SearchInventory(client.Player, search); }
public void HandlePacket(GameClient client, GSPacketIn packet) { // for 1.115c+ The First client packet Changes. if (client.Version < GameClient.eClientVersion.Version1115) { int rc4 = packet.ReadByte(); byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); byte major = (byte)packet.ReadByte(); byte minor = (byte)packet.ReadByte(); byte build = (byte)packet.ReadByte(); if (rc4 == 1) { //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(client.PacketProcessor.Encoding.SBox); packet.Read(((PacketEncoding168)client.PacketProcessor.Encoding).SBox, 0, 256); ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState = PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; //DOLConsole.WriteLine(client.Socket.RemoteEndPoint.ToString()+": SBox set!"); //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(((PacketEncoding168)client.PacketProcessor.Encoding).SBox); } else { //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } } else { // we don't handle Encryption for 1.115c // the rc4 secret can't be unencrypted from RSA. // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // if the DataSize is above 7 then the RC4 key is bundled // this is stored in case we find a way to handle encryption someday ! if (packet.DataSize > 7) { packet.Skip(6); ushort length = packet.ReadShortLowEndian(); packet.Read(client.PacketProcessor.Encoding.SBox, 0, length); // ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; } //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { // for 1.115c+ The First client packet Changes. if (client.Version < GameClient.eClientVersion.Version1115) { int rc4 = packet.ReadByte(); byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); byte major = (byte)packet.ReadByte(); byte minor = (byte)packet.ReadByte(); byte build = (byte)packet.ReadByte(); if(rc4==1) { //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(client.PacketProcessor.Encoding.SBox); packet.Read(((PacketEncoding168)client.PacketProcessor.Encoding).SBox,0,256); ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; //DOLConsole.WriteLine(client.Socket.RemoteEndPoint.ToString()+": SBox set!"); //DOLConsole.Log("SBox=\n"); //DOLConsole.LogDump(((PacketEncoding168)client.PacketProcessor.Encoding).SBox); } else { //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } } else { // we don't handle Encryption for 1.115c // the rc4 secret can't be unencrypted from RSA. // register client type byte clientType = (byte)packet.ReadByte(); client.ClientType = (GameClient.eClientType)(clientType & 0x0F); client.ClientAddons = (GameClient.eClientAddons)(clientType & 0xF0); // if the DataSize is above 7 then the RC4 key is bundled // this is stored in case we find a way to handle encryption someday ! if (packet.DataSize > 7) { packet.Skip(6); ushort length = packet.ReadShortLowEndian(); packet.Read(client.PacketProcessor.Encoding.SBox, 0, length); // ((PacketEncoding168)client.PacketProcessor.Encoding).EncryptionState=PacketEncoding168.eEncryptionState.PseudoRC4Encrypted; } //Send the crypt key to the client client.Out.SendVersionAndCryptKey(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(8); string cmdLine = packet.ReadString(255); if(!ScriptMgr.HandleCommand(client, cmdLine)) { if (cmdLine[0] == '&') { cmdLine = '/' + cmdLine.Remove(0, 1); } client.Out.SendMessage("No such command ("+cmdLine+")",eChatType.CT_System,eChatLoc.CL_SystemWindow); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { packet.Skip(8); string cmdLine = packet.ReadString(255); if (!ScriptMgr.HandleCommand(client, cmdLine)) { if (cmdLine[0] == '&') { cmdLine = '/' + cmdLine.Remove(0, 1); } client.Out.SendMessage("No such command (" + cmdLine + ")", eChatType.CT_System, eChatLoc.CL_SystemWindow); } }
private void _HandlePacket1125d(GameClient client, GSPacketIn packet) { byte type = (byte)packet.ReadByte(); // changed from ushort low end packet.Skip(1); // unknown string charName = packet.ReadString(24); // down from 28, both need checking //TODO Character handling if (charName.Equals("noname")) { client.Out.SendLoginGranted(); client.Out.SendSessionID(); } else { // SH: Also load the player if client player is NOT null but their charnames differ!!! // only load player when on charscreen and player is not loaded yet // packet is sent on every region change (and twice after "play" was pressed) if (((client.Player == null && client.Account.Characters != null) || (client.Player != null && client.Player.Name.ToLower() != charName.ToLower())) && client.ClientState == GameClient.eClientState.CharScreen) { bool charFound = false; for (int i = 0; i < client.Account.Characters.Length; i++) { if (client.Account.Characters[i] != null && client.Account.Characters[i].Name == charName) { charFound = true; client.LoadPlayer(i); break; } } if (!charFound) { client.Player = null; client.ActiveCharIndex = -1; } else { // Log character play AuditMgr.AddAuditEntry(client, AuditType.Character, AuditSubtype.CharacterLogin, "", charName); } } // live actually sends the login granted packet, which sets the button activity states client.Out.SendLoginGranted(); client.Out.SendSessionID(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client.Version >= GameClient.eClientVersion.Version1127) { var playerCommandHandler1127 = new PlayerCommandHandler1127(); playerCommandHandler1127.HandlePacket(client, packet); return; } packet.Skip(8); string cmdLine = packet.ReadString(255); if (!ScriptMgr.HandleCommand(client, cmdLine)) { if (cmdLine[0] == '&') { cmdLine = "/" + cmdLine.Remove(0, 1); } client.Out.SendMessage($"No such command ({cmdLine})", eChatType.CT_System, eChatLoc.CL_SystemWindow); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null) { return; } string ipAddress = client.TcpEndpointAddress; byte major; byte minor; byte build; string password; string userName; /// <summary> /// Packet Format Change above 1.115 /// </summary> if (client.Version < GameClient.eClientVersion.Version1115) { packet.Skip(2); //Skip the client_type byte major = (byte)packet.ReadByte(); minor = (byte)packet.ReadByte(); build = (byte)packet.ReadByte(); password = packet.ReadString(20); bool v174; //the logger detection we had is no longer working //bool loggerUsing = false; switch (client.Version) { case GameClient.eClientVersion.Version168: case GameClient.eClientVersion.Version169: case GameClient.eClientVersion.Version170: case GameClient.eClientVersion.Version171: case GameClient.eClientVersion.Version172: case GameClient.eClientVersion.Version173: v174 = false; break; default: v174 = true; break; } if (v174) { packet.Skip(11); } else { packet.Skip(7); } uint c2 = packet.ReadInt(); uint c3 = packet.ReadInt(); uint c4 = packet.ReadInt(); if (v174) { packet.Skip(27); } else { packet.Skip(31); } userName = packet.ReadString(20); } else { // 1.115c+ // client type packet.Skip(1); //version major = (byte)packet.ReadByte(); minor = (byte)packet.ReadByte(); build = (byte)packet.ReadByte(); // revision packet.Skip(1); // build packet.Skip(2); // Read Login userName = packet.ReadLowEndianShortPascalString(); // Read Password password = packet.ReadLowEndianShortPascalString(); } /* * if (c2 == 0 && c3 == 0x05000000 && c4 == 0xF4000000) * { * loggerUsing = true; * Log.Warn("logger detected (" + username + ")"); * }*/ // check server status if (GameServer.Instance.ServerStatus == eGameServerStatus.GSS_Closed) { client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.GameCurrentlyClosed); Log.Info(ipAddress + " disconnected because game is closed!"); GameServer.Instance.Disconnect(client); return; } // check connection allowed with serverrules try { if (!GameServer.ServerRules.IsAllowedToConnect(client, userName)) { if (Log.IsInfoEnabled) { Log.Info(ipAddress + " disconnected because IsAllowedToConnect returned false!"); } GameServer.Instance.Disconnect(client); return; } } catch (Exception e) { if (Log.IsErrorEnabled) { Log.Error("Error shutting down Client after IsAllowedToConnect failed!", e); } } // Handle connection EnterLock(userName); try { Account playerAccount; // Make sure that client won't quit lock (client) { GameClient.eClientState state = client.ClientState; if (state != GameClient.eClientState.NotConnected) { Log.DebugFormat("wrong client state on connect {0} {1}", userName, state.ToString()); return; } if (Log.IsInfoEnabled) { Log.Info(string.Format("({0})User {1} logging on! ({2} type:{3} add:{4})", ipAddress, userName, client.Version, (client.ClientType), client.ClientAddons.ToString("G"))); } // check client already connected GameClient findclient = WorldMgr.GetClientByAccountName(userName, true); if (findclient != null) { client.IsConnected = false; if (findclient.ClientState == GameClient.eClientState.Connecting) { if (Log.IsInfoEnabled) { Log.Info("User is already connecting, ignored."); } client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn); return; } // in login if (findclient.ClientState == GameClient.eClientState.Linkdead) { if (Log.IsInfoEnabled) { Log.Info("User is still being logged out from linkdeath!"); } client.Out.SendLoginDenied(eLoginError.AccountIsInLogoutProcedure); } else { if (Log.IsInfoEnabled) { Log.Info("User already logged in!"); } client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn); } GameServer.Instance.Disconnect(client); return; } Regex goodName = new Regex("^[a-zA-Z0-9]*$"); if (!goodName.IsMatch(userName) || string.IsNullOrWhiteSpace(userName)) { if (Log.IsInfoEnabled) { Log.Info("Invalid symbols in account name \"" + userName + "\" found!"); } client.IsConnected = false; if (client != null && client.Out != null) { client.Out.SendLoginDenied(eLoginError.AccountInvalid); } else { Log.Warn("Client or Client.Out null on invalid name failure. Disconnecting."); } GameServer.Instance.Disconnect(client); return; } else { playerAccount = GameServer.Database.FindObjectByKey <Account>(userName); client.PingTime = DateTime.Now.Ticks; if (playerAccount == null) { //check autocreate ... if (GameServer.Instance.Configuration.AutoAccountCreation && Properties.ALLOW_AUTO_ACCOUNT_CREATION) { // autocreate account if (string.IsNullOrEmpty(password)) { client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.AccountInvalid); GameServer.Instance.Disconnect(client); if (Log.IsInfoEnabled) { Log.Info("Account creation failed, no password set for Account: " + userName); } return; } // check for account bombing TimeSpan ts; IList <Account> allAccByIp = GameServer.Database.SelectObjects <Account>("LastLoginIP = '" + ipAddress + "'"); int totalacc = 0; foreach (Account ac in allAccByIp) { ts = DateTime.Now - ac.CreationDate; if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION_SAMEIP && totalacc > 1) { Log.Warn("Account creation: too many from same IP within set minutes - " + userName + " : " + ipAddress); client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime); GameServer.Instance.Disconnect(client); return; } totalacc++; } if (totalacc >= Properties.TOTAL_ACCOUNTS_ALLOWED_SAMEIP) { Log.Warn("Account creation: too many accounts created from same ip - " + userName + " : " + ipAddress); client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.AccountNoAccessThisGame); GameServer.Instance.Disconnect(client); return; } // per timeslice - for preventing account bombing via different ip if (Properties.TIME_BETWEEN_ACCOUNT_CREATION > 0) { ts = DateTime.Now - m_lastAccountCreateTime; if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION) { Log.Warn("Account creation: time between account creation too small - " + userName + " : " + ipAddress); client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime); GameServer.Instance.Disconnect(client); return; } } m_lastAccountCreateTime = DateTime.Now; playerAccount = new Account(); playerAccount.Name = userName; playerAccount.Password = CryptPassword(password); playerAccount.Realm = 0; playerAccount.CreationDate = DateTime.Now; playerAccount.LastLogin = DateTime.Now; playerAccount.LastLoginIP = ipAddress; playerAccount.LastClientVersion = ((int)client.Version).ToString(); playerAccount.Language = Properties.SERV_LANGUAGE; playerAccount.PrivLevel = 1; if (Log.IsInfoEnabled) { Log.Info("New account created: " + userName); } GameServer.Database.AddObject(playerAccount); // Log account creation AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountCreate, "", userName); } else { if (Log.IsInfoEnabled) { Log.Info("No such account found and autocreation deactivated!"); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.AccountNotFound); GameServer.Instance.Disconnect(client); return; } } else { // check password if (!playerAccount.Password.StartsWith("##")) { playerAccount.Password = CryptPassword(playerAccount.Password); } if (!CryptPassword(password).Equals(playerAccount.Password)) { if (Log.IsInfoEnabled) { Log.Info("(" + client.TcpEndpoint + ") Wrong password!"); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.WrongPassword); // Log failure AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountFailedLogin, "", userName); GameServer.Instance.Disconnect(client); return; } // save player infos playerAccount.LastLogin = DateTime.Now; playerAccount.LastLoginIP = ipAddress; playerAccount.LastClientVersion = ((int)client.Version).ToString(); if (string.IsNullOrEmpty(playerAccount.Language)) { playerAccount.Language = Properties.SERV_LANGUAGE; } GameServer.Database.SaveObject(playerAccount); } } //Save the account table client.Account = playerAccount; // create session ID here to disable double login bug if (WorldMgr.CreateSessionID(client) < 0) { if (Log.IsInfoEnabled) { Log.InfoFormat("Too many clients connected, denied login to " + playerAccount.Name); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.TooManyPlayersLoggedIn); client.Disconnect(); return; } client.Out.SendLoginGranted(); client.ClientState = GameClient.eClientState.Connecting; // Log entry AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountSuccessfulLogin, "", userName); } } catch (DatabaseException e) { if (Log.IsErrorEnabled) { Log.Error("LoginRequestHandler", e); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount); GameServer.Instance.Disconnect(client); } catch (Exception e) { if (Log.IsErrorEnabled) { Log.Error("LoginRequestHandler", e); } client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount); GameServer.Instance.Disconnect(client); } finally { ExitLock(userName); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { string ipAddress = client.TcpEndpointAddress; packet.Skip(2); //Skip the client_type byte var major = (byte)packet.ReadByte(); var minor = (byte)packet.ReadByte(); var build = (byte)packet.ReadByte(); string password = packet.ReadString(20); bool v174; //the logger detection we had is no longer working //bool loggerUsing = false; switch (client.Version) { case GameClient.eClientVersion.Version168: case GameClient.eClientVersion.Version169: case GameClient.eClientVersion.Version170: case GameClient.eClientVersion.Version171: case GameClient.eClientVersion.Version172: case GameClient.eClientVersion.Version173: v174 = false; break; default: v174 = true; break; } if (v174) { packet.Skip(11); } else { packet.Skip(7); } uint c2 = packet.ReadInt(); uint c3 = packet.ReadInt(); uint c4 = packet.ReadInt(); if (v174) { packet.Skip(27); } else { packet.Skip(31); } string userName = packet.ReadString(20); /* if (c2 == 0 && c3 == 0x05000000 && c4 == 0xF4000000) { loggerUsing = true; Log.Warn("logger detected (" + username + ")"); }*/ // check server status if (GameServer.Instance.ServerStatus == eGameServerStatus.GSS_Closed) { client.Out.SendLoginDenied(eLoginError.GameCurrentlyClosed); Log.Info(ipAddress + " disconnected because game is closed!"); GameServer.Instance.Disconnect(client); return; } // check connection allowed with serverrules try { if (!GameServer.ServerRules.IsAllowedToConnect(client, userName)) { if (Log.IsInfoEnabled) Log.Info(ipAddress + " disconnected because IsAllowedToConnect returned false!"); GameServer.Instance.Disconnect(client); return; } } catch (Exception e) { if (Log.IsErrorEnabled) Log.Error("Error shutting down Client after IsAllowedToConnect failed!", e); } // Handle connection EnterLock(userName); try { Account playerAccount; // Make sure that client won't quit lock (client) { GameClient.eClientState state = client.ClientState; if (state != GameClient.eClientState.NotConnected) { Log.DebugFormat("wrong client state on connect {0} {1}", userName, state.ToString()); return; } if (Log.IsInfoEnabled) Log.Info(string.Format("({0})User {1} logging on! ({2} type:{3} add:{4})", ipAddress, userName, client.Version, (client.ClientType), client.ClientAddons.ToString("G"))); // check client already connected GameClient findclient = WorldMgr.GetClientByAccountName(userName, true); if (findclient != null) { if (findclient.ClientState == GameClient.eClientState.Connecting) { if (Log.IsInfoEnabled) Log.Info("User is already connecting, ignored."); client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn); return; } // in login if (findclient.ClientState == GameClient.eClientState.Linkdead) { if (Log.IsInfoEnabled) Log.Info("User is still being logged out from linkdeath!"); client.Out.SendLoginDenied(eLoginError.AccountIsInLogoutProcedure); } else { if (Log.IsInfoEnabled) Log.Info("User already logged in!"); client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn); } GameServer.Instance.Disconnect(client); return; } bool goodname = true; foreach (char c in userName.ToLower()) { if ((c < '0' || c > '9') && (c < 'a' || c > 'z') && client.Account.PrivLevel == (uint)ePrivLevel.Player) { goodname = false; break; } } // Yes! Stoping! if (!goodname) { if (Log.IsInfoEnabled) Log.Info("Invalid symbols in account name \"" + userName + "\" found!"); client.Out.SendLoginDenied(eLoginError.AccountInvalid); GameServer.Instance.Disconnect(client); return; } else { playerAccount = GameServer.Database.FindObjectByKey<Account>(userName); client.PingTime = DateTime.Now.Ticks; if (playerAccount == null) { //check autocreate ... if (GameServer.Instance.Configuration.AutoAccountCreation && Properties.ALLOW_AUTO_ACCOUNT_CREATION) { // autocreate account if (string.IsNullOrEmpty(password)) { client.Out.SendLoginDenied(eLoginError.AccountInvalid); GameServer.Instance.Disconnect(client); if (Log.IsInfoEnabled) Log.Info("Account creation failed, no password set for Account: " + userName); return; } // check for account bombing TimeSpan ts; IList<Account> allAccByIp = GameServer.Database.SelectObjects<Account>("LastLoginIP = '" + ipAddress + "'"); int totalacc = 0; foreach (Account ac in allAccByIp) { ts = DateTime.Now - ac.CreationDate; if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION_SAMEIP && totalacc > 1) { Log.Warn("Account creation: too many from same IP within set minutes - " + userName + " : " + ipAddress); client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime); GameServer.Instance.Disconnect(client); return; } totalacc++; } if (totalacc >= Properties.TOTAL_ACCOUNTS_ALLOWED_SAMEIP) { Log.Warn("Account creation: too many accounts created from same ip - " + userName + " : " + ipAddress); client.Out.SendLoginDenied(eLoginError.AccountNoAccessThisGame); GameServer.Instance.Disconnect(client); return; } // per timeslice - for preventing account bombing via different ip if (Properties.TIME_BETWEEN_ACCOUNT_CREATION > 0) { ts = DateTime.Now - m_lastAccountCreateTime; if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION) { Log.Warn("Account creation: time between account creation too small - " + userName + " : " + ipAddress); client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime); GameServer.Instance.Disconnect(client); return; } } m_lastAccountCreateTime = DateTime.Now; playerAccount = new Account(); playerAccount.Name = userName; playerAccount.Password = CryptPassword(password); playerAccount.Realm = 0; playerAccount.CreationDate = DateTime.Now; playerAccount.LastLogin = DateTime.Now; playerAccount.LastLoginIP = ipAddress; playerAccount.LastClientVersion = ((int)client.Version).ToString(); playerAccount.Language = Properties.SERV_LANGUAGE; playerAccount.PrivLevel = 1; if (Log.IsInfoEnabled) Log.Info("New account created: " + userName); GameServer.Database.AddObject(playerAccount); // Log account creation AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountCreate, "", userName); } else { if (Log.IsInfoEnabled) Log.Info("No such account found and autocreation deactivated!"); client.Out.SendLoginDenied(eLoginError.AccountNotFound); GameServer.Instance.Disconnect(client); return; } } else { // check password if (!playerAccount.Password.StartsWith("##")) { playerAccount.Password = CryptPassword(playerAccount.Password); } if (!CryptPassword(password).Equals(playerAccount.Password)) { if (Log.IsInfoEnabled) Log.Info("(" + client.TcpEndpoint + ") Wrong password!"); client.Out.SendLoginDenied(eLoginError.WrongPassword); // Log failure AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountFailedLogin, "", userName); GameServer.Instance.Disconnect(client); return; } // save player infos playerAccount.LastLogin = DateTime.Now; playerAccount.LastLoginIP = ipAddress; playerAccount.LastClientVersion = ((int)client.Version).ToString(); if (string.IsNullOrEmpty(playerAccount.Language)) { playerAccount.Language = Properties.SERV_LANGUAGE; } GameServer.Database.SaveObject(playerAccount); } } //Save the account table client.Account = playerAccount; // create session ID here to disable double login bug if (WorldMgr.CreateSessionID(client) < 0) { if (Log.IsInfoEnabled) Log.InfoFormat("Too many clients connected, denied login to " + playerAccount.Name); client.Out.SendLoginDenied(eLoginError.TooManyPlayersLoggedIn); client.Disconnect(); return; } client.Out.SendLoginGranted(); client.ClientState = GameClient.eClientState.Connecting; // Log entry AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountSuccessfulLogin, "", userName); } } catch (DatabaseException e) { if (Log.IsErrorEnabled) Log.Error("LoginRequestHandler", e); client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount); GameServer.Instance.Disconnect(client); } catch (Exception e) { if (Log.IsErrorEnabled) Log.Error("LoginRequestHandler", e); client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount); GameServer.Instance.Disconnect(client); } finally { ExitLock(userName); } }
//static int lastZ=int.MinValue; public void HandlePacket(GameClient client, GSPacketIn packet) { //Tiv: in very rare cases client send 0xA9 packet before sending S<=C 0xE8 player world initialize if ((client.Player.ObjectState != GameObject.eObjectState.Active) || (client.ClientState != GameClient.eClientState.Playing)) { return; } int environmentTick = Environment.TickCount; int packetVersion; if (client.Version > GameClient.eClientVersion.Version171) { packetVersion = 172; } else { packetVersion = 168; } int oldSpeed = client.Player.CurrentSpeed; //read the state of the player packet.Skip(2); //PID ushort data = packet.ReadShort(); int speed = (data & 0x1FF); // if(!GameServer.ServerRules.IsAllowedDebugMode(client) // && (speed > client.Player.MaxSpeed + SPEED_TOL)) if ((data & 0x200) != 0) { speed = -speed; } if (client.Player.IsMezzed || client.Player.IsStunned) { // Nidel: updating client.Player.CurrentSpeed instead of speed client.Player.CurrentSpeed = 0; } else { client.Player.CurrentSpeed = (short)speed; } client.Player.IsStrafing = ((data & 0xe000) != 0); int realZ = packet.ReadShort(); ushort xOffsetInZone = packet.ReadShort(); ushort yOffsetInZone = packet.ReadShort(); ushort currentZoneID; if (packetVersion == 168) { currentZoneID = (ushort)packet.ReadByte(); packet.Skip(1); //0x00 padding for zoneID } else { currentZoneID = packet.ReadShort(); } //Dinberg - Instance considerations. //Now this gets complicated, so listen up! We have told the client a lie when it comes to the zoneID. //As a result, every movement update, they are sending a lie back to us. Two liars could get confusing! //BUT, the lie we sent has a truth to it - the geometry and layout of the zone. As a result, the zones //x and y offsets will still actually be relevant to our current zone. And for the clones to have been //created, there must have been a real zone to begin with, of id == instanceZone.SkinID. //So, although our client is lying to us, and thinks its in another zone, that zone happens to coincide //exactly with the zone we are instancing - and so all the positions still ring true. //Philosophically speaking, its like looking in a mirror and saying 'Am I a reflected, or reflector?' //What it boils down to has no bearing whatsoever on the result of anything, so long as someone sitting //outside of the unvierse knows not to listen to whether you say which you are, and knows the truth to the //answer. Then, he need only know what you are doing ;) Zone newZone = WorldMgr.GetZone(currentZoneID); if (newZone == null) { if (client.Player == null) { return; } if (!client.Player.TempProperties.getProperty("isbeingbanned", false)) { if (log.IsErrorEnabled) { log.Error(client.Player.Name + "'s position in unknown zone! => " + currentZoneID); } GamePlayer player = client.Player; player.TempProperties.setProperty("isbeingbanned", true); player.MoveToBind(); } return; // TODO: what should we do? player lost in space } // move to bind if player fell through the floor if (realZ == 0) { client.Player.MoveTo( (ushort)client.Player.BindRegion, client.Player.BindXpos, client.Player.BindYpos, (ushort)client.Player.BindZpos, (ushort)client.Player.BindHeading ); return; } int realX = newZone.XOffset + xOffsetInZone; int realY = newZone.YOffset + yOffsetInZone; bool zoneChange = newZone != client.Player.LastPositionUpdateZone; if (zoneChange) { //If the region changes -> make sure we don't take any falling damage if (client.Player.LastPositionUpdateZone != null && newZone.ZoneRegion.ID != client.Player.LastPositionUpdateZone.ZoneRegion.ID) { client.Player.MaxLastZ = int.MinValue; } // Update water level and diving flag for the new zone client.Out.SendPlayerPositionAndObjectID(); zoneChange = true; /* * "You have entered Burial Tomb." * "Burial Tomb" * "Current area is adjusted for one level 1 player." * "Current area has a 50% instance bonus." */ string description = newZone.Description; string screenDescription = description; var translation = client.GetTranslation(newZone) as DBLanguageZone; if (translation != null) { if (!Util.IsEmpty(translation.Description)) { description = translation.Description; } if (!Util.IsEmpty(translation.ScreenDescription)) { screenDescription = translation.ScreenDescription; } } client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "PlayerPositionUpdateHandler.Entered", description), eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage(screenDescription, eChatType.CT_ScreenCenterSmaller, eChatLoc.CL_SystemWindow); client.Player.LastPositionUpdateZone = newZone; } int coordsPerSec = 0; int jumpDetect = 0; int timediff = Environment.TickCount - client.Player.LastPositionUpdateTick; int distance = 0; if (timediff > 0) { distance = client.Player.LastPositionUpdatePoint.GetDistanceTo(new Point3D(realX, realY, realZ)); coordsPerSec = distance * 1000 / timediff; if (distance < 100 && client.Player.LastPositionUpdatePoint.Z > 0) { jumpDetect = realZ - client.Player.LastPositionUpdatePoint.Z; } } #region DEBUG #if OUTPUT_DEBUG_INFO if (client.Player.LastPositionUpdatePoint.X != 0 && client.Player.LastPositionUpdatePoint.Y != 0) { log.Debug(client.Player.Name + ": distance = " + distance + ", speed = " + oldSpeed + ", coords/sec=" + coordsPerSec); } if (jumpDetect > 0) { log.Debug(client.Player.Name + ": jumpdetect = " + jumpDetect); } #endif #endregion DEBUG client.Player.LastPositionUpdateTick = Environment.TickCount; client.Player.LastPositionUpdatePoint.X = realX; client.Player.LastPositionUpdatePoint.Y = realY; client.Player.LastPositionUpdatePoint.Z = realZ; int tolerance = ServerProperties.Properties.CPS_TOLERANCE; if (client.Player.Steed != null && client.Player.Steed.MaxSpeed > 0) { tolerance += client.Player.Steed.MaxSpeed; } else if (client.Player.MaxSpeed > 0) { tolerance += client.Player.MaxSpeed; } if (client.Player.IsJumping) { coordsPerSec = 0; jumpDetect = 0; client.Player.IsJumping = false; } if (client.Player.IsAllowedToFly == false && (coordsPerSec > tolerance || jumpDetect > ServerProperties.Properties.JUMP_TOLERANCE)) { bool isHackDetected = true; if (coordsPerSec > tolerance) { // check to see if CPS time tolerance is exceeded int lastCPSTick = client.Player.TempProperties.getProperty <int>(LASTCPSTICK, 0); if (environmentTick - lastCPSTick > ServerProperties.Properties.CPS_TIME_TOLERANCE) { isHackDetected = false; } } if (isHackDetected) { StringBuilder builder = new StringBuilder(); builder.Append("MOVEHACK_DETECT"); builder.Append(": CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); builder.Append(" CPS:="); builder.Append(coordsPerSec); builder.Append(" JT="); builder.Append(jumpDetect); ChatUtil.SendDebugMessage(client, builder.ToString()); if (client.Account.PrivLevel == 1) { GameServer.Instance.LogCheatAction(builder.ToString()); if (ServerProperties.Properties.ENABLE_MOVEDETECT) { if (ServerProperties.Properties.BAN_HACKERS && false) // banning disabled until this technique is proven accurate { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban MOVEHACK:(CPS:{0}, JT:{1}) on player:{2}", coordsPerSec, jumpDetect, client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); string message = ""; message = "You have been auto kicked and banned due to movement hack detection!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } else { string message = ""; message = "You have been auto kicked due to movement hack detection!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } client.Disconnect(); return; } } } client.Player.TempProperties.setProperty(LASTCPSTICK, environmentTick); } ushort headingflag = packet.ReadShort(); client.Player.Heading = (ushort)(headingflag & 0xFFF); ushort flyingflag = packet.ReadShort(); byte flags = (byte)packet.ReadByte(); if (client.Player.X != realX || client.Player.Y != realY) { client.Player.TempProperties.setProperty(LASTMOVEMENTTICK, client.Player.CurrentRegion.Time); } client.Player.X = realX; client.Player.Y = realY; client.Player.Z = realZ; if (zoneChange) { // update client zone information for waterlevel and diving client.Out.SendPlayerPositionAndObjectID(); } // used to predict current position, should be before // any calculation (like fall damage) client.Player.MovementStartTick = Environment.TickCount; // Begin ---------- New Area System ----------- if (client.Player.CurrentRegion.Time > client.Player.AreaUpdateTick) // check if update is needed { var oldAreas = client.Player.CurrentAreas; // Because we may be in an instance we need to do the area check from the current region // rather than relying on the zone which is in the skinned region. - Tolakram var newAreas = client.Player.CurrentRegion.GetAreasOfZone(newZone, client.Player); // Check for left areas if (oldAreas != null) { foreach (IArea area in oldAreas) { if (!newAreas.Contains(area)) { area.OnPlayerLeave(client.Player); } } } // Check for entered areas foreach (IArea area in newAreas) { if (oldAreas == null || !oldAreas.Contains(area)) { area.OnPlayerEnter(client.Player); } } // set current areas to new one... client.Player.CurrentAreas = newAreas; client.Player.AreaUpdateTick = client.Player.CurrentRegion.Time + 2000; // update every 2 seconds } // End ---------- New Area System ----------- client.Player.TargetInView = ((flags & 0x10) != 0); client.Player.GroundTargetInView = ((flags & 0x08) != 0); client.Player.IsTorchLighted = ((flags & 0x80) != 0); //7 6 5 4 3 2 1 0 //15 14 13 12 11 10 9 8 // 1 1 const string SHLASTUPDATETICK = "SHPLAYERPOSITION_LASTUPDATETICK"; const string SHLASTFLY = "SHLASTFLY_STRING"; const string SHLASTSTATUS = "SHLASTSTATUS_STRING"; int SHlastTick = client.Player.TempProperties.getProperty <int>(SHLASTUPDATETICK); int SHlastFly = client.Player.TempProperties.getProperty <int>(SHLASTFLY); int SHlastStatus = client.Player.TempProperties.getProperty <int>(SHLASTSTATUS); int SHcount = client.Player.TempProperties.getProperty <int>(SHSPEEDCOUNTER); int status = (data & 0x1FF ^ data) >> 8; int fly = (flyingflag & 0x1FF ^ flyingflag) >> 8; if (client.Player.IsJumping) { SHcount = 0; } if (SHlastTick != 0 && SHlastTick != environmentTick) { if (((SHlastStatus == status || (status & 0x8) == 0)) && ((fly & 0x80) != 0x80) && (SHlastFly == fly || (SHlastFly & 0x10) == (fly & 0x10) || !((((SHlastFly & 0x10) == 0x10) && ((fly & 0x10) == 0x0) && (flyingflag & 0x7FF) > 0)))) { if ((environmentTick - SHlastTick) < 400) { SHcount++; if (SHcount > 1 && client.Account.PrivLevel > 1) { //Apo: ?? no idea how to name the first parameter for language translation: 1: ??, 2: {detected} ?, 3: {count} ? client.Out.SendMessage(string.Format("SH: ({0}) detected: {1}, count {2}", 500 / (environmentTick - SHlastTick), environmentTick - SHlastTick, SHcount), eChatType.CT_Staff, eChatLoc.CL_SystemWindow); } if (SHcount % 5 == 0) { StringBuilder builder = new StringBuilder(); builder.Append("TEST_SH_DETECT["); builder.Append(SHcount); builder.Append("] ("); builder.Append(environmentTick - SHlastTick); builder.Append("): CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); GameServer.Instance.LogCheatAction(builder.ToString()); if (client.Account.PrivLevel > 1) { client.Out.SendMessage("SH: Logging SH cheat.", eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); if (SHcount >= ServerProperties.Properties.SPEEDHACK_TOLERANCE) { client.Out.SendMessage("SH: Player would have been banned!", eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); } } if ((client.Account.PrivLevel == 1) && SHcount >= ServerProperties.Properties.SPEEDHACK_TOLERANCE) { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban SH:({0},{1}) on player:{2}", SHcount, environmentTick - SHlastTick, client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); string message = ""; message = "You have been auto kicked and banned for speed hacking!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } else { string message = ""; message = "You have been auto kicked for speed hacking!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } client.Disconnect(); return; } } } else { SHcount = 0; } SHlastTick = environmentTick; } } else { SHlastTick = environmentTick; } int state = ((data >> 10) & 7); client.Player.IsClimbing = (state == 7); client.Player.IsSwimming = (state == 1); if (state == 3 && client.Player.TempProperties.getProperty <bool>(GamePlayer.DEBUG_MODE_PROPERTY, false) == false && client.Player.IsAllowedToFly == false) //debugFly on, but player not do /debug on (hack) { StringBuilder builder = new StringBuilder(); builder.Append("HACK_FLY"); builder.Append(": CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); GameServer.Instance.LogCheatAction(builder.ToString()); { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban flying hack: on player:{0}", client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); } string message = ""; message = "Client Hack Detected!"; for (int i = 0; i < 6; i++) { client.Out.SendMessage(message, eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_System, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Disconnect(); return; } } SHlastFly = fly; SHlastStatus = status; client.Player.TempProperties.setProperty(SHLASTUPDATETICK, SHlastTick); client.Player.TempProperties.setProperty(SHLASTFLY, SHlastFly); client.Player.TempProperties.setProperty(SHLASTSTATUS, SHlastStatus); client.Player.TempProperties.setProperty(SHSPEEDCOUNTER, SHcount); lock (client.Player.LastUniqueLocations) { GameLocation[] locations = client.Player.LastUniqueLocations; GameLocation loc = locations[0]; if (loc.X != realX || loc.Y != realY || loc.Z != realZ || loc.RegionID != client.Player.CurrentRegionID) { loc = locations[locations.Length - 1]; Array.Copy(locations, 0, locations, 1, locations.Length - 1); locations[0] = loc; loc.X = realX; loc.Y = realY; loc.Z = realZ; loc.Heading = client.Player.Heading; loc.RegionID = client.Player.CurrentRegionID; } } //**************// //FALLING DAMAGE// //**************// if (GameServer.ServerRules.CanTakeFallDamage(client.Player) && client.Player.IsSwimming == false) { int maxLastZ = client.Player.MaxLastZ; /* Are we on the ground? */ if ((flyingflag >> 15) != 0) { int safeFallLevel = client.Player.GetAbilityLevel(Abilities.SafeFall); int fallSpeed = (flyingflag & 0xFFF) - 100 * safeFallLevel; // 0x7FF fall speed and 0x800 bit = fall speed overcaped int fallMinSpeed = 400; int fallDivide = 6; if (client.Version >= GameClient.eClientVersion.Version188) { fallMinSpeed = 500; fallDivide = 15; } int fallPercent = Math.Min(99, (fallSpeed - (fallMinSpeed + 1)) / fallDivide); if (fallSpeed > fallMinSpeed) { client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "PlayerPositionUpdateHandler.FallingDamage"), eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); client.Player.CalcFallDamage(fallPercent); } client.Player.MaxLastZ = client.Player.Z; } else { // always set Z if on the ground if (flyingflag == 0) { client.Player.MaxLastZ = client.Player.Z; } // set Z if in air and higher than old Z else if (maxLastZ < client.Player.Z) { client.Player.MaxLastZ = client.Player.Z; } } } //**************// byte[] con168 = packet.ToArray(); //Riding is set here! if (client.Player.Steed != null && client.Player.Steed.ObjectState == GameObject.eObjectState.Active) { client.Player.Heading = client.Player.Steed.Heading; con168[2] = 0x18; // Set ride flag 00011000 con168[3] = 0; // player speed = 0 while ride con168[12] = (byte)(client.Player.Steed.ObjectID >> 8); //heading = steed ID con168[13] = (byte)(client.Player.Steed.ObjectID & 0xFF); con168[14] = (byte)0; con168[15] = (byte)(client.Player.Steed.RiderSlot(client.Player)); // there rider slot this player } else if (!client.Player.IsAlive) { con168[2] &= 0xE3; //11100011 con168[2] |= 0x14; //Set dead flag 00010100 } //diving is set here con168[16] &= 0xFB; //11 11 10 11 if ((con168[16] & 0x02) != 0x00) { client.Player.IsDiving = true; con168[16] |= 0x04; } else { client.Player.IsDiving = false; } con168[16] &= 0xFC; //11 11 11 00 cleared Wireframe & Stealth bits if (client.Player.IsWireframe) { con168[16] |= 0x01; } //stealth is set here if (client.Player.IsStealthed) { con168[16] |= 0x02; } con168[17] = (byte)((con168[17] & 0x80) | client.Player.HealthPercent); // zone ID has changed in 1.72, fix bytes 11 and 12 byte[] con172 = (byte[])con168.Clone(); if (packetVersion == 168) { // client sent v168 pos update packet, fix 172 version con172[10] = 0; con172[11] = con168[10]; } else { // client sent v172 pos update packet, fix 168 version con168[10] = con172[11]; con168[11] = 0; } GSUDPPacketOut outpak168 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); //Now copy the whole content of the packet outpak168.Write(con168, 0, 18 /*con168.Length*/); outpak168.WritePacketLength(); GSUDPPacketOut outpak172 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); //Now copy the whole content of the packet outpak172.Write(con172, 0, 18 /*con172.Length*/); outpak172.WritePacketLength(); // byte[] pak168 = outpak168.GetBuffer(); // byte[] pak172 = outpak172.GetBuffer(); // outpak168 = null; // outpak172 = null; GSUDPPacketOut outpak190 = null; GSUDPPacketOut outpak1112 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); outpak1112.Write(con172, 0, 18 /*con172.Length*/); outpak1112.WriteByte(client.Player.ManaPercent); outpak1112.WriteByte(client.Player.EndurancePercent); outpak1112.WriteByte((byte)(client.Player.RPFlag ? 1 : 0)); outpak1112.WriteByte(0); //outpak1112.WriteByte((con168.Length == 22) ? con168[21] : (byte)0); outpak1112.WritePacketLength(); foreach (GamePlayer player in client.Player.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if (player == null) { continue; } //No position updates for ourselves if (player == client.Player) { // Update Player Cache (Client sending Packet is admitting he's already having it) player.Client.GameObjectUpdateArray[new Tuple <ushort, ushort>(client.Player.CurrentRegionID, (ushort)client.Player.ObjectID)] = GameTimer.GetTickCount(); continue; } //no position updates in different houses if ((client.Player.InHouse || player.InHouse) && player.CurrentHouse != client.Player.CurrentHouse) { continue; } if (client.Player.MinotaurRelic != null) { MinotaurRelic relic = client.Player.MinotaurRelic; if (!relic.Playerlist.Contains(player) && player != client.Player) { relic.Playerlist.Add(player); player.Out.SendMinotaurRelicWindow(client.Player, client.Player.MinotaurRelic.Effect, true); } } if (!client.Player.IsStealthed || player.CanDetect(client.Player)) { // Update Player Cache player.Client.GameObjectUpdateArray[new Tuple <ushort, ushort>(client.Player.CurrentRegionID, (ushort)client.Player.ObjectID)] = GameTimer.GetTickCount(); //forward the position packet like normal! if (player.Client.Version >= GameClient.eClientVersion.Version1112) { player.Out.SendUDPRaw(outpak1112); } else if (player.Client.Version >= GameClient.eClientVersion.Version190) { if (outpak190 == null) { outpak190 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); outpak190.Write(con172, 0, 18 /*con172.Length*/); outpak190.WriteByte(client.Player.ManaPercent); outpak190.WriteByte(client.Player.EndurancePercent); outpak190.FillString(client.Player.CharacterClass.Name, 32); // roleplay flag, if == 1, show name (RP) with gray color if (client.Player.RPFlag) { outpak190.WriteByte(1); } else { outpak190.WriteByte(0); } outpak190.WriteByte((con168.Length == 54) ? con168[53] : (byte)0); // send last byte for 190+ packets outpak190.WritePacketLength(); } player.Out.SendUDPRaw(outpak190); } else if (player.Client.Version >= GameClient.eClientVersion.Version172) { player.Out.SendUDPRaw(outpak172); } else { player.Out.SendUDPRaw(outpak168); } } else { player.Out.SendObjectDelete(client.Player); //remove the stealthed player from view } } if (client.Player.CharacterClass.ID == (int)eCharacterClass.Warlock) { //Send Chamber effect client.Player.Out.SendWarlockChamberEffect(client.Player); } //handle closing of windows //trade window if (client.Player.TradeWindow != null) { if (client.Player.TradeWindow.Partner != null) { if (!client.Player.IsWithinRadius(client.Player.TradeWindow.Partner, WorldMgr.GIVE_ITEM_DISTANCE)) { client.Player.TradeWindow.CloseTrade(); } } } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null || client.Player == null) { return; } if (client.Player.ObjectState != GameObject.eObjectState.Active) { return; } ushort sessionId = packet.ReadShort(); // session ID if (client.SessionID != sessionId) { // GameServer.BanAccount(client, 120, "Hack sessionId", string.Format("Wrong sessionId:0x{0} in 0xBA packet (SessionID:{1})", sessionId, client.SessionID)); return; // client hack } //ushort head = packet.ReadShort(); //client.Player.Heading = (ushort)(head & 0xFFF); client.Player.Heading = packet.ReadShort(); packet.Skip(1); // unknown int flags = packet.ReadByte(); // client.Player.PetInView = ((flags & 0x04) != 0); // TODO client.Player.GroundTargetInView = ((flags & 0x08) != 0); client.Player.TargetInView = ((flags & 0x10) != 0); packet.Skip(1); byte ridingFlag = (byte)packet.ReadByte(); if (client.Player.IsWireframe) { flags |= 0x01; } //stealth is set here if (client.Player.IsStealthed) { flags |= 0x02; } GSUDPPacketOut outpak190 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerHeading)); foreach (GamePlayer player in client.Player.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if (player != null && player != client.Player) { outpak190.WriteShort((ushort)client.SessionID); outpak190.WriteShort(client.Player.Heading); outpak190.WriteShort((ushort)flags); outpak190.WriteByte(0); //outpak190.WriteByte(0); outpak190.WriteByte(ridingFlag); outpak190.WriteByte(client.Player.HealthPercent); outpak190.WriteByte(client.Player.ManaPercent); outpak190.WriteByte(client.Player.EndurancePercent); outpak190.WriteByte(0);// unknown yet outpak190.WritePacketLength(); player.Out.SendUDPRaw(outpak190); } } }
//static int lastZ=int.MinValue; public void HandlePacket(GameClient client, GSPacketIn packet) { //Tiv: in very rare cases client send 0xA9 packet before sending S<=C 0xE8 player world initialize if ((client.Player.ObjectState != GameObject.eObjectState.Active) || (client.ClientState != GameClient.eClientState.Playing)) return; int environmentTick = Environment.TickCount; int packetVersion; if (client.Version > GameClient.eClientVersion.Version171) { packetVersion = 172; } else { packetVersion = 168; } int oldSpeed = client.Player.CurrentSpeed; //read the state of the player packet.Skip(2); //PID ushort data = packet.ReadShort(); int speed = (data & 0x1FF); // if(!GameServer.ServerRules.IsAllowedDebugMode(client) // && (speed > client.Player.MaxSpeed + SPEED_TOL)) if ((data & 0x200) != 0) speed = -speed; if (client.Player.IsMezzed || client.Player.IsStunned) { // Nidel: updating client.Player.CurrentSpeed instead of speed client.Player.CurrentSpeed = 0; } else { client.Player.CurrentSpeed = (short)speed; } client.Player.IsStrafing = ((data & 0xe000) != 0); int realZ = packet.ReadShort(); ushort xOffsetInZone = packet.ReadShort(); ushort yOffsetInZone = packet.ReadShort(); ushort currentZoneID; if (packetVersion == 168) { currentZoneID = (ushort)packet.ReadByte(); packet.Skip(1); //0x00 padding for zoneID } else { currentZoneID = packet.ReadShort(); } //Dinberg - Instance considerations. //Now this gets complicated, so listen up! We have told the client a lie when it comes to the zoneID. //As a result, every movement update, they are sending a lie back to us. Two liars could get confusing! //BUT, the lie we sent has a truth to it - the geometry and layout of the zone. As a result, the zones //x and y offsets will still actually be relevant to our current zone. And for the clones to have been //created, there must have been a real zone to begin with, of id == instanceZone.SkinID. //So, although our client is lying to us, and thinks its in another zone, that zone happens to coincide //exactly with the zone we are instancing - and so all the positions still ring true. //Philosophically speaking, its like looking in a mirror and saying 'Am I a reflected, or reflector?' //What it boils down to has no bearing whatsoever on the result of anything, so long as someone sitting //outside of the unvierse knows not to listen to whether you say which you are, and knows the truth to the //answer. Then, he need only know what you are doing ;) Zone newZone = WorldMgr.GetZone(currentZoneID); if (newZone == null) { if (client.Player == null) return; if (!client.Player.TempProperties.getProperty("isbeingbanned", false)) { if (log.IsErrorEnabled) log.Error(client.Player.Name + "'s position in unknown zone! => " + currentZoneID); GamePlayer player = client.Player; player.TempProperties.setProperty("isbeingbanned", true); player.MoveToBind(); } return; // TODO: what should we do? player lost in space } // move to bind if player fell through the floor if (realZ == 0) { client.Player.MoveTo( (ushort)client.Player.DBCharacter.BindRegion, client.Player.DBCharacter.BindXpos, client.Player.DBCharacter.BindYpos, (ushort)client.Player.DBCharacter.BindZpos, (ushort)client.Player.DBCharacter.BindHeading ); return; } int realX = newZone.XOffset + xOffsetInZone; int realY = newZone.YOffset + yOffsetInZone; bool zoneChange = newZone != client.Player.LastPositionUpdateZone; if (zoneChange) { //If the region changes -> make sure we don't take any falling damage if (client.Player.LastPositionUpdateZone != null && newZone.ZoneRegion.ID != client.Player.LastPositionUpdateZone.ZoneRegion.ID) client.Player.MaxLastZ = int.MinValue; // Update water level and diving flag for the new zone client.Out.SendPlayerPositionAndObjectID(); zoneChange = true; /* * "You have entered Burial Tomb." * "Burial Tomb" * "Current area is adjusted for one level 1 player." * "Current area has a 50% instance bonus." */ string description = newZone.Description; string screenDescription = description; DataObject translation = LanguageMgr.GetTranslation(client, newZone); if (translation != null) { if (!Util.IsEmpty(((DBLanguageZone)translation).Description)) description = ((DBLanguageZone)translation).Description; if (!Util.IsEmpty(((DBLanguageZone)translation).ScreenDescription)) screenDescription = ((DBLanguageZone)translation).ScreenDescription; } client.Out.SendMessage(LanguageMgr.GetTranslation(client, "PlayerPositionUpdateHandler.Entered", description), eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage(screenDescription, eChatType.CT_ScreenCenterSmaller, eChatLoc.CL_SystemWindow); client.Player.LastPositionUpdateZone = newZone; } int coordsPerSec = 0; int jumpDetect = 0; int timediff = Environment.TickCount - client.Player.LastPositionUpdateTick; int distance = 0; if (timediff > 0) { distance = client.Player.LastPositionUpdatePoint.GetDistanceTo(new Point3D(realX, realY, realZ)); coordsPerSec = distance * 1000 / timediff; if (distance < 100 && client.Player.LastPositionUpdatePoint.Z > 0) { jumpDetect = realZ - client.Player.LastPositionUpdatePoint.Z; } } #region DEBUG #if OUTPUT_DEBUG_INFO if (client.Player.LastPositionUpdatePoint.X != 0 && client.Player.LastPositionUpdatePoint.Y != 0) { log.Debug(client.Player.Name + ": distance = " + distance + ", speed = " + oldSpeed + ", coords/sec=" + coordsPerSec); } if (jumpDetect > 0) { log.Debug(client.Player.Name + ": jumpdetect = " + jumpDetect); } #endif #endregion DEBUG client.Player.LastPositionUpdateTick = Environment.TickCount; client.Player.LastPositionUpdatePoint.X = realX; client.Player.LastPositionUpdatePoint.Y = realY; client.Player.LastPositionUpdatePoint.Z = realZ; int tolerance = ServerProperties.Properties.CPS_TOLERANCE; if (client.Player.Steed != null && client.Player.Steed.MaxSpeed > 0) { tolerance += client.Player.Steed.MaxSpeed; } else if (client.Player.MaxSpeed > 0) { tolerance += client.Player.MaxSpeed; } if (client.Player.IsJumping) { coordsPerSec = 0; jumpDetect = 0; client.Player.IsJumping = false; } if (client.Player.CanFly == false && (coordsPerSec > tolerance || jumpDetect > ServerProperties.Properties.JUMP_TOLERANCE)) { bool isHackDetected = true; if (coordsPerSec > tolerance) { // check to see if CPS time tolerance is exceeded int lastCPSTick = client.Player.TempProperties.getProperty<int>(LASTCPSTICK, 0); if (environmentTick - lastCPSTick > ServerProperties.Properties.CPS_TIME_TOLERANCE) { isHackDetected = false; } } if (isHackDetected) { StringBuilder builder = new StringBuilder(); builder.Append("MOVEHACK_DETECT"); builder.Append(": CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); builder.Append(" CPS:="); builder.Append(coordsPerSec); builder.Append(" JT="); builder.Append(jumpDetect); ChatUtil.SendDebugMessage(client, builder.ToString()); if (client.Account.PrivLevel == 1) { GameServer.Instance.LogCheatAction(builder.ToString()); if (ServerProperties.Properties.ENABLE_MOVEDETECT) { if (ServerProperties.Properties.BAN_HACKERS && false) // banning disabled until this technique is proven accurate { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban MOVEHACK:(CPS:{0}, JT:{1}) on player:{2}", coordsPerSec, jumpDetect, client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); string message = ""; message = "You have been auto kicked and banned due to movement hack detection!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } else { string message = ""; message = "You have been auto kicked due to movement hack detection!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } client.Disconnect(); return; } } } client.Player.TempProperties.setProperty(LASTCPSTICK, environmentTick); } ushort headingflag = packet.ReadShort(); client.Player.Heading = (ushort)(headingflag & 0xFFF); ushort flyingflag = packet.ReadShort(); byte flags = (byte)packet.ReadByte(); if (client.Player.X != realX || client.Player.Y != realY) { client.Player.TempProperties.setProperty(LASTMOVEMENTTICK, client.Player.CurrentRegion.Time); } client.Player.X = realX; client.Player.Y = realY; client.Player.Z = realZ; if (zoneChange) { // update client zone information for waterlevel and diving client.Out.SendPlayerPositionAndObjectID(); } // used to predict current position, should be before // any calculation (like fall damage) client.Player.MovementStartTick = Environment.TickCount; // Begin ---------- New Area System ----------- if (client.Player.CurrentRegion.Time > client.Player.AreaUpdateTick) // check if update is needed { IList oldAreas = client.Player.CurrentAreas; // Because we may be in an instance we need to do the area check from the current region // rather than relying on the zone which is in the skinned region. - Tolakram IList newAreas = client.Player.CurrentRegion.GetAreasOfZone(newZone, client.Player); // Check for left areas if (oldAreas != null) { foreach (IArea area in oldAreas) { if (!newAreas.Contains(area)) { area.OnPlayerLeave(client.Player); } } } // Check for entered areas foreach (IArea area in newAreas) { if (oldAreas == null || !oldAreas.Contains(area)) { area.OnPlayerEnter(client.Player); } } // set current areas to new one... client.Player.CurrentAreas = newAreas; client.Player.AreaUpdateTick = client.Player.CurrentRegion.Time + 2000; // update every 2 seconds } // End ---------- New Area System ----------- client.Player.TargetInView = ((flags & 0x10) != 0); client.Player.GroundTargetInView = ((flags & 0x08) != 0); //7 6 5 4 3 2 1 0 //15 14 13 12 11 10 9 8 // 1 1 const string SHLASTUPDATETICK = "SHPLAYERPOSITION_LASTUPDATETICK"; const string SHLASTFLY = "SHLASTFLY_STRING"; const string SHLASTSTATUS = "SHLASTSTATUS_STRING"; int SHlastTick = client.Player.TempProperties.getProperty<int>(SHLASTUPDATETICK); int SHlastFly = client.Player.TempProperties.getProperty<int>(SHLASTFLY); int SHlastStatus = client.Player.TempProperties.getProperty<int>(SHLASTSTATUS); int SHcount = client.Player.TempProperties.getProperty<int>(SHSPEEDCOUNTER); int status = (data & 0x1FF ^ data) >> 8; int fly = (flyingflag & 0x1FF ^ flyingflag) >> 8; if (client.Player.IsJumping) { SHcount = 0; } if (SHlastTick != 0 && SHlastTick != environmentTick) { if (((SHlastStatus == status || (status & 0x8) == 0)) && ((fly & 0x80) != 0x80) && (SHlastFly == fly || (SHlastFly & 0x10) == (fly & 0x10) || !((((SHlastFly & 0x10) == 0x10) && ((fly & 0x10) == 0x0) && (flyingflag & 0x7FF) > 0)))) { if ((environmentTick - SHlastTick) < 400) { SHcount++; if (SHcount > 1 && client.Account.PrivLevel > 1) { //Apo: ?? no idea how to name the first parameter for language translation: 1: ??, 2: {detected} ?, 3: {count} ? client.Out.SendMessage(string.Format("SH: ({0}) detected: {1}, count {2}", 500 / (environmentTick - SHlastTick), environmentTick - SHlastTick, SHcount), eChatType.CT_Staff, eChatLoc.CL_SystemWindow); } if (SHcount % 5 == 0) { StringBuilder builder = new StringBuilder(); builder.Append("TEST_SH_DETECT["); builder.Append(SHcount); builder.Append("] ("); builder.Append(environmentTick - SHlastTick); builder.Append("): CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); GameServer.Instance.LogCheatAction(builder.ToString()); if (client.Account.PrivLevel > 1) { client.Out.SendMessage("SH: Logging SH cheat.", eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); if (SHcount >= ServerProperties.Properties.SPEEDHACK_TOLERANCE) client.Out.SendMessage("SH: Player would have been banned!", eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); } if ((client.Account.PrivLevel == 1) && SHcount >= ServerProperties.Properties.SPEEDHACK_TOLERANCE) { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban SH:({0},{1}) on player:{2}", SHcount, environmentTick - SHlastTick, client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); string message = ""; message = "You have been auto kicked and banned for speed hacking!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } else { string message = ""; message = "You have been auto kicked for speed hacking!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } client.Disconnect(); return; } } } else { SHcount = 0; } SHlastTick = environmentTick; } } else { SHlastTick = environmentTick; } int state = ((data >> 10) & 7); client.Player.IsClimbing = (state == 7); client.Player.IsSwimming = (state == 1); if (state == 3 && client.Player.TempProperties.getProperty<object>(GamePlayer.DEBUG_MODE_PROPERTY, null) == null && !client.Player.CanFly) //debugFly on, but player not do /debug on (hack) { StringBuilder builder = new StringBuilder(); builder.Append("HACK_FLY"); builder.Append(": CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); GameServer.Instance.LogCheatAction(builder.ToString()); { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban flying hack: on player:{0}", client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); } string message = ""; message = "Client Hack Detected!"; for (int i = 0; i < 6; i++) { client.Out.SendMessage(message, eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_System, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Disconnect(); return; } } SHlastFly = fly; SHlastStatus = status; client.Player.TempProperties.setProperty(SHLASTUPDATETICK, SHlastTick); client.Player.TempProperties.setProperty(SHLASTFLY, SHlastFly); client.Player.TempProperties.setProperty(SHLASTSTATUS, SHlastStatus); client.Player.TempProperties.setProperty(SHSPEEDCOUNTER, SHcount); lock (client.Player.LastUniqueLocations) { GameLocation[] locations = client.Player.LastUniqueLocations; GameLocation loc = locations[0]; if (loc.X != realX || loc.Y != realY || loc.Z != realZ || loc.RegionID != client.Player.CurrentRegionID) { loc = locations[locations.Length - 1]; Array.Copy(locations, 0, locations, 1, locations.Length - 1); locations[0] = loc; loc.X = realX; loc.Y = realY; loc.Z = realZ; loc.Heading = client.Player.Heading; loc.RegionID = client.Player.CurrentRegionID; } } //**************// //FALLING DAMAGE// //**************// if (GameServer.ServerRules.CanTakeFallDamage(client.Player) && client.Player.IsSwimming == false) { int maxLastZ = client.Player.MaxLastZ; /* Are we on the ground? */ if ((flyingflag >> 15) != 0) { int safeFallLevel = client.Player.GetAbilityLevel(Abilities.SafeFall); int fallSpeed = (flyingflag & 0xFFF) - 100 * safeFallLevel; // 0x7FF fall speed and 0x800 bit = fall speed overcaped int fallMinSpeed = 400; int fallDivide = 6; if (client.Version >= GameClient.eClientVersion.Version188) { fallMinSpeed = 500; fallDivide = 15; } int fallPercent = Math.Min(99, (fallSpeed - (fallMinSpeed + 1)) / fallDivide); if (fallSpeed > fallMinSpeed) { client.Out.SendMessage(LanguageMgr.GetTranslation(client, "PlayerPositionUpdateHandler.FallingDamage"), eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); client.Player.CalcFallDamage(fallPercent); } client.Player.MaxLastZ = client.Player.Z; } else { // always set Z if on the ground if (flyingflag == 0) client.Player.MaxLastZ = client.Player.Z; // set Z if in air and higher than old Z else if (maxLastZ < client.Player.Z) client.Player.MaxLastZ = client.Player.Z; } } //**************// byte[] con168 = packet.ToArray(); //Riding is set here! if (client.Player.Steed != null && client.Player.Steed.ObjectState == GameObject.eObjectState.Active) { client.Player.Heading = client.Player.Steed.Heading; con168[2] = 0x18; // Set ride flag 00011000 con168[3] = 0; // player speed = 0 while ride con168[12] = (byte)(client.Player.Steed.ObjectID >> 8); //heading = steed ID con168[13] = (byte)(client.Player.Steed.ObjectID & 0xFF); con168[14] = (byte)0; con168[15] = (byte)(client.Player.Steed.RiderSlot(client.Player)); // there rider slot this player } else if (!client.Player.IsAlive) { con168[2] &= 0xE3; //11100011 con168[2] |= 0x14; //Set dead flag 00010100 } //diving is set here con168[16] &= 0xFB; //11 11 10 11 if ((con168[16] & 0x02) != 0x00) { client.Player.IsDiving = true; con168[16] |= 0x04; } else client.Player.IsDiving = false; con168[16] &= 0xFC; //11 11 11 00 cleared Wireframe & Stealth bits if (client.Player.IsWireframe) { con168[16] |= 0x01; } //stealth is set here if (client.Player.IsStealthed) { con168[16] |= 0x02; } con168[17] = (byte)((con168[17] & 0x80) | client.Player.HealthPercent); // zone ID has changed in 1.72, fix bytes 11 and 12 byte[] con172 = (byte[])con168.Clone(); if (packetVersion == 168) { // client sent v168 pos update packet, fix 172 version con172[10] = 0; con172[11] = con168[10]; } else { // client sent v172 pos update packet, fix 168 version con168[10] = con172[11]; con168[11] = 0; } GSUDPPacketOut outpak168 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); //Now copy the whole content of the packet outpak168.Write(con168, 0, 18/*con168.Length*/); outpak168.WritePacketLength(); GSUDPPacketOut outpak172 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); //Now copy the whole content of the packet outpak172.Write(con172, 0, 18/*con172.Length*/); outpak172.WritePacketLength(); // byte[] pak168 = outpak168.GetBuffer(); // byte[] pak172 = outpak172.GetBuffer(); // outpak168 = null; // outpak172 = null; GSUDPPacketOut outpak190 = null; foreach (GamePlayer player in client.Player.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if (player == null) continue; //No position updates for ourselves if (player == client.Player) continue; //no position updates in different houses if ((client.Player.InHouse || player.InHouse) && player.CurrentHouse != client.Player.CurrentHouse) continue; if (client.Player.MinotaurRelic != null) { MinotaurRelic relic = client.Player.MinotaurRelic; if (!relic.Playerlist.Contains(player) && player != client.Player) { relic.Playerlist.Add(player); player.Out.SendMinotaurRelicWindow(client.Player, client.Player.MinotaurRelic.Effect, true); } } if (!client.Player.IsStealthed || player.CanDetect(client.Player)) { //forward the position packet like normal! if (player.Client.Version >= GameClient.eClientVersion.Version190) { if (outpak190 == null) { outpak190 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); outpak190.Write(con172, 0, 18/*con172.Length*/); outpak190.WriteByte(client.Player.ManaPercent); outpak190.WriteByte(client.Player.EndurancePercent); outpak190.FillString(client.Player.CharacterClass.Name, 32); // roleplay flag, if == 1, show name (RP) with gray color if (client.Player.RPFlag) outpak190.WriteByte(1); else outpak190.WriteByte(0); outpak190.WriteByte((con168.Length == 54) ? con168[53] : (byte)0); // send last byte for 190+ packets outpak190.WritePacketLength(); } player.Out.SendUDPRaw(outpak190); } else if (player.Client.Version >= GameClient.eClientVersion.Version172) player.Out.SendUDPRaw(outpak172); else player.Out.SendUDPRaw(outpak168); } else player.Out.SendObjectDelete(client.Player); //remove the stealthed player from view } if (client.Player.CharacterClass.ID == (int)eCharacterClass.Warlock) { //Send Chamber effect client.Player.Out.SendWarlockChamberEffect(client.Player); } //handle closing of windows //trade window if (client.Player.TradeWindow != null) { if (client.Player.TradeWindow.Partner != null) { if (!client.Player.IsWithinRadius(client.Player.TradeWindow.Partner, WorldMgr.GIVE_ITEM_DISTANCE)) client.Player.TradeWindow.CloseTrade(); } } }
//static int lastZ=int.MinValue; public void HandlePacket(GameClient client, GSPacketIn packet) { //Tiv: in very rare cases client send 0xA9 packet before sending S<=C 0xE8 player world initialize if ((client.Player.ObjectState != GameObject.eObjectState.Active) || (client.ClientState != GameClient.eClientState.Playing)) { return; } int environmentTick = Environment.TickCount; int oldSpeed = client.Player.CurrentSpeed; int newPlayerX = (int)packet.ReadFloatLowEndian(); int newPlayerY = (int)packet.ReadFloatLowEndian(); int newPlayerZ = (int)packet.ReadFloatLowEndian(); int newPlayerSpeed = (int)packet.ReadFloatLowEndian(); int newPlayerZSpeed = (int)packet.ReadFloatLowEndian(); ushort sessionID = packet.ReadShort(); ushort currentZoneID = packet.ReadShort(); ushort playerState = packet.ReadShort(); ushort fallingDMG = packet.ReadShort(); ushort newHeading = packet.ReadShort(); byte playerAction = (byte)packet.ReadByte(); packet.Skip(2); // unknown bytes x2 byte playerHealth = (byte)packet.ReadByte(); // two trailing bytes, no data //int speed = (newPlayerSpeed & 0x1FF); //Flags1 = (eFlags1)playerState; //Flags2 = (eFlags2)playerAction; if (client.Player.IsMezzed || client.Player.IsStunned) { // Nidel: updating client.Player.CurrentSpeed instead of speed client.Player.CurrentSpeed = 0; } else { client.Player.CurrentSpeed = (short)newPlayerSpeed; } /* * client.Player.IsStrafing = Flags1 == eFlags1.STRAFELEFT || Flags1 == eFlags1.STRAFERIGHT; * client.Player.IsDiving = Flags2 == eFlags2.DIVING ? true : false; * client.Player.IsSwimming = Flags1 == eFlags1.SWIMMING ? true : false; * if (client.Player.IsRiding) * Flags1 = eFlags1.RIDING; * client.Player.IsClimbing = Flags1 == eFlags1.CLIMBING ? true : false; * if (!client.Player.IsAlive) * Flags1 = eFlags1.DEAD;*/ client.Player.IsJumping = ((playerAction & 0x40) != 0); client.Player.IsStrafing = ((playerState & 0xe000) != 0); Zone newZone = WorldMgr.GetZone(currentZoneID); if (newZone == null) { if (client.Player == null) { return; } if (!client.Player.TempProperties.getProperty("isbeingbanned", false)) { if (log.IsErrorEnabled) { log.Error(client.Player.Name + "'s position in unknown zone! => " + currentZoneID); } GamePlayer player = client.Player; player.TempProperties.setProperty("isbeingbanned", true); player.MoveToBind(); } return; // TODO: what should we do? player lost in space } // move to bind if player fell through the floor if (newPlayerZ == 0) { client.Player.MoveTo( (ushort)client.Player.BindRegion, client.Player.BindXpos, client.Player.BindYpos, (ushort)client.Player.BindZpos, (ushort)client.Player.BindHeading ); return; } //int realX = newPlayerX; //int realY = newPlayerY; //int realZ = newPlayerZ; bool zoneChange = newZone != client.Player.LastPositionUpdateZone; if (zoneChange) { //If the region changes -> make sure we don't take any falling damage if (client.Player.LastPositionUpdateZone != null && newZone.ZoneRegion.ID != client.Player.LastPositionUpdateZone.ZoneRegion.ID) { client.Player.MaxLastZ = int.MinValue; } // Update water level and diving flag for the new zone client.Out.SendPlayerPositionAndObjectID(); zoneChange = true; /* * "You have entered Burial Tomb." * "Burial Tomb" * "Current area is adjusted for one level 1 player." * "Current area has a 50% instance bonus." */ string description = newZone.Description; string screenDescription = description; var translation = client.GetTranslation(newZone) as DBLanguageZone; if (translation != null) { if (!Util.IsEmpty(translation.Description)) { description = translation.Description; } if (!Util.IsEmpty(translation.ScreenDescription)) { screenDescription = translation.ScreenDescription; } } client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "PlayerPositionUpdateHandler.Entered", description), eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage(screenDescription, eChatType.CT_ScreenCenterSmaller, eChatLoc.CL_SystemWindow); client.Player.LastPositionUpdateZone = newZone; } int coordsPerSec = 0; int jumpDetect = 0; int timediff = Environment.TickCount - client.Player.LastPositionUpdateTick; int distance = 0; if (timediff > 0) { distance = client.Player.LastPositionUpdatePoint.GetDistanceTo(new Point3D(newPlayerX, newPlayerY, newPlayerZ)); coordsPerSec = distance * 1000 / timediff; if (distance < 100 && client.Player.LastPositionUpdatePoint.Z > 0) { jumpDetect = newPlayerZ - client.Player.LastPositionUpdatePoint.Z; } } client.Player.LastPositionUpdateTick = Environment.TickCount; client.Player.LastPositionUpdatePoint.X = newPlayerX; client.Player.LastPositionUpdatePoint.Y = newPlayerY; client.Player.LastPositionUpdatePoint.Z = newPlayerZ; int tolerance = ServerProperties.Properties.CPS_TOLERANCE; if (client.Player.Steed != null && client.Player.Steed.MaxSpeed > 0) { tolerance += client.Player.Steed.MaxSpeed; } else if (client.Player.MaxSpeed > 0) { tolerance += client.Player.MaxSpeed; } if (client.Player.IsJumping) { coordsPerSec = 0; jumpDetect = 0; client.Player.IsJumping = false; } if (!client.Player.IsAllowedToFly && (coordsPerSec > tolerance || jumpDetect > ServerProperties.Properties.JUMP_TOLERANCE)) { bool isHackDetected = true; if (coordsPerSec > tolerance) { // check to see if CPS time tolerance is exceeded int lastCPSTick = client.Player.TempProperties.getProperty <int>(LASTCPSTICK, 0); if (environmentTick - lastCPSTick > ServerProperties.Properties.CPS_TIME_TOLERANCE) { isHackDetected = false; } } if (isHackDetected) { StringBuilder builder = new StringBuilder(); builder.Append("MOVEHACK_DETECT"); builder.Append(": CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); builder.Append(" CPS:="); builder.Append(coordsPerSec); builder.Append(" JT="); builder.Append(jumpDetect); ChatUtil.SendDebugMessage(client, builder.ToString()); if (client.Account.PrivLevel == 1) { GameServer.Instance.LogCheatAction(builder.ToString()); if (ServerProperties.Properties.ENABLE_MOVEDETECT) { if (ServerProperties.Properties.BAN_HACKERS && false) // banning disabled until this technique is proven accurate { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban MOVEHACK:(CPS:{0}, JT:{1}) on player:{2}", coordsPerSec, jumpDetect, client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); string message = ""; message = "You have been auto kicked and banned due to movement hack detection!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } else { string message = ""; message = "You have been auto kicked due to movement hack detection!"; for (int i = 0; i < 8; i++) { client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_Help, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Player.SaveIntoDatabase(); client.Player.Quit(true); } client.Disconnect(); return; } } } client.Player.TempProperties.setProperty(LASTCPSTICK, environmentTick); } //client.Player.Heading = (ushort)(newHeading & 0xFFF); //patch 0024 expermental if (client.Player.X != newPlayerX || client.Player.Y != newPlayerY) { client.Player.TempProperties.setProperty(LASTMOVEMENTTICK, client.Player.CurrentRegion.Time); } //patch 0024 expermental //client.Player.X = realX; //client.Player.Y = realY; //client.Player.Z = realZ; client.Player.SetCoords(newPlayerX, newPlayerY, newPlayerZ, (ushort)(newHeading & 0xFFF)); //patch 0024 expermental if (zoneChange) { // update client zone information for waterlevel and diving client.Out.SendPlayerPositionAndObjectID(); } // used to predict current position, should be before // any calculation (like fall damage) //client.Player.MovementStartTick = Environment.TickCount; experimental 0024 // Begin ---------- New Area System ----------- if (client.Player.CurrentRegion.Time > client.Player.AreaUpdateTick) // check if update is needed { var oldAreas = client.Player.CurrentAreas; // Because we may be in an instance we need to do the area check from the current region // rather than relying on the zone which is in the skinned region. - Tolakram var newAreas = client.Player.CurrentRegion.GetAreasOfZone(newZone, client.Player); // Check for left areas if (oldAreas != null) { foreach (IArea area in oldAreas) { if (!newAreas.Contains(area)) { area.OnPlayerLeave(client.Player); } } } // Check for entered areas foreach (IArea area in newAreas) { if (oldAreas == null || !oldAreas.Contains(area)) { area.OnPlayerEnter(client.Player); } } // set current areas to new one... client.Player.CurrentAreas = newAreas; client.Player.AreaUpdateTick = client.Player.CurrentRegion.Time + 2000; // update every 2 seconds } // End ---------- New Area System ----------- //client.Player.TargetInView = ((flags & 0x10) != 0); //client.Player.IsDiving = ((playerAction & 0x02) != 0); client.Player.TargetInView = ((playerAction & 0x30) != 0); client.Player.GroundTargetInView = ((playerAction & 0x08) != 0); client.Player.IsTorchLighted = ((playerAction & 0x80) != 0); // patch 0069 player diving is 0x02, but will broadcast to other players as 0x04 // if player has a pet summoned, player action is sent by client as 0x04, but sending to other players this is skipped client.Player.IsDiving = ((playerAction & 0x02) != 0); int state = ((playerState >> 10) & 7); client.Player.IsClimbing = (state == 7); client.Player.IsSwimming = (state == 1); //int status = (data & 0x1FF ^ data) >> 8; //int fly = (flyingflag & 0x1FF ^ flyingflag) >> 8; if (state == 3 && client.Player.TempProperties.getProperty <bool>(GamePlayer.DEBUG_MODE_PROPERTY, false) == false && !client.Player.IsAllowedToFly) //debugFly on, but player not do /debug on (hack) { StringBuilder builder = new StringBuilder(); builder.Append("HACK_FLY"); builder.Append(": CharName="); builder.Append(client.Player.Name); builder.Append(" Account="); builder.Append(client.Account.Name); builder.Append(" IP="); builder.Append(client.TcpEndpointAddress); GameServer.Instance.LogCheatAction(builder.ToString()); { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban flying hack: on player:{0}", client.Player.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); } string message = ""; message = "Client Hack Detected!"; for (int i = 0; i < 6; i++) { client.Out.SendMessage(message, eChatType.CT_System, eChatLoc.CL_SystemWindow); client.Out.SendMessage(message, eChatType.CT_System, eChatLoc.CL_ChatWindow); } client.Out.SendPlayerQuit(true); client.Disconnect(); return; } } lock (client.Player.LastUniqueLocations) { GameLocation[] locations = client.Player.LastUniqueLocations; GameLocation loc = locations[0]; if (loc.X != newPlayerX || loc.Y != newPlayerY || loc.Z != newPlayerZ || loc.RegionID != client.Player.CurrentRegionID) { loc = locations[locations.Length - 1]; Array.Copy(locations, 0, locations, 1, locations.Length - 1); locations[0] = loc; loc.X = newPlayerX; loc.Y = newPlayerY; loc.Z = newPlayerZ; loc.Heading = client.Player.Heading; loc.RegionID = client.Player.CurrentRegionID; } } //FALLING DAMAGE if (GameServer.ServerRules.CanTakeFallDamage(client.Player) && !client.Player.IsSwimming) { try { int maxLastZ = client.Player.MaxLastZ; // Are we on the ground? if ((fallingDMG >> 15) != 0) { int safeFallLevel = client.Player.GetAbilityLevel(Abilities.SafeFall); int fallSpeed = (newPlayerZSpeed * -1) - (100 * safeFallLevel); int fallDivide = 15; int fallPercent = Math.Min(99, (fallSpeed - (501)) / fallDivide); if (fallSpeed > 500) { client.Out.SendMessage(LanguageMgr.GetTranslation(client.Account.Language, "PlayerPositionUpdateHandler.FallingDamage"), eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); client.Out.SendMessage(string.Format("You take {0}% of you max hits in damage.", fallPercent), eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); client.Out.SendMessage("You lose endurance", eChatType.CT_Damaged, eChatLoc.CL_SystemWindow); client.Player.CalcFallDamage(fallPercent); } client.Player.MaxLastZ = client.Player.Z; } else { if (maxLastZ < client.Player.Z || client.Player.IsRiding || newPlayerZSpeed > -150) // is riding, for dragonflys { client.Player.MaxLastZ = client.Player.Z; } } } catch { log.Warn("error when attempting to calculate fall damage"); } } if (client.Player.Steed != null && client.Player.Steed.ObjectState == GameObject.eObjectState.Active) { client.Player.Heading = client.Player.Steed.Heading; newHeading = (ushort)client.Player.Steed.ObjectID; // test patch 0064 //playerState |= 0x1800; } else if ((playerState >> 10) == 4) // patch 0062 fix bug on release preventing players from receiving res sickness { client.Player.IsSitting = true; } /*else if ((playerState & 0x1000) != 0) //player sitting when releasing on death, dead = 0x1400 * { * client.Player.IsSitting = true; * }*/ GSUDPPacketOut outpak = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerPosition)); //patch 0069 test to fix player swim out byte flag byte playerOutAction = 0x00; if (client.Player.IsDiving) { playerOutAction |= 0x04; } if (client.Player.TargetInView) { playerOutAction |= 0x30; } if (client.Player.GroundTargetInView) { playerOutAction |= 0x08; } if (client.Player.IsTorchLighted) { playerOutAction |= 0x80; } //stealth is set here if (client.Player.IsStealthed) { playerState |= 0x0200; } outpak.WriteFloatLowEndian(newPlayerX); outpak.WriteFloatLowEndian(newPlayerY); outpak.WriteFloatLowEndian(newPlayerZ); outpak.WriteFloatLowEndian(newPlayerSpeed); outpak.WriteFloatLowEndian(newPlayerZSpeed); outpak.WriteShort(sessionID); outpak.WriteShort(currentZoneID); outpak.WriteShort(playerState); outpak.WriteShort(0); // fall damage flag, dont need to send it outpak.WriteShort(newHeading); outpak.WriteByte(playerOutAction); outpak.WriteByte((byte)(client.Player.RPFlag ? 1 : 0)); outpak.WriteByte(0); outpak.WriteByte((byte)(client.Player.HealthPercent + (client.Player.AttackState ? 0x80 : 0))); outpak.WriteByte(client.Player.ManaPercent); outpak.WriteByte(client.Player.EndurancePercent); //Now copy the whole content of the packet //outpak1119.Write(pak1119, 0, 36); outpak.WritePacketLength(); foreach (GamePlayer player in client.Player.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if (player == null) { continue; } //No position updates for ourselves if (player == client.Player) { // Update Player Cache (Client sending Packet is admitting he's already having it) player.Client.GameObjectUpdateArray[new Tuple <ushort, ushort>(client.Player.CurrentRegionID, (ushort)client.Player.ObjectID)] = GameTimer.GetTickCount(); continue; } //no position updates in different houses if ((client.Player.InHouse || player.InHouse) && player.CurrentHouse != client.Player.CurrentHouse) { continue; } /* patch 0068 no minotaur logic * if (client.Player.MinotaurRelic != null) * { * MinotaurRelic relic = client.Player.MinotaurRelic; * if (!relic.Playerlist.Contains(player) && player != client.Player) * { * relic.Playerlist.Add(player); * player.Out.SendMinotaurRelicWindow(client.Player, client.Player.MinotaurRelic.Effect, true); * } * }*/ if (!client.Player.IsStealthed || player.CanDetect(client.Player)) { // Update Player Cache // test patch remove players in cache 0065 //player.Client.GameObjectUpdateArray[new Tuple<ushort, ushort>(client.Player.CurrentRegionID, (ushort)client.Player.ObjectID)] = GameTimer.GetTickCount(); player.Out.SendUDPRaw(outpak); } else { player.Out.SendObjectDelete(client.Player); //remove the stealthed player from view } } //handle closing of windows //trade window if (client.Player.TradeWindow != null) { if (client.Player.TradeWindow.Partner != null) { if (!client.Player.IsWithinRadius(client.Player.TradeWindow.Partner, WorldMgr.GIVE_ITEM_DISTANCE)) { client.Player.TradeWindow.CloseTrade(); } } } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null || client.Player == null) { return; } if (client.Player.ObjectState != GameObject.eObjectState.Active) { return; } ushort sessionId = packet.ReadShort(); // session ID if (client.SessionID != sessionId) { // GameServer.BanAccount(client, 120, "Hack sessionId", string.Format("Wrong sessionId:0x{0} in 0xBA packet (SessionID:{1})", sessionId, client.SessionID)); return; // client hack } ushort head = packet.ReadShort(); client.Player.Heading = (ushort)(head & 0xFFF); packet.Skip(1); // unknown int flags = packet.ReadByte(); // client.Player.PetInView = ((flags & 0x04) != 0); // TODO client.Player.GroundTargetInView = ((flags & 0x08) != 0); client.Player.TargetInView = ((flags & 0x10) != 0); byte[] con = packet.ToArray(); con[0] = (byte)(client.SessionID >> 8); con[1] = (byte)(client.SessionID & 0xff); if (!client.Player.IsAlive) { con[9] = 5; // set dead state } else if (client.Player.Steed != null && client.Player.Steed.ObjectState == GameObject.eObjectState.Active) { client.Player.Heading = client.Player.Steed.Heading; con[9] = 6; // Set ride state con[7] = (byte)(client.Player.Steed.RiderSlot(client.Player)); // there rider slot this player con[2] = (byte)(client.Player.Steed.ObjectID >> 8); //heading = steed ID con[3] = (byte)(client.Player.Steed.ObjectID & 0xFF); } con[5] &= 0xC0; //11 00 00 00 = 0x80(Torch) + 0x40(Unknown), all other in view check's not need send anyone if (client.Player.IsWireframe) { con[5] |= 0x01; } //stealth is set here if (client.Player.IsStealthed) { con[5] |= 0x02; } con[8] = (byte)((con[8] & 0x80) | client.Player.HealthPercent); GSUDPPacketOut outpak = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerHeading)); //Now copy the whole content of the packet outpak.Write(con, 0, /*con.Length*/ 10); outpak.WritePacketLength(); GSUDPPacketOut outpak190 = null; // byte[] outp = outpak.GetBuffer(); // outpak = null; foreach (GamePlayer player in client.Player.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if (player != null && player != client.Player) { if (player.Client.Version >= GameClient.eClientVersion.Version190) { if (outpak190 == null) { outpak190 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerHeading)); byte[] con190 = (byte[])con.Clone(); //Now copy the whole content of the packet outpak190.Write(con190, 0, /*con190.Lenght*/ 10); outpak190.WriteByte(client.Player.ManaPercent); outpak190.WriteByte(client.Player.EndurancePercent); outpak190.WritePacketLength(); // byte[] outp190 = outpak190.GetBuffer(); // outpak190 = null;// ? } player.Out.SendUDPRaw(outpak190); } else { player.Out.SendUDPRaw(outpak); } } } }
public void HandlePacket(GameClient client, GSPacketIn packet) { string accountName = packet.ReadString(24); log.Debug("CharacterCreateRequestHandler for account " + accountName + " using version " + client.Version); if (!accountName.StartsWith(client.Account.Name))// TODO more correctly check, client send accountName as account-S, -N, -H (if it not fit in 20, then only account) { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = String.Format("Autoban wrong Account '{0}'", GameServer.Database.Escape(accountName)); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); } client.Disconnect(); return; } if (client.Version >= GameClient.eClientVersion.Version1104) { packet.ReadIntLowEndian(); //unk - probably indicates customize or create } int charsCount = client.Version < GameClient.eClientVersion.Version173 ? 8 : 10; for (int i = 0; i < charsCount; i++) { string charName = packet.ReadString(24); //log.DebugFormat("Character[{0}] = {1}", i, charName); if (charName.Length == 0) { // 1.104+ if character is not in list but is in DB then delete the character if (client.Version >= GameClient.eClientVersion.Version1104) { CheckForDeletedCharacter(accountName, client, i); } //If the charname is empty, skip the other bytes packet.Skip(160); if (client.Version >= GameClient.eClientVersion.Version199) { // skip 4 bytes added in 1.99 packet.Skip(4); } } else { // Graveen: changed the following to allow GMs to have special chars in their names (_,-, etc..) Regex nameCheck = new Regex("^[A-Z][a-zA-Z]"); if (charName.Length < 3 || !nameCheck.IsMatch(charName)) { if (client.Account.PrivLevel == 1) { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = String.Format("Autoban bad CharName '{0}'", GameServer.Database.Escape(charName)); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); } client.Disconnect(); return; } } String select = String.Format("Name = '{0}'", GameServer.Database.Escape(charName)); DOLCharacters character = GameServer.Database.SelectObject<DOLCharacters>(select); if (character != null) { if (character.AccountName != client.Account.Name) { if (Properties.BAN_HACKERS == true) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = String.Format("Autoban CharName '{0}' on wrong Account '{1}'", GameServer.Database.Escape(charName), GameServer.Database.Escape(client.Account.Name)); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(string.Format(b.Reason + ". Client Account: {0}, DB Account: {1}", client.Account.Name, character.AccountName)); } client.Disconnect(); return; } byte customizationMode = (byte)packet.ReadByte(); // log.DebugFormat("CustomizationMode = {0} for charName {1}", customizationMode, charName); // check for update to existing character CheckCharacterForUpdates(client, packet, character, charName, customizationMode); } else { // create new character and return CreateCharacter(client, packet, charName, i); } } } }
private void CreateCharacter(GameClient client, GSPacketIn packet, string charName, int accountSlot) { Account account = client.Account; DOLCharacters ch = new DOLCharacters(); ch.AccountName = account.Name; ch.Name = charName; if (packet.ReadByte() == 0x01) { ch.EyeSize = (byte)packet.ReadByte(); ch.LipSize = (byte)packet.ReadByte(); ch.EyeColor = (byte)packet.ReadByte(); ch.HairColor = (byte)packet.ReadByte(); ch.FaceType = (byte)packet.ReadByte(); ch.HairStyle = (byte)packet.ReadByte(); packet.Skip(3); ch.MoodType = (byte)packet.ReadByte(); ch.CustomisationStep = 2; // disable config button packet.Skip(13); log.Debug("Disable Config Button"); } else { packet.Skip(23); } packet.Skip(24); //Location String ch.LastName = ""; ch.GuildID = ""; packet.Skip(24); //Skip class name packet.Skip(24); //Skip race name ch.Level = packet.ReadByte(); //not safe! ch.Level = 1; ch.Class = packet.ReadByte(); if (ServerProperties.Properties.START_AS_BASE_CLASS) { ch.Class = RevertClass(ch); } ch.Realm = packet.ReadByte(); if (log.IsDebugEnabled) log.Debug("Creation " + client.Version + " character, class:" + ch.Class + ", realm:" + ch.Realm); // Is class disabled ? int occurences = 0; List<string> disabled_classes = Properties.DISABLED_CLASSES.SplitCSV(true); occurences = (from j in disabled_classes where j == ch.Class.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { log.Debug("Client " + client.Account.Name + " tried to create a disabled classe: " + (eCharacterClass)ch.Class); client.Out.SendCharacterOverview((eRealm)ch.Realm); return; } if (client.Version >= GameClient.eClientVersion.Version193) { ValidateCharacter.init_post193_tables(); } else { ValidateCharacter.init_pre193_tables(); } if (!Enum.IsDefined(typeof(eCharacterClass), (eCharacterClass)ch.Class)) { log.Error(client.Account.Name + " tried to create a character with wrong class ID: " + ch.Class + ", realm:" + ch.Realm); if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = string.Format("Autoban character create class: id:{0} realm:{1} name:{2} account:{3}", ch.Class, ch.Realm, ch.Name, account.Name); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); client.Disconnect(); } return; } ch.AccountSlot = accountSlot + ch.Realm * 100; //The following byte contains //1bit=start location ... in ShroudedIsles you can choose ... //1bit=first race bit //1bit=unknown //1bit=gender (0=male, 1=female) //4bit=race byte startRaceGender = (byte)packet.ReadByte(); ch.Race = (startRaceGender & 0x0F) + ((startRaceGender & 0x40) >> 2); List<string> disabled_races = new List<string>(Properties.DISABLED_RACES.SplitCSV(true)); occurences = (from j in disabled_races where j == ch.Race.ToString() select j).Count(); if (occurences > 0 && (ePrivLevel)client.Account.PrivLevel == ePrivLevel.Player) { log.Debug("Client " + client.Account.Name + " tried to create a disabled race: " + (eRace)ch.Race); client.Out.SendCharacterOverview((eRealm)ch.Realm); return; } ch.Gender = ((startRaceGender >> 4) & 0x01); bool siStartLocation = ((startRaceGender >> 7) != 0); ch.CreationModel = packet.ReadShortLowEndian(); ch.CurrentModel = ch.CreationModel; ch.Region = packet.ReadByte(); packet.Skip(1); //TODO second byte of region unused currently packet.Skip(4); //TODO Unknown Int / last used? ch.Strength = (byte)packet.ReadByte(); ch.Dexterity = (byte)packet.ReadByte(); ch.Constitution = (byte)packet.ReadByte(); ch.Quickness = (byte)packet.ReadByte(); ch.Intelligence = (byte)packet.ReadByte(); ch.Piety = (byte)packet.ReadByte(); ch.Empathy = (byte)packet.ReadByte(); ch.Charisma = (byte)packet.ReadByte(); packet.Skip(44); //TODO equipment if (client.Version >= GameClient.eClientVersion.Version199) { // skip 4 bytes added in 1.99 packet.Skip(4); } // log.DebugFormat("STR {0}, CON {1}, DEX {2}, QUI {3}, INT {4}, PIE {5}, EMP {6}, CHA {7}", ch.Strength, ch.Constitution, ch.Dexterity, ch.Quickness, ch.Intelligence, ch.Piety, ch.Empathy, ch.Charisma); // check if client tried to create invalid char if (!ValidateCharacter.IsCharacterValid(ch)) { if (log.IsWarnEnabled) { log.Warn(ch.AccountName + " tried to create invalid character:" + "\nchar name=" + ch.Name + ", gender=" + ch.Gender + ", race=" + ch.Race + ", realm=" + ch.Realm + ", class=" + ch.Class + ", region=" + ch.Region + "\nstr=" + ch.Strength + ", con=" + ch.Constitution + ", dex=" + ch.Dexterity + ", qui=" + ch.Quickness + ", int=" + ch.Intelligence + ", pie=" + ch.Piety + ", emp=" + ch.Empathy + ", chr=" + ch.Charisma); } // This is not live like but unfortunately we are missing code / packet support to stay on character create screen if something is invalid client.Out.SendCharacterOverview((eRealm)ch.Realm); return; } ch.CreationDate = DateTime.Now; ch.Endurance = 100; ch.MaxEndurance = 100; ch.Concentration = 100; ch.MaxSpeed = GamePlayer.PLAYER_BASE_SPEED; #region Starting Locations //if the server property for disable tutorial is set, we load in the classic starting locations if (ch.Region == 27 && ServerProperties.Properties.DISABLE_TUTORIAL) { switch (ch.Realm) { case 1: ch.Region = 1; break; case 2: ch.Region = 100; break; case 3: ch.Region = 200; break; } } ch.Xpos = 505603; ch.Ypos = 494709; ch.Zpos = 2463; ch.Direction = 5947; if (ch.Region == 51 && ch.Realm == 1)//Albion ShroudedIsles start point (I hope) { ch.Xpos = 526252; ch.Ypos = 542415; ch.Zpos = 3165; ch.Direction = 5286; } if (ch.Region != 51 && ch.Realm == 1)//Albion start point (Church outside Camelot/humberton) { ch.Xpos = 505603; ch.Ypos = 494709; ch.Zpos = 2463; ch.Direction = 5947; //ch.Region = 1; //DOLConsole.WriteLine(String.Format("Character ClassName:"+ch.ClassName+" created!")); //DOLConsole.WriteLine(String.Format("Character RaceName:"+ch.RaceName+" created!")); } if (ch.Region == 151 && ch.Realm == 2)//Midgard ShroudedIsles start point { ch.Xpos = 293720; ch.Ypos = 356408; ch.Zpos = 3488; ch.Direction = 6670; } if (ch.Region != 151 && ch.Realm == 2)//Midgard start point (Fort Atla) { ch.Xpos = 749103; ch.Ypos = 815835; ch.Zpos = 4408; ch.Direction = 7915; //ch.Region = 100; //DOLConsole.WriteLine(String.Format("Character ClassName:"+ch.ClassName+" created!")); //DOLConsole.WriteLine(String.Format("Character RaceName:"+ch.RaceName+" created!")); } if (ch.Region == 181 && ch.Realm == 3)//Hibernia ShroudedIsles start point { ch.Xpos = 426483; ch.Ypos = 440626; ch.Zpos = 5952; ch.Direction = 2403; } if (ch.Region != 181 && ch.Realm == 3)//Hibernia start point (Mag Mel) { ch.Xpos = 345900; ch.Ypos = 490867; ch.Zpos = 5200; ch.Direction = 4826; //ch.Region = 200; //DOLConsole.WriteLine(String.Format("Character ClassName:"+ch.ClassName+" created!")); //DOLConsole.WriteLine(String.Format("Character RaceName:"+ch.RaceName+" created!")); } // chars are bound on creation ch.BindRegion = ch.Region; ch.BindHeading = ch.Direction; ch.BindXpos = ch.Xpos; ch.BindYpos = ch.Ypos; ch.BindZpos = ch.Zpos; #endregion Starting Locations #region starting guilds if (account.PrivLevel == 1 && Properties.STARTING_GUILD) { switch (ch.Realm) { case 1: switch (ServerProperties.Properties.SERV_LANGUAGE) { case "EN": ch.GuildID = GuildMgr.GuildNameToGuildID("Clan Cotswold"); break; case "DE": ch.GuildID = GuildMgr.GuildNameToGuildID("Klan Cotswold"); break; default: ch.GuildID = GuildMgr.GuildNameToGuildID("Clan Cotswold"); break; } break; case 2: switch (ServerProperties.Properties.SERV_LANGUAGE) { case "EN": ch.GuildID = GuildMgr.GuildNameToGuildID("Mularn Protectors"); break; case "DE": ch.GuildID = GuildMgr.GuildNameToGuildID("Beschützer von Mularn"); break; default: ch.GuildID = GuildMgr.GuildNameToGuildID("Mularn Protectors"); break; } break; case 3: switch (ServerProperties.Properties.SERV_LANGUAGE) { case "EN": ch.GuildID = GuildMgr.GuildNameToGuildID("Tir na Nog Adventurers"); break; case "DE": ch.GuildID = GuildMgr.GuildNameToGuildID("Tir na Nog-Abenteurer"); break; default: ch.GuildID = GuildMgr.GuildNameToGuildID("Tir na Nog Adventurers"); break; } break; default: break; } if (ch.GuildID != "") ch.GuildRank = 8; } #endregion starting guilds if (Properties.STARTING_BPS > 0) ch.BountyPoints = Properties.STARTING_BPS; if (Properties.STARTING_MONEY > 0) { long value = Properties.STARTING_MONEY; ch.Copper = Money.GetCopper(value); ch.Silver = Money.GetSilver(value); ch.Gold = Money.GetGold(value); ch.Platinum = Money.GetPlatinum(value); } if (Properties.STARTING_REALM_LEVEL > 0) { int realmLevel = Properties.STARTING_REALM_LEVEL; long rpamount = 0; if (realmLevel < GamePlayer.REALMPOINTS_FOR_LEVEL.Length) rpamount = GamePlayer.REALMPOINTS_FOR_LEVEL[realmLevel]; // thanks to Linulo from http://daoc.foren.4players.de/viewtopic.php?t=40839&postdays=0&postorder=asc&start=0 if (rpamount == 0) rpamount = (long)(25.0 / 3.0 * (realmLevel * realmLevel * realmLevel) - 25.0 / 2.0 * (realmLevel * realmLevel) + 25.0 / 6.0 * realmLevel); ch.RealmPoints = rpamount; ch.RealmLevel = realmLevel; ch.RealmSpecialtyPoints = realmLevel; } ch.RespecAmountRealmSkill += 2; SetBasicCraftingForNewCharacter(ch); //Save the character in the database GameServer.Database.AddObject(ch); //Fire the character creation event GameEventMgr.Notify(DatabaseEvent.CharacterCreated, null, new CharacterEventArgs(ch, client)); //add equipment StartupEquipment.AddEquipment(ch); //write changes GameServer.Database.SaveObject(ch); // Log creation AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.CharacterCreate, "", charName); client.Account.Characters = null; if (log.IsInfoEnabled) log.Info(String.Format("Character {0} created!", charName)); GameServer.Database.FillObjectRelations(client.Account); client.Out.SendCharacterOverview((eRealm)ch.Realm); return; }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null || client.Player == null) { return; } if (client.Player.ObjectState != GameObject.eObjectState.Active) { return; } ushort sessionId = packet.ReadShort(); if (client.SessionID != sessionId) { // GameServer.BanAccount(client, 120, "Hack sessionId", string.Format("Wrong sessionId:0x{0} in 0xBA packet (SessionID:{1})", sessionId, client.SessionID)); return; // client hack } client.Player.Heading = packet.ReadShort(); packet.Skip(1); // unknown int flags = packet.ReadByte(); // client.Player.PetInView = ((flags & 0x04) != 0); // TODO client.Player.GroundTargetInView = ((flags & 0x08) != 0); client.Player.TargetInView = ((flags & 0x10) != 0); packet.Skip(1); byte ridingFlag = (byte)packet.ReadByte(); flags = 0; // reset flags, only some sent back out if (client.Player.IsWireframe) { flags |= 0x01; } if (client.Player.IsStealthed) { flags |= 0x02; } if (client.Player.IsDiving) { flags |= 0x04; } if (client.Player.IsTorchLighted) { flags |= 0x80; } byte steedSlot = (byte)client.Player.SteedSeatPosition; GSUDPPacketOut outpak = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerHeading)); outpak.WriteShort((ushort)client.SessionID); outpak.WriteShort(client.Player.Heading); outpak.WriteByte(steedSlot); outpak.WriteByte((byte)flags); outpak.WriteByte(0); outpak.WriteByte(ridingFlag); outpak.WriteByte(client.Player.HealthPercent); outpak.WriteByte(client.Player.ManaPercent); outpak.WriteByte(client.Player.EndurancePercent); outpak.WriteByte(0); // null term? outpak.WritePacketLength(); foreach (GamePlayer player in client.Player.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if (player != null && player != client.Player) { player.Out.SendUDPRaw(outpak); } } }
public void HandlePacket(GameClient client, GSPacketIn packet) { int packetVersion; switch (client.Version) { case GameClient.eClientVersion.Version168: case GameClient.eClientVersion.Version169: case GameClient.eClientVersion.Version170: case GameClient.eClientVersion.Version171: case GameClient.eClientVersion.Version172: case GameClient.eClientVersion.Version173: packetVersion = 168; break; default: packetVersion = 174; break; } packet.Skip(4); //Skip the first 4 bytes if (packetVersion == 174) { packet.Skip(1); } string charName = packet.ReadString(28); //TODO Character handling if (charName.Equals("noname")) { client.Out.SendSessionID(); } else { // SH: Also load the player if client player is NOT null but their charnames differ!!! // only load player when on charscreen and player is not loaded yet // packet is sent on every region change (and twice after "play" was pressed) if ( ( (client.Player == null && client.Account.Characters != null) || (client.Player != null && client.Player.Name.ToLower() != charName.ToLower()) ) && client.ClientState == GameClient.eClientState.CharScreen) { bool charFound = false; for (int i = 0; i < client.Account.Characters.Length; i++) { if (client.Account.Characters[i] != null && client.Account.Characters[i].Name == charName) { charFound = true; // Notify Character Selection Event, last hope to fix any bad data before Loading. GameEventMgr.Notify(DatabaseEvent.CharacterSelected, new CharacterEventArgs(client.Account.Characters[i], client)); client.LoadPlayer(i); break; } } if (charFound == false) { client.Player = null; client.ActiveCharIndex = -1; } else { // Log character play AuditMgr.AddAuditEntry(client, AuditType.Character, AuditSubtype.CharacterLogin, "", charName); } } client.Out.SendSessionID(); } }
private int CheckCharacterForUpdates(GameClient client, GSPacketIn packet, DOLCharacters character, string charName, byte customizationMode) { int newModel = character.CurrentModel; if (customizationMode == 1 || customizationMode == 2 || customizationMode == 3) { bool flagChangedStats = false; character.EyeSize = (byte)packet.ReadByte(); character.LipSize = (byte)packet.ReadByte(); character.EyeColor = (byte)packet.ReadByte(); character.HairColor = (byte)packet.ReadByte(); character.FaceType = (byte)packet.ReadByte(); character.HairStyle = (byte)packet.ReadByte(); packet.Skip(3); character.MoodType = (byte)packet.ReadByte(); packet.Skip(89); // Skip location string, race string, classe string, level ,class ,realm and startRaceGender newModel = packet.ReadShortLowEndian(); //read new model if (customizationMode != 3 && client.Version >= GameClient.eClientVersion.Version189) { packet.Skip(6); // Region ID + character Internal ID int[] stats = new int[8]; stats[0] = (byte)packet.ReadByte(); // Strength stats[2] = (byte)packet.ReadByte(); // Dexterity stats[1] = (byte)packet.ReadByte(); // Constitution stats[3] = (byte)packet.ReadByte(); // Quickness stats[4] = (byte)packet.ReadByte(); // Intelligence stats[5] = (byte)packet.ReadByte(); // Piety stats[6] = (byte)packet.ReadByte(); // Empathy stats[7] = (byte)packet.ReadByte(); // Charisma packet.Skip(43);// armor models/armor color/weapon models/active weapon slots/siZone if (client.Version >= GameClient.eClientVersion.Version199) { // skip 4 bytes added in 1.99 packet.Skip(4); } // what is this? byte newConstitution = (byte)packet.ReadByte(); if (newConstitution > 0 && newConstitution < 255) // added 255 check, still not sure why this is here - tolakram stats[1] = newConstitution; flagChangedStats |= stats[0] != character.Strength; flagChangedStats |= stats[1] != character.Constitution; flagChangedStats |= stats[2] != character.Dexterity; flagChangedStats |= stats[3] != character.Quickness; flagChangedStats |= stats[4] != character.Intelligence; flagChangedStats |= stats[5] != character.Piety; flagChangedStats |= stats[6] != character.Empathy; flagChangedStats |= stats[7] != character.Charisma; // // !! Stat changes disabled by Tolakram until someone figures out why this can create invalid stats !! // flagChangedStats = false; if (flagChangedStats) { ICharacterClass charClass = ScriptMgr.FindCharacterClass(character.Class); if (charClass != null) { int points = 0; int[] leveledStats = new int[8]; int[] raceStats = new int[8]; bool valid = true; for (int j = 0; j < 8; j++) { eStat stat = (eStat)ValidateCharacter.eStatIndex[j]; raceStats[j] = ValidateCharacter.STARTING_STATS[character.Race][j]; for (int level = character.Level; level > 5; level--) { if (charClass.PrimaryStat != eStat.UNDEFINED && charClass.PrimaryStat == stat) { leveledStats[j]++; } if (charClass.SecondaryStat != eStat.UNDEFINED && charClass.SecondaryStat == stat) { if ((level - 6) % 2 == 0) leveledStats[j]++; } if (charClass.TertiaryStat != eStat.UNDEFINED && charClass.TertiaryStat == stat) { if ((level - 6) % 3 == 0) leveledStats[j]++; } } int result = stats[j] - leveledStats[j] - raceStats[j]; bool validBeginStat = result >= 0; int pointsUsed = result; string statCategory = ""; if (charClass.PrimaryStat != eStat.UNDEFINED && charClass.PrimaryStat == stat) statCategory = "1)"; if (charClass.SecondaryStat != eStat.UNDEFINED && charClass.SecondaryStat == stat) statCategory = "2)"; if (charClass.TertiaryStat != eStat.UNDEFINED && charClass.TertiaryStat == stat) statCategory = "3)"; pointsUsed += Math.Max(0, result - 10); //two points used pointsUsed += Math.Max(0, result - 15); //three points used log.Info(string.Format("{0,-2} {1,-3}:{2, 3} {3,3} {4,3} {5,3} {6,2} {7} {8}", statCategory, (stat == eStat.STR) ? "STR" : stat.ToString(), stats[j], leveledStats[j], stats[j] - leveledStats[j], raceStats[j], result, pointsUsed, (validBeginStat) ? "" : "Not Valid")); points += pointsUsed; if (!validBeginStat) { valid = false; if (client.Account.PrivLevel == 1) { if (ServerProperties.Properties.BAN_HACKERS) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = String.Format("Autoban Hack char update : Wrong {0} point:{1}", (stat == eStat.STR) ? "STR" : stat.ToString(), result); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); } client.Disconnect(); return 1; } } } if (valid) { character.Strength = (byte)stats[0]; character.Constitution = (byte)stats[1]; character.Dexterity = (byte)stats[2]; character.Quickness = (byte)stats[3]; character.Intelligence = (byte)stats[4]; character.Piety = (byte)stats[5]; character.Empathy = (byte)stats[6]; character.Charisma = (byte)stats[7]; DOLCharacters[] chars = client.Account.Characters; for (int z = 0; z < chars.Length; z++) { if (chars[z].Name != character.Name) continue; //Log.Error(string.Format("found activePlayer:[{0}] {1} {2}", client.ActiveCharIndex, client.Player.Name, character.Name)); if (log.IsInfoEnabled) log.Info(String.Format("Character {0} updated in cache!\n", charName)); if (client.Player != null) { client.Player.DBCharacter.Strength = (byte)stats[0]; client.Player.DBCharacter.Constitution = (byte)stats[1]; client.Player.DBCharacter.Dexterity = (byte)stats[2]; client.Player.DBCharacter.Quickness = (byte)stats[3]; client.Player.DBCharacter.Intelligence = (byte)stats[4]; client.Player.DBCharacter.Piety = (byte)stats[5]; client.Player.DBCharacter.Empathy = (byte)stats[6]; client.Player.DBCharacter.Charisma = (byte)stats[7]; } client.Account.Characters[z].Strength = (byte)stats[0]; client.Account.Characters[z].Constitution = (byte)stats[1]; client.Account.Characters[z].Dexterity = (byte)stats[2]; client.Account.Characters[z].Quickness = (byte)stats[3]; client.Account.Characters[z].Intelligence = (byte)stats[4]; client.Account.Characters[z].Piety = (byte)stats[5]; client.Account.Characters[z].Empathy = (byte)stats[6]; client.Account.Characters[z].Charisma = (byte)stats[7]; } } } else { if (log.IsErrorEnabled) log.Error("No CharacterClass with ID " + character.Class + " found"); } } } else { packet.Skip(58); // skip all other things if (client.Version >= GameClient.eClientVersion.Version199) { // skip 4 bytes added in 1.99 packet.Skip(4); } } if (customizationMode == 2) // change player customization { if (client.Account.PrivLevel == 1 && ((newModel >> 11) & 3) == 0) // Player size must be > 0 (from 1 to 3) { DBBannedAccount b = new DBBannedAccount(); b.Author = "SERVER"; b.Ip = client.TcpEndpointAddress; b.Account = client.Account.Name; b.DateBan = DateTime.Now; b.Type = "B"; b.Reason = String.Format("Autoban Hack char update : zero character size in model:{0}", newModel); GameServer.Database.AddObject(b); GameServer.Database.SaveObject(b); GameServer.Instance.LogCheatAction(b.Reason + ". Account: " + b.Account); client.Disconnect(); return 1; } if ((ushort)newModel != character.CreationModel) { character.CurrentModel = newModel; } character.CustomisationStep = 2; // disable config button GameServer.Database.SaveObject(character); if (log.IsInfoEnabled) log.Info(String.Format("Character {0} face proprieties configured by account {1}!\n", charName, client.Account.Name)); } else if (customizationMode == 3) //auto config -- seems someone thinks this is not possible? { character.CustomisationStep = 3; // enable config button to player GameServer.Database.SaveObject(character); //if (log.IsInfoEnabled) // log.Info(String.Format("Character {0} face proprieties auto updated!\n", charName)); } else if (customizationMode == 1 && flagChangedStats) //changed stat only for 1.89+ { GameServer.Database.SaveObject(character); if (log.IsInfoEnabled) log.Info(String.Format("Character {0} stat updated!\n", charName)); } } return 1; }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client.Player == null) return; string filter = packet.ReadString(64); int slot = (int)packet.ReadInt(); int skill = (int)packet.ReadInt(); int resist = (int)packet.ReadInt(); int bonus = (int)packet.ReadInt(); int hp = (int)packet.ReadInt(); int power = (int)packet.ReadInt(); int proc = (int)packet.ReadInt(); int qtyMin = (int)packet.ReadInt(); int qtyMax = (int)packet.ReadInt(); int levelMin = (int)packet.ReadInt(); int levelMax = (int)packet.ReadInt(); int priceMin = (int)packet.ReadInt(); int priceMax = (int)packet.ReadInt(); int visual = (int)packet.ReadInt(); byte page = (byte)packet.ReadByte(); byte unk1 = (byte)packet.ReadByte(); short unk2 = (short)packet.ReadShort(); if(client.Version >= GameClient.eClientVersion.Version198) { // Dunnerholl 2009-07-28 Version 1.98 introduced new options to Market search. 12 Bytes were added, but only 7 are in usage so far in my findings. // update this, when packets change and keep in mind, that this code reflects only the 1.98 changes byte armorType = page; // page is now used for the armorType (still has to be logged, i just checked that 2 means leather, 0 = standard byte damageType = (byte)packet.ReadByte(); // 1=crush, 2=slash, 3=thrust // 3 bytes unused packet.Skip(3); byte playerCrafted = (byte)packet.ReadByte(); // 1 = show only Player crafted, 0 = all // 3 bytes unused packet.Skip(3); page = (byte)packet.ReadByte(); // page is now sent here byte unknown = (byte)packet.ReadByte(); // always been 0xE5, if u page it is 0x4B, tested on alb only byte unknown2 = (byte)packet.ReadByte(); //always been 0x12, if u page it is 0x7C, tested on alb only byte unknown3 = (byte)packet.ReadByte(); //always been 0x00, if u page it is 0x1B, tested on alb only } int requestedPage = (int)page; int firstSlot = 0 + (requestedPage * 20); int lastSlot = 19 + (requestedPage * 20); StringBuilder sql = new StringBuilder(); sql.Append("SlotPosition >= 1500 AND OwnerLot != 0 "); if (filter != null && filter != "") sql.Append(" AND Name LIKE '%" + filter + "%'"); #region Slot if (slot != -1) { switch (slot) { case 0: sql.Append(" AND Item_Type = '22'"); break; case 1: sql.Append(" AND Item_Type = '23'"); break; case 2: sql.Append(" AND Item_Type = '21'"); break; case 3: sql.Append(" AND Item_Type = '28'"); break; case 4: sql.Append(" AND Item_Type = '27'"); break; case 5: sql.Append(" AND Item_Type = '25'"); break; case 6: sql.Append(" AND Item_Type IN (35, 36)"); break; case 7: sql.Append(" AND Item_Type IN (33, 34)"); break; case 8: sql.Append(" AND Item_Type = '32'"); break; case 9: sql.Append(" AND Item_Type = '29'"); break; case 10: sql.Append(" AND Item_Type = '26'"); break; case 11: sql.Append(" AND Item_Type = '24'"); break; case 12: sql.Append(" AND Item_Type IN (10, 11)"); break; case 13: sql.Append(" AND Object_Type = '42'"); break; case 14: sql.Append(" AND Item_Type = '12'"); break; case 15: sql.Append(" AND Item_Type = '13'"); break; case 16: sql.Append(" AND Item_Type = '11'"); break; case 17: sql.Append(" AND Object_Type = '45'"); break; case 18: sql.Append(" AND (Item_Type = '0' OR Object_Type = '0')"); break; } } #endregion #region Bonus if (bonus > 0) sql.Append(" AND (Bonus >= '" + bonus + "')"); #endregion #region Price if (priceMax > 0 && priceMin < priceMax) sql.Append(" AND (SellPrice >= '" + priceMin + "' AND SellPrice <= '" + priceMax + "')"); #endregion #region Level if (levelMax > 0 && levelMin < levelMax) sql.Append(" AND (Level >= '" + levelMin + "' AND Level <= '" + levelMax + "')"); #endregion #region Visual Effect if (visual > 0) sql.Append(" AND (Effect > '0')"); #endregion #region Skill if (skill > 0) sql.Append(" AND (Bonus1Type = '" + skill + "' OR " + "Bonus2Type = '" + skill + "' OR " + "Bonus3Type = '" + skill + "' OR " + "Bonus4Type = '" + skill + "' OR " + "Bonus5Type = '" + skill + "' OR " + "Bonus6Type = '" + skill + "' OR " + "Bonus7Type = '" + skill + "' OR " + "Bonus8Type = '" + skill + "' OR " + "Bonus9Type = '" + skill + "' OR " + "Bonus10Type = '" + skill + "' OR " + "ExtraBonusType = '" + skill + "')"); #endregion #region Resist if(resist > 0) sql.Append(" AND (Bonus1Type = '" + resist + "' OR " + "Bonus2Type = '" + resist + "' OR " + "Bonus3Type = '" + resist + "' OR " + "Bonus4Type = '" + resist + "' OR " + "Bonus5Type = '" + resist + "' OR " + "Bonus6Type = '" + resist + "' OR " + "Bonus7Type = '" + resist + "' OR " + "Bonus8Type = '" + resist + "' OR " + "Bonus9Type = '" + resist + "' OR " + "Bonus10Type = '" + resist + "' OR " + "ExtraBonusType = '" + resist + "')"); #endregion #region Health if(hp > 0) sql.Append(" AND (Bonus1Type = '" + eProperty.MaxHealth + "' AND Bonus1 >= '" + hp + "' OR " + "Bonus2Type = '" + eProperty.MaxHealth + "' AND Bonus2 >= '" + hp + "' OR " + "Bonus3Type = '" + eProperty.MaxHealth + "' AND Bonus3 >= '" + hp + "' OR " + "Bonus4Type = '" + eProperty.MaxHealth + "' AND Bonus4 >= '" + hp + "' OR " + "Bonus5Type = '" + eProperty.MaxHealth + "' AND Bonus5 >= '" + hp + "' OR " + "Bonus6Type = '" + eProperty.MaxHealth + "' AND Bonus6 >= '" + hp + "' OR " + "Bonus7Type = '" + eProperty.MaxHealth + "' AND Bonus7 >= '" + hp + "' OR " + "Bonus8Type = '" + eProperty.MaxHealth + "' AND Bonus8 >= '" + hp + "' OR " + "Bonus9Type = '" + eProperty.MaxHealth + "' AND Bonus9 >= '" + hp + "' OR " + "Bonus10Type = '" + eProperty.MaxHealth + "' AND Bonus10 >= '" + hp + "' OR " + "ExtraBonusType = '" + eProperty.MaxHealth + "' AND ExtraBonus >= '" + hp + "')"); #endregion #region Power if(power > 0) sql.Append(" AND (Bonus1Type = '" + eProperty.MaxMana + "' AND Bonus1 >= '" + power + "' OR " + "Bonus2Type = '" + eProperty.MaxMana + "' AND Bonus2 >= '" + power + "' OR " + "Bonus3Type = '" + eProperty.MaxMana + "' AND Bonus3 >= '" + power + "' OR " + "Bonus4Type = '" + eProperty.MaxMana + "' AND Bonus4 >= '" + power + "' OR " + "Bonus5Type = '" + eProperty.MaxMana + "' AND Bonus5 >= '" + power + "' OR " + "Bonus6Type = '" + eProperty.MaxMana + "' AND Bonus6 >= '" + power + "' OR " + "Bonus7Type = '" + eProperty.MaxMana + "' AND Bonus7 >= '" + power + "' OR " + "Bonus8Type = '" + eProperty.MaxMana + "' AND Bonus8 >= '" + power + "' OR " + "Bonus9Type = '" + eProperty.MaxMana + "' AND Bonus9 >= '" + power + "' OR " + "Bonus10Type = '" + eProperty.MaxMana + "' AND Bonus10 >= '" + power + "' OR " + "ExtraBonusType = '" + eProperty.MaxMana + "' AND ExtraBonus >= '" + power + "')"); #endregion string qryString = GameServer.Database.Escape(sql.ToString()); var items = GameServer.Database.SelectObjects<InventoryItem>(qryString); int itemsOnPage = page < (int)Math.Ceiling((double)items.Count / 20) ? 20 : items.Count % 20; if (itemsOnPage > 0) { int itemCount = items.Count; int pageCount = (int)Math.Ceiling((double)itemCount / 20) - 1; client.Player.Out.SendMarketExplorerWindow(items, page, (byte)pageCount); client.Player.Out.SendMessage(itemsOnPage.ToString() + " Results found for page " + (page + 1) + ".", eChatType.CT_Important, eChatLoc.CL_ChatWindow); client.Player.TempProperties.removeProperty(EXPLORER_LIST); client.Player.TempProperties.setProperty(EXPLORER_LIST, items); } else client.Player.Out.SendMessage("No Items found", eChatType.CT_Important, eChatLoc.CL_ChatWindow); }
public void HandlePacket(GameClient client, GSPacketIn packet) { int packetVersion; switch (client.Version) { case GameClient.eClientVersion.Version168: case GameClient.eClientVersion.Version169: case GameClient.eClientVersion.Version170: case GameClient.eClientVersion.Version171: case GameClient.eClientVersion.Version172: case GameClient.eClientVersion.Version173: packetVersion = 168; break; default: packetVersion = 174; break; } packet.Skip(4); //Skip the first 4 bytes if (packetVersion == 174) { packet.Skip(1); } string charName = packet.ReadString(28); //TODO Character handling if (charName.Equals("noname")) { client.Out.SendSessionID(); } else { // SH: Also load the player if client player is NOT null but their charnames differ!!! // only load player when on charscreen and player is not loaded yet // packet is sent on every region change (and twice after "play" was pressed) if ( ( (client.Player == null && client.Account.Characters != null) || (client.Player != null && client.Player.Name.ToLower() != charName.ToLower()) ) && client.ClientState == GameClient.eClientState.CharScreen) { bool charFound = false; for (int i = 0; i < client.Account.Characters.Length; i++) { if (client.Account.Characters[i] != null && client.Account.Characters[i].Name == charName) { charFound = true; client.LoadPlayer(i); break; } } if (charFound == false) { client.Player = null; client.ActiveCharIndex = -1; } else { // Log character play AuditMgr.AddAuditEntry(client, AuditType.Character, AuditSubtype.CharacterLogin, "", charName); } } if (client.Player == null) { // client keeps sending the name of the deleted char even if new one was created, correct name only after "play" button pressed //client.Server.Error(new Exception("ERROR, active character not found!!! name="+charName)); } client.Out.SendSessionID(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null) { return; } string ipAddress = client.TcpEndpointAddress; byte major; byte minor; byte build; string password; string userName; if (client.Version >= GameClient.eClientVersion.Version1126) { // Read Login userName = packet.ReadIntPascalStringLowEndian(); // Read Password password = packet.ReadIntPascalStringLowEndian(); } else if (client.Version == GameClient.eClientVersion.Version1125) { // 1.125 // client type packet.Skip(1); //version major = (byte)packet.ReadByte(); minor = (byte)packet.ReadByte(); build = (byte)packet.ReadByte(); // revision packet.Skip(1); // build packet.Skip(2); // Read Login userName = packet.ReadIntPascalStringLowEndian(); // Read Password password = packet.ReadIntPascalStringLowEndian(); } else { // 1.115c - 1.124 // client type packet.Skip(1); //version major = (byte)packet.ReadByte(); minor = (byte)packet.ReadByte(); build = (byte)packet.ReadByte(); // revision packet.Skip(1); // build packet.Skip(2); // Read Login userName = packet.ReadShortPascalStringLowEndian(); // Read Password password = packet.ReadShortPascalStringLowEndian(); } // check server status if (GameServer.Instance.ServerStatus == eGameServerStatus.GSS_Closed) { client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.GameCurrentlyClosed); log.Info(ipAddress + " disconnected because game is closed!"); GameServer.Instance.Disconnect(client); return; } // check connection allowed with serverrules try { if (!GameServer.ServerRules.IsAllowedToConnect(client, userName)) { if (log.IsInfoEnabled) { log.Info($"{ipAddress} disconnected because IsAllowedToConnect returned false!"); } GameServer.Instance.Disconnect(client); return; } } catch (Exception e) { if (log.IsErrorEnabled) { log.Error("Error shutting down Client after IsAllowedToConnect failed!", e); } } // Handle connection EnterLock(userName); try { // Make sure that client won't quit lock (client) { GameClient.eClientState state = client.ClientState; if (state != GameClient.eClientState.NotConnected) { log.Debug($"wrong client state on connect {userName} {state}"); return; } if (log.IsInfoEnabled) { log.Info($"({ipAddress})User {userName} logging on! ({client.Version} type:{client.ClientType} add:{client.ClientAddons:G})"); } // check client already connected GameClient findclient = WorldMgr.GetClientByAccountName(userName, true); if (findclient != null) { client.IsConnected = false; if (findclient.ClientState == GameClient.eClientState.Connecting) { if (log.IsInfoEnabled) { log.Info("User is already connecting, ignored."); } client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn); return; } // in login if (findclient.ClientState == GameClient.eClientState.Linkdead) { if (log.IsInfoEnabled) { log.Info("User is still being logged out from linkdeath!"); } client.Out.SendLoginDenied(eLoginError.AccountIsInLogoutProcedure); } else { if (log.IsInfoEnabled) { log.Info("User already logged in!"); } client.Out.SendLoginDenied(eLoginError.AccountAlreadyLoggedIn); } GameServer.Instance.Disconnect(client); return; } Regex goodName = new Regex("^[a-zA-Z0-9]*$"); Account playerAccount; if (!goodName.IsMatch(userName) || string.IsNullOrWhiteSpace(userName)) { if (log.IsInfoEnabled) { log.Info($"Invalid symbols in account name \"{userName}\" found!"); } client.IsConnected = false; if (client.Out != null) { client.Out.SendLoginDenied(eLoginError.AccountInvalid); } else { log.Warn("Client or Client.Out null on invalid name failure. Disconnecting."); } GameServer.Instance.Disconnect(client); return; } else { playerAccount = GameServer.Database.FindObjectByKey <Account>(userName); client.PingTime = DateTime.Now.Ticks; if (playerAccount == null) { // check autocreate ... if (GameServer.Instance.Configuration.AutoAccountCreation && Properties.ALLOW_AUTO_ACCOUNT_CREATION) { // autocreate account if (string.IsNullOrEmpty(password)) { client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.AccountInvalid); GameServer.Instance.Disconnect(client); if (log.IsInfoEnabled) { log.Info($"Account creation failed, no password set for Account: {userName}"); } return; } // check for account bombing TimeSpan ts; IList <Account> allAccByIp = GameServer.Database.SelectObjects <Account>("`LastLoginIP` = @LastLoginIP", new QueryParameter("@LastLoginIP", ipAddress)); int totalacc = 0; foreach (Account ac in allAccByIp) { ts = DateTime.Now - ac.CreationDate; if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION_SAMEIP && totalacc > 1) { log.Warn($"Account creation: too many from same IP within set minutes - {userName} : {ipAddress}"); client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime); GameServer.Instance.Disconnect(client); return; } totalacc++; } if (totalacc >= Properties.TOTAL_ACCOUNTS_ALLOWED_SAMEIP) { log.Warn($"Account creation: too many accounts created from same ip - {userName} : {ipAddress}"); client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.AccountNoAccessThisGame); GameServer.Instance.Disconnect(client); return; } // per timeslice - for preventing account bombing via different ip if (Properties.TIME_BETWEEN_ACCOUNT_CREATION > 0) { ts = DateTime.Now - _lastAccountCreateTime; if (ts.TotalMinutes < Properties.TIME_BETWEEN_ACCOUNT_CREATION) { log.Warn($"Account creation: time between account creation too small - {userName} : {ipAddress}"); client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.PersonalAccountIsOutOfTime); GameServer.Instance.Disconnect(client); return; } } _lastAccountCreateTime = DateTime.Now; playerAccount = new Account { Name = userName, Password = CryptPassword(password), Realm = 0, CreationDate = DateTime.Now, LastLogin = DateTime.Now, LastLoginIP = ipAddress, LastClientVersion = ((int)client.Version).ToString(), Language = Properties.SERV_LANGUAGE, PrivLevel = 1 }; if (log.IsInfoEnabled) { log.Info($"New account created: {userName}"); } GameServer.Database.AddObject(playerAccount); // Log account creation AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountCreate, string.Empty, userName); } else { if (log.IsInfoEnabled) { log.Info("No such account found and autocreation deactivated!"); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.AccountNotFound); GameServer.Instance.Disconnect(client); return; } } else { // check password if (!playerAccount.Password.StartsWith("##")) { playerAccount.Password = CryptPassword(playerAccount.Password); } if (!CryptPassword(password).Equals(playerAccount.Password)) { if (log.IsInfoEnabled) { log.Info($"({client.TcpEndpoint}) Wrong password!"); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.WrongPassword); // Log failure AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountFailedLogin, string.Empty, userName); GameServer.Instance.Disconnect(client); return; } // save player infos playerAccount.LastLogin = DateTime.Now; playerAccount.LastLoginIP = ipAddress; playerAccount.LastClientVersion = ((int)client.Version).ToString(); if (string.IsNullOrEmpty(playerAccount.Language)) { playerAccount.Language = Properties.SERV_LANGUAGE; } GameServer.Database.SaveObject(playerAccount); } } // Save the account table client.Account = playerAccount; // create session ID here to disable double login bug if (WorldMgr.CreateSessionID(client) < 0) { if (log.IsInfoEnabled) { log.InfoFormat("Too many clients connected, denied login to {0}", playerAccount.Name); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.TooManyPlayersLoggedIn); client.Disconnect(); return; } client.Out.SendLoginGranted(); client.ClientState = GameClient.eClientState.Connecting; // Log entry AuditMgr.AddAuditEntry(client, AuditType.Account, AuditSubtype.AccountSuccessfulLogin, string.Empty, userName); } } catch (DatabaseException e) { if (log.IsErrorEnabled) { log.Error("LoginRequestHandler", e); } client.IsConnected = false; client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount); GameServer.Instance.Disconnect(client); } catch (Exception e) { if (log.IsErrorEnabled) { log.Error("LoginRequestHandler", e); } client.Out.SendLoginDenied(eLoginError.CannotAccessUserAccount); GameServer.Instance.Disconnect(client); } finally { ExitLock(userName); } }
/// <summary> /// Reads up ONE character iteration on the packet stream /// </summary> /// <param name="packet"></param> /// <param name="client"></param> public CreationCharacterData(GSPacketIn packet, GameClient client) { //unk - probably indicates customize or create (these are moved from 1.99 4 added bytes) if (client.Version >= GameClient.eClientVersion.Version1104) { packet.ReadIntLowEndian(); } CharName = packet.ReadString(24); CustomMode = packet.ReadByte(); EyeSize = packet.ReadByte(); LipSize = packet.ReadByte(); EyeColor = packet.ReadByte(); HairColor = packet.ReadByte(); FaceType = packet.ReadByte(); HairStyle = packet.ReadByte(); packet.Skip(3); MoodType = packet.ReadByte(); packet.Skip(8); Operation = packet.ReadInt(); var unk = packet.ReadByte(); packet.Skip(24); //Location String packet.Skip(24); //Skip class name packet.Skip(24); //Skip race name var level = packet.ReadByte(); //not safe! Class = packet.ReadByte(); Realm = packet.ReadByte(); //The following byte contains //1bit=start location ... in ShroudedIsles you can choose ... //1bit=first race bit //1bit=unknown //1bit=gender (0=male, 1=female) //4bit=race byte startRaceGender = (byte)packet.ReadByte(); Race = (startRaceGender & 0x0F) + ((startRaceGender & 0x40) >> 2); Gender = ((startRaceGender >> 4) & 0x01); SIStartLocation = ((startRaceGender >> 7) != 0); CreationModel = packet.ReadShortLowEndian(); Region = packet.ReadByte(); packet.Skip(1); //TODO second byte of region unused currently packet.Skip(4); //TODO Unknown Int / last used? Strength = packet.ReadByte(); Dexterity = packet.ReadByte(); Constitution = packet.ReadByte(); Quickness = packet.ReadByte(); Intelligence = packet.ReadByte(); Piety = packet.ReadByte(); Empathy = packet.ReadByte(); Charisma = packet.ReadByte(); packet.Skip(40); //TODO equipment var activeRightSlot = packet.ReadByte(); // 0x9C var activeLeftSlot = packet.ReadByte(); // 0x9D var siZone = packet.ReadByte(); // 0x9E // skip 4 bytes added in 1.99 if (client.Version >= GameClient.eClientVersion.Version199 && client.Version < GameClient.eClientVersion.Version1104) { packet.Skip(4); } // New constitution must be read before skipping 4 bytes NewConstitution = packet.ReadByte(); // 0x9F }
public void HandlePacket(GameClient client, GSPacketIn packet) { int packetVersion; switch (client.Version) { case GameClient.eClientVersion.Version168: case GameClient.eClientVersion.Version169: case GameClient.eClientVersion.Version170: case GameClient.eClientVersion.Version171: case GameClient.eClientVersion.Version172: case GameClient.eClientVersion.Version173: packetVersion = 168; break; default: packetVersion = 174; break; } packet.Skip(4); //Skip the first 4 bytes if (packetVersion == 174) { packet.Skip(1); } string charName = packet.ReadString(28); //TODO Character handling if (charName.Equals("noname")) { client.Out.SendSessionID(); } else { // SH: Also load the player if client player is NOT null but their charnames differ!!! // only load player when on charscreen and player is not loaded yet // packet is sent on every region change (and twice after "play" was pressed) if ( ( (client.Player == null && client.Account.Characters != null) || (client.Player != null && client.Player.Name.ToLower() != charName.ToLower()) ) && client.ClientState == GameClient.eClientState.CharScreen) { bool charFound = false; for (int i = 0; i < client.Account.Characters.Length; i++) { if (client.Account.Characters[i] != null && client.Account.Characters[i].Name == charName) { charFound = true; client.LoadPlayer(i); break; } } if (charFound == false) { client.Player = null; client.ActiveCharIndex = -1; } else { // Log character play AuditMgr.AddAuditEntry(client, AuditType.Character, AuditSubtype.CharacterLogin, "", charName); } } if (client.Player == null) { // client keeps sending the name of the deleted char even if new one was created, correct name only after "play" button pressed //client.Server.Error(new Exception("ERROR, active character not found!!! name="+charName)); } client.Out.SendSessionID(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client.Version >= GameClient.eClientVersion.Version1126) { _HandlePacket1126(client, packet); return; } // 1125d support TODO this needs to be changed when a version greater than 1125d comes out if (client.Version >= GameClient.eClientVersion.Version1125) { _HandlePacket1125d(client, packet); return; } int packetVersion; switch (client.Version) { case GameClient.eClientVersion.Version168: case GameClient.eClientVersion.Version169: case GameClient.eClientVersion.Version170: case GameClient.eClientVersion.Version171: case GameClient.eClientVersion.Version172: case GameClient.eClientVersion.Version173: packetVersion = 168; break; default: packetVersion = 174; break; } packet.Skip(4); //Skip the first 4 bytes if (packetVersion == 174) { packet.Skip(1); } string charName = packet.ReadString(28); //TODO Character handling if (charName.Equals("noname")) { client.Out.SendSessionID(); } else { // SH: Also load the player if client player is NOT null but their charnames differ!!! // only load player when on charscreen and player is not loaded yet // packet is sent on every region change (and twice after "play" was pressed) if ( ( (client.Player == null && client.Account.Characters != null) || (client.Player != null && client.Player.Name.ToLower() != charName.ToLower()) ) && client.ClientState == GameClient.eClientState.CharScreen) { bool charFound = false; for (int i = 0; i < client.Account.Characters.Length; i++) { if (client.Account.Characters[i] != null && client.Account.Characters[i].Name == charName) { charFound = true; // Notify Character Selection Event, last hope to fix any bad data before Loading. GameEventMgr.Notify(DatabaseEvent.CharacterSelected, new CharacterEventArgs(client.Account.Characters[i], client)); client.LoadPlayer(i); break; } } if (charFound == false) { client.Player = null; client.ActiveCharIndex = -1; } else { // Log character play AuditMgr.AddAuditEntry(client, AuditType.Character, AuditSubtype.CharacterLogin, "", charName); } } client.Out.SendSessionID(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { int packetVersion; switch (client.Version) { case GameClient.eClientVersion.Version168: case GameClient.eClientVersion.Version169: case GameClient.eClientVersion.Version170: case GameClient.eClientVersion.Version171: case GameClient.eClientVersion.Version172: case GameClient.eClientVersion.Version173: packetVersion = 168; break; default: packetVersion = 174; break; } packet.Skip(4); //Skip the first 4 bytes if (packetVersion == 174) { packet.Skip(1); } string charName = packet.ReadString(28); // WHRIA START if (charName.Length >= 5) { if (charName.Substring(0, 4) == "slot") { int iSelected = 0; if (charName.Substring(4, 1) == "a") iSelected = 0; if (charName.Substring(4, 1) == "b") iSelected = 1; if (charName.Substring(4, 1) == "c") iSelected = 2; if (charName.Substring(4, 1) == "d") iSelected = 3; if (charName.Substring(4, 1) == "e") iSelected = 4; if (charName.Substring(4, 1) == "f") iSelected = 5; if (charName.Substring(4, 1) == "g") iSelected = 6; if (charName.Substring(4, 1) == "h") iSelected = 7; if (charName.Substring(4, 1) == "i") iSelected = 8; if (charName.Substring(4, 1) == "j") iSelected = 9; int sizeOfCharacter = client.Account.Characters.Length; for (int j = 0; j < sizeOfCharacter; j++) { int iSlot = client.Account.Characters[j].AccountSlot; if (iSlot >= 300) iSlot -= 300; if (iSlot >= 200) iSlot -= 200; if (iSlot >= 100) iSlot -= 100; if (iSlot == iSelected) { Regex nameCheck = new Regex("^[A-Z][a-zA-Z]"); if (!nameCheck.IsMatch(client.Account.Characters[j].Name) && client.Account.Characters[j] != null) { charName = client.Account.Characters[j].Name; } } } } } // END //TODO Character handling if (charName.Equals("noname")) { client.Out.SendSessionID(); } else { // SH: Also load the player if client player is NOT null but their charnames differ!!! // only load player when on charscreen and player is not loaded yet // packet is sent on every region change (and twice after "play" was pressed) if ( ( (client.Player == null && client.Account.Characters != null) || (client.Player != null && client.Player.Name.ToLower() != charName.ToLower()) ) && client.ClientState == GameClient.eClientState.CharScreen) { bool charFound = false; for (int i = 0; i < client.Account.Characters.Length; i++) { if (client.Account.Characters[i] != null && client.Account.Characters[i].Name == charName) { charFound = true; // Notify Character Selection Event, last hope to fix any bad data before Loading. GameEventMgr.Notify(DatabaseEvent.CharacterSelected, new CharacterEventArgs(client.Account.Characters[i], client)); client.LoadPlayer(i); break; } } if (charFound == false) { client.Player = null; client.ActiveCharIndex = -1; } else { // Log character play AuditMgr.AddAuditEntry(client, AuditType.Character, AuditSubtype.CharacterLogin, "", charName); } } client.Out.SendSessionID(); } }
public void HandlePacket(GameClient client, GSPacketIn packet) { if (client == null || client.Player == null) return; if (client.Player.ObjectState != GameObject.eObjectState.Active) return; ushort sessionId = packet.ReadShort(); // session ID if (client.SessionID != sessionId) { // GameServer.BanAccount(client, 120, "Hack sessionId", string.Format("Wrong sessionId:0x{0} in 0xBA packet (SessionID:{1})", sessionId, client.SessionID)); return; // client hack } ushort head = packet.ReadShort(); client.Player.Heading = (ushort)(head & 0xFFF); packet.Skip(1); // unknown int flags = packet.ReadByte(); // client.Player.PetInView = ((flags & 0x04) != 0); // TODO client.Player.GroundTargetInView = ((flags & 0x08) != 0); client.Player.TargetInView = ((flags & 0x10) != 0); byte[] con = packet.ToArray(); if (!client.Player.IsAlive) { con[9] = 5; // set dead state } else if (client.Player.Steed != null && client.Player.Steed.ObjectState == GameObject.eObjectState.Active) { client.Player.Heading = client.Player.Steed.Heading; con[9] = 6; // Set ride state con[7] = (byte)(client.Player.Steed.RiderSlot(client.Player)); // there rider slot this player con[2] = (byte)(client.Player.Steed.ObjectID >> 8); //heading = steed ID con[3] = (byte)(client.Player.Steed.ObjectID & 0xFF); } con[5] &= 0xC0; //11 00 00 00 = 0x80(Torch) + 0x40(Unknown), all other in view check's not need send anyone if (client.Player.IsWireframe) { con[5] |= 0x01; } //stealth is set here if (client.Player.IsStealthed) { con[5] |= 0x02; } con[8] = (byte)((con[8] & 0x80) | client.Player.HealthPercent); GSUDPPacketOut outpak = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerHeading)); //Now copy the whole content of the packet outpak.Write(con, 0, /*con.Length*/10); outpak.WritePacketLength(); GSUDPPacketOut outpak190 = null; // byte[] outp = outpak.GetBuffer(); // outpak = null; foreach (GamePlayer player in client.Player.GetPlayersInRadius(WorldMgr.VISIBILITY_DISTANCE)) { if (player != null && player != client.Player) { if (player.Client.Version >= GameClient.eClientVersion.Version190) { if (outpak190 == null) { outpak190 = new GSUDPPacketOut(client.Out.GetPacketCode(eServerPackets.PlayerHeading)); byte[] con190 = (byte[])con.Clone(); //Now copy the whole content of the packet outpak190.Write(con190, 0, /*con190.Lenght*/10); outpak190.WriteByte(client.Player.ManaPercent); outpak190.WriteByte(client.Player.EndurancePercent); outpak190.WritePacketLength(); // byte[] outp190 = outpak190.GetBuffer(); // outpak190 = null;// ? } player.Out.SendUDPRaw(outpak190); } else player.Out.SendUDPRaw(outpak); } } }