コード例 #1
0
        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();
            }
        }
コード例 #2
0
        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();
            }
        }
コード例 #3
0
        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();
        }
コード例 #4
0
        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);
                }
            }
        }
コード例 #5
0
        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();
        }
コード例 #6
0
        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);
                }
            }
        }
コード例 #7
0
ファイル: PingRequestHandler.cs プロジェクト: towbes/DOLSharp
        /// <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);
        }
コード例 #8
0
        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);
            }
        }
コード例 #9
0
ファイル: PingRequestHandler.cs プロジェクト: mynew4/DAoC
		/// <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);
		}
コード例 #10
0
		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);
		}
コード例 #11
0
        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);
        }
コード例 #12
0
        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();
            }
        }
コード例 #13
0
ファイル: CryptKeyRequestHandler.cs プロジェクト: mynew4/DAoC
		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();
			}
		}
コード例 #14
0
		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);
			}
		}
コード例 #15
0
        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);
            }
        }
コード例 #16
0
        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();
            }
        }
コード例 #17
0
        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);
            }
        }
コード例 #18
0
        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);
            }
        }
コード例 #19
0
		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);
			}
		}
コード例 #20
0
        //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();
                    }
                }
            }
        }
コード例 #21
0
        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);
                }
            }
        }
コード例 #22
0
        //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();
                }
            }
        }
コード例 #23
0
        //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();
                    }
                }
            }
        }
コード例 #24
0
        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);
                    }
                }
            }
        }
コード例 #25
0
        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);
                    }
                }
            }
        }
コード例 #26
0
        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;
        }
コード例 #27
0
        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);
                }
            }
        }
コード例 #28
0
		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();
			}
		}
コード例 #29
0
        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;
        }
コード例 #30
0
        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);
        }
コード例 #31
0
        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();
            }
        }
コード例 #32
0
        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);
            }
        }
コード例 #33
0
            /// <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
            }
コード例 #34
0
        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();
            }
        }
コード例 #35
0
        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();
            }
        }
コード例 #36
0
		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();
			}
		}
コード例 #37
0
        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);
                }
            }
        }