Thread Rating:
  • 9 Vote(s) - 4.56 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Release MW3 Server Addon Extensions
(01-02-2014, 08:46)master131 Wrote:
(01-02-2014, 08:38)[HARD] Tony. Wrote: I think would be cheerful if to add bots. they are OnNotify(joined_spectators). it would be cheerful, better than to play with people here an example.


http://youtu.be/UqPO8Rofb0g

Will do. Also, I edited Timing.cs again because the correct way to solve the issue is mentioned here on MSDN using a GCHandle:
http://msdn.microsoft.com/en-us/library/367eeye0.aspx

EDIT - The GSC function AddTestClient is null-sub'ed, aka, it's been emptied out so it does absolutely nothing. I remember @NTAuthority made an modification which allowed it, will dig in and figure it out.

EDIT #2 - This looks like quite a bit of work to do, there's alot for me to patch and port to C#, I'll do it when I have time, I'm currently working on something else right now that's not MW3 related.
YOU convert a code with C++ on #? Troll
or you want to add them in addon? Huh
Reply

(01-02-2014, 08:57)[HARD] Tony. Wrote:
(01-02-2014, 08:46)master131 Wrote:
(01-02-2014, 08:38)[HARD] Tony. Wrote: I think would be cheerful if to add bots. they are OnNotify(joined_spectators). it would be cheerful, better than to play with people here an example.


http://youtu.be/UqPO8Rofb0g

Will do. Also, I edited Timing.cs again because the correct way to solve the issue is mentioned here on MSDN using a GCHandle:
http://msdn.microsoft.com/en-us/library/367eeye0.aspx

EDIT - The GSC function AddTestClient is null-sub'ed, aka, it's been emptied out so it does absolutely nothing. I remember @NTAuthority made an modification which allowed it, will dig in and figure it out.

EDIT #2 - This looks like quite a bit of work to do, there's alot for me to patch and port to C#, I'll do it when I have time, I'm currently working on something else right now that's not MW3 related.
YOU convert a code with C++ on #? Troll
or you want to add them in addon? Huh

I'm not going to make a custom version of the addon, I'm going to port the bots code to C#.
[Image: 30xhrep.png]

A casual conversation between barata and I about Nukem.
Reply

(01-02-2014, 09:04)master131 Wrote:
(01-02-2014, 08:57)[HARD] Tony. Wrote:
(01-02-2014, 08:46)master131 Wrote:
(01-02-2014, 08:38)[HARD] Tony. Wrote: I think would be cheerful if to add bots. they are OnNotify(joined_spectators). it would be cheerful, better than to play with people here an example.


http://youtu.be/UqPO8Rofb0g

Will do. Also, I edited Timing.cs again because the correct way to solve the issue is mentioned here on MSDN using a GCHandle:
http://msdn.microsoft.com/en-us/library/367eeye0.aspx

EDIT - The GSC function AddTestClient is null-sub'ed, aka, it's been emptied out so it does absolutely nothing. I remember @NTAuthority made an modification which allowed it, will dig in and figure it out.

EDIT #2 - This looks like quite a bit of work to do, there's alot for me to patch and port to C#, I'll do it when I have time, I'm currently working on something else right now that's not MW3 related.
YOU convert a code with C++ on #? Troll
or you want to add them in addon? Huh

I'm not going to make a custom version of the addon, I'm going to port the bots code to C#.

Thanks Nyan Cat
Reply

Thanks. Smile
~FYANB~ Servers Website

Primary Account:
[Image: 76561198070236721.png]
Secondary Account:
[Image: 76561198096107676.png]
Third Account:
[Image: 76561198164751656.png]
Reply

Here's TestClients.cs, I haven't gotten around to making the bots properly spawn, but they appear as spectators when you call TestClients.AddTestClient. Credits go to @NTAuthority for the original code for IW5M.

<removed, check main post>
[Image: 30xhrep.png]

A casual conversation between barata and I about Nukem.
Reply

(01-02-2014, 18:53)master131 Wrote: Here's TestClients.cs, I haven't gotten around to making the bots properly spawn, but they appear as spectators when you call TestClients.AddTestClient. Credits go to @NTAuthority for the original code for IW5M.

Code:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

namespace Addon
{
    static class TestClients
    {
        #region Hooking Functions
        [DllImport("kernel32.dll", SetLastError = true)]
        static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);

        [DllImport("kernel32.dll", SetLastError = true)]
        static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, uint flAllocationType, uint flProtect);

        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);

        private const uint MEM_COMMIT = 0x1000;
        private const uint MEM_RESERVE = 0x2000;
        private const uint PAGE_EXECUTE_READWRITE = 0x40;

        private static readonly List<GCHandle> GCHandles = new List<GCHandle>();

        private static void PerformJmpHook(IntPtr original, byte[] destinationStub)
        {
            var stubAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr) destinationStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(destinationStub, 0, stubAddress, destinationStub.Length);
            PerformJmpHook(original, stubAddress);
        }

        private static void PerformJmpHook(IntPtr original, IntPtr destination)
        {
            uint oldProtect;
            VirtualProtect(original, (UIntPtr)5, PAGE_EXECUTE_READWRITE, out oldProtect);
            var hook = new byte[5];
            hook[0] = 0xE9;
            BitConverter.GetBytes((destination.ToInt32() - original.ToInt32()) - 5).CopyTo(hook, 1);
            Marshal.Copy(hook, 0, original, hook.Length);
            VirtualProtect(original, (UIntPtr)5, oldProtect, out oldProtect);
        }

        private static IntPtr GetUnmanagedFunctionPointerFromDelegate(Delegate d)
        {
            GCHandles.Add(GCHandle.Alloc(d));
            return Marshal.GetFunctionPointerForDelegate(d);
        }
        #endregion

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate bool SvCheckClientDelegate(IntPtr clientPart);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate int FuncIntDelegate();

        [UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
        private delegate void SvCmdTokenizeStringDelegate(string str);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void SvDirectConnectDelegate(netaddr_t adr);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void SvSendClientGameStateDelegate(IntPtr client);

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate void SvClientEnterWorldDelegate(IntPtr client, byte[] userCmd);

        private static readonly IntPtr SvCheckTimeoutAddress = (IntPtr) 0x4FE8A0;
        private static readonly IntPtr SteamCheckSvAuthAddress = (IntPtr) 0x599D20;
        private static readonly IntPtr ResetReliableCmdAddress = (IntPtr) 0x5029DB;
        private static readonly IntPtr SvMaxClientsDvarPtr = (IntPtr) 0x5787780;
        private static readonly IntPtr ClientAddress = (IntPtr) 0x4A0FE90;
        private static readonly IntPtr GetStatMajorAddress = (IntPtr) 0x4D0560;
        private static readonly IntPtr GetStatMinorAddress = (IntPtr) 0x4D05A0;
        private static readonly IntPtr GetChecksumAddress = (IntPtr) 0x40C8C0;
        private static readonly IntPtr SvDirectConnectAddress = (IntPtr) 0x4F7670;
        private static readonly IntPtr SvCmdArgsAddress = (IntPtr) 0x1B5B7D8;

        private static readonly FuncIntDelegate GetStatMajor;
        private static readonly FuncIntDelegate GetStatMinor;
        private static readonly FuncIntDelegate GetChecksum;
        private static readonly SvCmdTokenizeStringDelegate SvCmdTokenizeString;
        private static readonly SvDirectConnectDelegate SvDirectConnect;
        private static readonly SvSendClientGameStateDelegate SvSendClientGameState;
        private static readonly SvClientEnterWorldDelegate SvClientEnterWorld;

        private static ushort BotPort;

        private static byte[] SvCheckTimeoutHookStub = new byte[]
        {
            0x56, // push esi
            0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, <handler>
            0xFF, 0xD0, // call eax
            0x83, 0xC4, 0x04, // add esp, 4
            0x84, 0xC0, // test al, al
            0x68, 0xA7, 0xE8, 0x4F, 0x00, // push 4FE8A7h
            0xC3, // retn
        };

        private static byte[] SteamCheckSvAuthHookStub = new byte[]
        {
            0x56, // push esi
            0xB8, 0x00, 0x00, 0x00, 0x00, // mov eax, <handler>
            0xFF, 0xD0, // call eax
            0x83, 0xC4, 0x04, // add esp, 4
            0x84, 0xC0, // test al, al
            0x75, 0x06, // jnz short continueSteamCheck
            0x68, 0xBC, 0x9D, 0x59, 0x00, // push 599DBCh
            0xC3, // retn

            // continueSteamCheck:
            0x68, 0x2D, 0x9D, 0x59, 0x00, // push 599D2Dh
            0xC3, // retn
        };

        private static byte[] ResetReliableCmdHookStub = new byte[]
        {
            0x80, 0xBE, 0xC0, 0x52, 0x04, 0x00, 0xFF, // cmp byte ptr [esi+452C0h], 0FFh
            0x75, 0x0C, // jnz short doReturn
            0x8B, 0x86, 0x70, 0x0E, 0x02, 0x00, // mov eax, [esi+20E70h]
            0x89, 0x86, 0x74, 0x0E, 0x02, 0x00, // mov [esi+20E74h], eax

            // doReturn:
            0x83, 0x3D, 0x9C, 0x1F, 0x2F, 0x06, 0x00, // cmp dword ptr [62F1F9C], 0
            0x68, 0xE2, 0x29, 0x50, 0x00, // push 5029E2h
            0xC3 // retn
        };

        private static byte[] SvCmdTokenizeStringStub = new byte[]
        {
            0x55, // push ebp
            0x8B, 0xEC, // mov ebp, esp
            0x56, // push esi
            0x51, // push ecx
            0xB8, 0x00, 0x02, 0x00, 0x00, // mov eax, 200
            0x2B, 0x05, 0xD0, 0xAF, 0xB4, 0x01, // sub eax, dword ptr [1B4AFD0]
            0x50, // push eax
            0xFF, 0x75, 0x08, // push [ebp+8]
            0xB9, 0xB0, 0x87, 0xB4, 0x01, // mov ecx, 1B487B0
            0xBE, 0xD8, 0xB7, 0xB5, 0x01, // mov esi, 1B5B7D8
            0xB8, 0x00, 0xC1, 0x4C, 0x00, // mov eax, 4CC100
            0xFF, 0xD0, // call eax
            0x83, 0xC4, 0x08, // add esp, 8
            0x59, // pop ecx
            0x5E, // pop esi
            0x5D, // pop ebp
            0xC3 // retn
        };

        private static readonly byte[] SvSendClientGameStateStub = new byte[]
        {
            0x55, // push ebp
            0x8B, 0xEC, // mov ebp, esp
            0x51, // push ecx
            0xB9, 0x40, 0x8D, 0x4F, 0x00, // mov ecx, 4F8D40
            0x8B, 0x45, 0x08, // mov eax, [ebp+8]
            0xFF, 0xD1, // call ecx
            0x59, // pop ecx
            0x5D, // pop ebp
            0xC3 // retn
        };

        private static readonly byte[] SvClientEnterWorldStub = new byte[]
        {
            0x55, // push ebp
            0x8B, 0xEC, // mov ebp, esp
            0x52, // push edx
            0xB8, 0xC0, 0x8F, 0x4F, 0x00, // mov eax, 4F8FC0
            0xFF, 0x75, 0x08, // push [ebp+8]
            0x8B, 0x55, 0x0C, // mov edx, [ebp+C]
            0xFF, 0xD0, // call eax
            0x83, 0xC4, 0x04, // add esp, 4
            0x5A, // pop edx
            0x5D, // pop ebp
            0xC3 // retn
        };

        [StructLayout(LayoutKind.Sequential)]
        struct netaddr_t
        {
            public int type;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public byte[] ip;
            public ushort port;
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
            public byte[] ipx;
        }

        static TestClients()
        {
            // Hook required methods.
            var svCheckTimeoutFuncAddress = GetUnmanagedFunctionPointerFromDelegate(
                new SvCheckClientDelegate(SvCheckTimeoutFunc));
            BitConverter.GetBytes(svCheckTimeoutFuncAddress.ToInt32()).CopyTo(SvCheckTimeoutHookStub, 2);
            PerformJmpHook(SvCheckTimeoutAddress, SvCheckTimeoutHookStub);

            var steamCheckSvAuthFuncAddress = GetUnmanagedFunctionPointerFromDelegate(
                new SvCheckClientDelegate(SteamCheckSvAuthFunc));
            BitConverter.GetBytes(steamCheckSvAuthFuncAddress.ToInt32()).CopyTo(SteamCheckSvAuthHookStub, 2);
            PerformJmpHook(SteamCheckSvAuthAddress, SteamCheckSvAuthHookStub);

            PerformJmpHook(ResetReliableCmdAddress, ResetReliableCmdHookStub);

            // Prepare function delegates.
            GetStatMajor = (FuncIntDelegate) Marshal.GetDelegateForFunctionPointer(GetStatMajorAddress, typeof (FuncIntDelegate));
            GetStatMinor = (FuncIntDelegate) Marshal.GetDelegateForFunctionPointer(GetStatMinorAddress, typeof (FuncIntDelegate));
            GetChecksum = (FuncIntDelegate) Marshal.GetDelegateForFunctionPointer(GetChecksumAddress, typeof (FuncIntDelegate));
            SvDirectConnect = (SvDirectConnectDelegate) Marshal.GetDelegateForFunctionPointer(SvDirectConnectAddress, typeof (SvDirectConnectDelegate));

            var svCmdTokenizeStringAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr) SvCmdTokenizeStringStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(SvCmdTokenizeStringStub, 0, svCmdTokenizeStringAddress, SvCmdTokenizeStringStub.Length);
            SvCmdTokenizeString = (SvCmdTokenizeStringDelegate) Marshal.GetDelegateForFunctionPointer(svCmdTokenizeStringAddress, typeof (SvCmdTokenizeStringDelegate));

            var svSendClientGameStateAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr) SvSendClientGameStateStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(SvSendClientGameStateStub, 0, svSendClientGameStateAddress, SvSendClientGameStateStub.Length);
            SvSendClientGameState = (SvSendClientGameStateDelegate) Marshal.GetDelegateForFunctionPointer(svSendClientGameStateAddress, typeof (SvSendClientGameStateDelegate));

            var svClientEnterWorldAddress = VirtualAlloc(IntPtr.Zero, (UIntPtr)SvClientEnterWorldStub.Length, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
            Marshal.Copy(SvClientEnterWorldStub, 0, svClientEnterWorldAddress, SvClientEnterWorldStub.Length);
            SvClientEnterWorld = (SvClientEnterWorldDelegate)Marshal.GetDelegateForFunctionPointer(svClientEnterWorldAddress, typeof(SvClientEnterWorldDelegate));
        }

        private static bool SvCheckTimeoutFunc(IntPtr clientPart)
        {
            var client = (IntPtr) (clientPart.ToInt32() - 136300);
            return Marshal.ReadInt32(client, -136260) != 2 &&
                   (Marshal.ReadInt32(client) == 1 || Marshal.ReadInt32(client, 283328) != -1);
        }

        private static bool SteamCheckSvAuthFunc(IntPtr clientPart)
        {
            var client = (IntPtr) (clientPart.ToInt32() - 283325);
            return Marshal.ReadInt32(client) >= 5 && Marshal.ReadInt32(client, 283328) != -1;
        }

        private static IntPtr GetClientFromNum(int clientNum)
        {
            return (IntPtr)(ClientAddress.ToInt32() + clientNum * 0x78690);
        }

        private static void SvCmdEndTokenizedString()
        {
            var argsIndex = Marshal.ReadInt32(SvCmdArgsAddress);

            var addr = (IntPtr) 0x1B4AFD0;
            var value = Marshal.ReadInt32(addr);
            var arrValue = Marshal.ReadInt32((IntPtr)0x1B5B81C, argsIndex * 4);
            Marshal.WriteInt32(addr, value - arrValue);

            addr = (IntPtr) 0x1B4AFD4;
            value = Marshal.ReadInt32(addr);
            arrValue = Marshal.ReadInt32((IntPtr)0x1B4AFB0, argsIndex * 4);

            argsIndex--;
            Marshal.WriteInt32(SvCmdArgsAddress, argsIndex);
        }

        private static void Memset(IntPtr ptr, int value, int length)
        {
            var b = (byte) value;
            for (int i = 0; i < length; i++)
                Marshal.WriteByte(ptr, i, b);
        }

        public static int AddTestClient()
        {
            // Read the sv_maxclients dvar value.
            var maxClients = Marshal.ReadInt32(Marshal.ReadIntPtr(SvMaxClientsDvarPtr), 0xC);
            
            // Look for a free slot.
            int index = 0;
            for (index = 0; index < maxClients; index++)
            {
                if (Marshal.ReadInt32(GetClientFromNum(index)) == 0)
                    break;
            }

            // No slots available.
            if (index == maxClients)
                return -1;

            // Prepare connection string.
            const int protocol = 20601; // as of 1.9.461
            var connectString = string.Format(
                "connect bot{0} \"\\cg_predictItems\\1\\cl_anonymous\\0\\color\\4\\head\\default\\model\\multi\\snaps\\20\\rate\\5000\\name\\bot{0}\\protocol\\{1}\\checksum\\{2}\\statver\\{3} {4}\\qport\\{5}\"",
                BotPort, protocol, GetChecksum(),
                GetStatMajor(), (uint) GetStatMinor(),
                BotPort + 1);

            // Handle client connection.
            var botAdr = new netaddr_t { port = BotPort };

            SvCmdTokenizeString(connectString.PadRight(1023, '\0'));
            SvDirectConnect(botAdr);
            SvCmdEndTokenizedString();

            BotPort++;

            // Get the bot's client number and client address.
            index = 0;

            IntPtr botClient = IntPtr.Zero;
            for (index = 0; index < maxClients; index++)
            {
                if (Marshal.ReadInt32(botClient = GetClientFromNum(index)) == 0)
                    continue;
                var clientAdr = (netaddr_t) Marshal.PtrToStructure((IntPtr) (botClient.ToInt32() + 40), typeof (netaddr_t));
                if (clientAdr.type == botAdr.type && clientAdr.port == botAdr.port)
                    break;
            }

            // Failed for some reason.
            if (index == maxClients)
                return -1;

            // Set the "bot" flag (actually the lower dword of the steam id)
            Marshal.WriteInt32(botClient, 283328, -1);

            // Set stat flags to "already set"
            Marshal.WriteInt16(botClient, 283322, 0x3FF);
            Memset((IntPtr)(botClient.ToInt32() + 269497), 0, 0x2FFC);
            Memset((IntPtr)(botClient.ToInt32() + 281785), 0, 0x600);

            // Call SV_SendClientGameState
            SvSendClientGameState(botClient);

            // SV_ClientEnterWorld
            SvClientEnterWorld(botClient, new byte[44]);

            // Return client num.
            return index;
        }
    }
}
full help
well, but I can't test today it (I have already 10 o'clock in the morning,.Fuu ) tomorrow I will get up and I will test it. Fuu ....
Reply

ok so how do i run the bots code??
~FYANB~ Servers Website

Primary Account:
[Image: 76561198070236721.png]
Secondary Account:
[Image: 76561198096107676.png]
Third Account:
[Image: 76561198164751656.png]
Reply

(01-02-2014, 19:38)Casper Wrote: ok so how do i run the bots code??

TestClients.AddTestClient
Reply

Hahaha, "connect" string. I didn't knew that bots using this way.
C++/Obj-Cdeveloper. Neko engine wip
Steam: Click
Reply

well the code works. but yea they only appear as spectators.
~FYANB~ Servers Website

Primary Account:
[Image: 76561198070236721.png]
Secondary Account:
[Image: 76561198096107676.png]
Third Account:
[Image: 76561198164751656.png]
Reply



Possibly Related Threads…
Thread Author Replies Views Last Post
  Help, server Admin largosik 0 2,294 02-02-2019, 18:09
Last Post: largosik
  Add a point shop to my server h1dexyz 1 3,151 03-04-2018, 22:36
Last Post: h1dexyz
Lightbulb Preview Weapon Classe For Infected Clasic Server groochu1982 0 2,445 02-19-2017, 08:35
Last Post: groochu1982
Exclamation Help HOW CAN I TURN OFF THE "CROSSHAIR" IN MY SERVER? Eliichong0 0 2,809 06-16-2016, 16:01
Last Post: Eliichong0
Bug Upload files to FTP server S3VDIT0 4 4,584 01-28-2016, 17:17
Last Post: S3VDIT0

Forum Jump:


Users browsing this thread:
3 Guest(s)

Forum Powered By MyBB, Theme by © 2002-2024 Melroy van den Berg.