Example #1
0
        void HandleProcess(Process game, GameOffsets offsets, CancellationTokenSource cts)
        {
            Debug.WriteLine("HandleProcess " + game.ProcessName);

            var state = new GameState(game, offsets);

            this.InitGameState(state);

            var profiler = Stopwatch.StartNew();

            while (!game.HasExited && !cts.IsCancellationRequested)
            {
                // iteration must never take longer than 1 tick

                this.UpdateGameState(state);

                this.CheckGameState(state);

                state.UpdateCount++;
                TimedTraceListener.Instance.UpdateCount = state.UpdateCount;

                if (profiler.ElapsedMilliseconds >= TARGET_UPDATE_RATE)
                {
                    Debug.WriteLine("**** update iteration took too long: " + profiler.ElapsedMilliseconds);
                }
                //var sleep = Stopwatch.StartNew();
                //MapTimesForm.Instance.Text = profiler.Elapsed.ToString();
                Thread.Sleep(Math.Max(TARGET_UPDATE_RATE - (int)profiler.ElapsedMilliseconds, 1));
                //MapTimesForm.Instance.Text = sleep.Elapsed.ToString();
                profiler.Restart();
            }
        }
Example #2
0
        public GameState(Process game, GameOffsets offsets)
        {
            this.GameProcess = game;
            this.GameOffsets = offsets;

            RawTickCount             = new ValueWatcher <int>(0);
            PlayerViewEntityIndex    = new ValueWatcher <int>(0);
            PlayerFlags              = new ValueWatcher <FL>(new FL());
            PlayerPosition           = new ValueWatcher <Vector3f>(new Vector3f());
            PlayerParentEntityHandle = new ValueWatcher <int>(0);
            HostState   = new ValueWatcher <HostState>(SourceSplit.HostState.NewGame);
            SignOnState = new ValueWatcher <SignOnState>(SourceSplit.SignOnState.None);
            ServerState = new ValueWatcher <ServerState>(SourceSplit.ServerState.Dead);
        }
Example #3
0
        void UpdateGameState(GameState state)
        {
            Process     game    = state.GameProcess;
            GameOffsets offsets = state.GameOffsets;

            // update all the stuff that doesn't depend on the signon state
            game.ReadInt32(offsets.TickCountPtr, out state.RawTickCount);
            game.ReadFloat(offsets.IntervalPerTickPtr, out state.IntervalPerTick);

            state.PrevSignOnState = state.SignOnState;
            game.ReadEnum32(offsets.SignOnStatePtr, out state.SignOnState);

            state.PrevHostState = state.HostState;
            game.ReadEnum32(offsets.HostStatePtr, out state.HostState);

            bool firstTick = false;

            // update the stuff that's only valid during signon state full
            if (state.SignOnState == SignOnState.Full)
            {
                // if signon state just became full (where demos start timing from)
                if (state.SignOnState != state.PrevSignOnState)
                {
                    firstTick = true;

                    // start rebasing from this tick
                    state.TickBase = state.RawTickCount;
                    Debug.WriteLine("rebasing ticks from " + state.TickBase);

                    // player was just spawned, get it's ptr
                    state.PlayerEntInfo = state.GetEntInfoByIndex(GameState.ENT_INDEX_PLAYER);

                    // update map name
                    state.GameProcess.ReadASCIIString(state.GameOffsets.CurMapPtr, out state.CurrentMap, 64);
                }

                // update time and rebase it against the first signon state full tick
                state.TickCount = state.RawTickCount - state.TickBase;
                state.TickTime  = state.TickCount * state.IntervalPerTick;
                TimedTraceListener.Instance.TickCount = state.TickCount;

                // update player related things
                if (state.PlayerEntInfo.EntityPtr != IntPtr.Zero && state.GameSupport != null)
                {
                    // flags
                    if (state.GameSupport.RequiredProperties.HasFlag(PlayerProperties.Flags))
                    {
                        state.PrevPlayerFlags = state.PlayerFlags;
                        game.ReadEnum32(state.PlayerEntInfo.EntityPtr + offsets.BaseEntityFlagsOffset, out state.PlayerFlags);
                    }

                    // position
                    if (state.GameSupport.RequiredProperties.HasFlag(PlayerProperties.Position))
                    {
                        state.PrevPlayerPosition = state.PlayerPosition;
                        game.ReadVector3f(state.PlayerEntInfo.EntityPtr + offsets.BaseEntityAbsOriginOffset, out state.PlayerPosition);
                    }

                    // view entity
                    if (state.GameSupport.RequiredProperties.HasFlag(PlayerProperties.ViewEntity))
                    {
                        const int ENT_ENTRY_MASK = 0x7FF;

                        state.PrevPlayerViewEntityIndex = state.PlayerViewEntityIndex;
                        int viewEntityHandle; // EHANDLE
                        game.ReadInt32(state.PlayerEntInfo.EntityPtr + offsets.BasePlayerViewEntity, out viewEntityHandle);
                        state.PlayerViewEntityIndex = viewEntityHandle == -1
                            ? GameState.ENT_INDEX_PLAYER
                            : viewEntityHandle & ENT_ENTRY_MASK;
                    }

                    // parent entity
                    if (state.GameSupport.RequiredProperties.HasFlag(PlayerProperties.ParentEntity))
                    {
                        state.PrevPlayerParentEntityHandle = state.PlayerParentEntityHandle; // EHANDLE
                        game.ReadInt32(state.PlayerEntInfo.EntityPtr + offsets.BaseEntityParentHandleOffset, out state.PlayerParentEntityHandle);
                    }

                    // if it's the first tick, don't use stuff from the previous map
                    if (firstTick)
                    {
                        state.PrevPlayerFlags              = state.PlayerFlags;
                        state.PrevPlayerPosition           = state.PlayerPosition;
                        state.PrevPlayerViewEntityIndex    = state.PlayerViewEntityIndex;
                        state.PrevPlayerParentEntityHandle = state.PlayerParentEntityHandle;
                    }
                }
            } // if (state.SignOnState == SignOnState.Full)
        }
Example #4
0
        // TODO: log fails
        bool TryGetGameProcess(out Process p, out GameOffsets offsets)
        {
#if DEBUG
            var sw = Stopwatch.StartNew();
#endif

            string[] procs = _settings.GameProcesses.Select(x => x.ToLower().Replace(".exe", String.Empty)).ToArray();
            p       = Process.GetProcesses().FirstOrDefault(x => procs.Contains(x.ProcessName.ToLower()));
            offsets = new GameOffsets();

            if (p == null || p.HasExited || Util.IsVACProtectedProcess(p))
            {
                return(false);
            }

            // process is up, check if engine and server are both loaded yet
            ProcessModule engine = p.Modules.Cast <ProcessModule>().FirstOrDefault(x => x.ModuleName.ToLower() == "engine.dll");
            ProcessModule server = p.Modules.Cast <ProcessModule>().FirstOrDefault(x => x.ModuleName.ToLower() == "server.dll");

            if (engine == null || server == null)
            {
                return(false);
            }

            // required engine stuff
            var scanner = new SignatureScanner(p, engine.BaseAddress, engine.ModuleMemorySize);

            if ((offsets.CurMapPtr = scanner.Scan(_curMapTarget)) == IntPtr.Zero ||
                (offsets.CurTimePtr = scanner.Scan(_curTimeTarget)) == IntPtr.Zero ||
                (offsets.GameDirPtr = scanner.Scan(_gameDirTarget)) == IntPtr.Zero ||
                (offsets.HostStatePtr = scanner.Scan(_hostStateTarget)) == IntPtr.Zero)
            {
                return(false);
            }

            if ((offsets.SignOnStatePtr = scanner.Scan(_signOnStateTarget1)) == IntPtr.Zero &&
                (offsets.SignOnStatePtr = scanner.Scan(_signOnStateTarget2)) == IntPtr.Zero)
            {
                return(false);
            }

            // required server stuff
            var serverScanner = new SignatureScanner(p, server.BaseAddress, server.ModuleMemorySize);

            if ((offsets.GlobalEntityListPtr = serverScanner.Scan(_globalEntityListTarget)) == IntPtr.Zero)
            {
                return(false);
            }

            // entity offsets
            if (!GetBaseEntityMemberOffset("m_fFlags", p, serverScanner, out offsets.BaseEntityFlagsOffset) ||
                !GetBaseEntityMemberOffset("m_vecAbsOrigin", p, serverScanner, out offsets.BaseEntityAbsOriginOffset) ||
                !GetBaseEntityMemberOffset("m_iName", p, serverScanner, out offsets.BaseEntityTargetNameOffset) ||
                !GetBaseEntityMemberOffset("m_hViewEntity", p, serverScanner, out offsets.BasePlayerViewEntity))
            {
                return(false);
            }

            // find m_pParent offset. the string "m_pParent" occurs more than once so we have to do something else
            // in old engine it's right before m_iParentAttachment. in new engine it's right before m_nTransmitStateOwnedCounter
            // TODO: test on all engines
            int tmp;
            if (!GetBaseEntityMemberOffset("m_nTransmitStateOwnedCounter", p, serverScanner, out tmp))
            {
                if (!GetBaseEntityMemberOffset("m_iParentAttachment", p, serverScanner, out tmp))
                {
                    return(false);
                }
                tmp -= 4; // sizeof m_iParentAttachment
            }
            tmp -= 4;     // sizeof m_nTransmitStateOwnedCounter (4 aligned byte)
            offsets.BaseEntityParentHandleOffset = tmp;

            Debug.WriteLine("CBaseServer::m_szMapname ptr = 0x" + offsets.CurMapPtr.ToString("X"));
            Debug.WriteLine("CGlobalVarsBase::curtime ptr = 0x" + offsets.CurTimePtr.ToString("X"));
            Debug.WriteLine("CBaseClientState::m_nSignonState ptr = 0x" + offsets.SignOnStatePtr.ToString("X"));
            Debug.WriteLine("CBaseEntityList::(CEntInfo)m_EntPtrArray ptr = 0x" + offsets.GlobalEntityListPtr.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_fFlags offset = 0x" + offsets.BaseEntityFlagsOffset.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_vecAbsOrigin offset = 0x" + offsets.BaseEntityAbsOriginOffset.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_iName offset = 0x" + offsets.BaseEntityTargetNameOffset.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_pParent offset = 0x" + offsets.BaseEntityParentHandleOffset.ToString("X"));
            Debug.WriteLine("CBasePlayer::m_hViewEntity offset = 0x" + offsets.BasePlayerViewEntity.ToString("X"));

#if DEBUG
            Debug.WriteLine("TryGetGameProcess took: " + sw.Elapsed);
#endif

            return(true);
        }
Example #5
0
        // TODO: log fails
        bool TryGetGameProcess(out Process p, out GameOffsets offsets)
        {
            #if DEBUG
            var sw = Stopwatch.StartNew();
            #endif

            string[] procs = _settings.GameProcesses.Select(x => x.ToLower().Replace(".exe", String.Empty)).ToArray();
            p = Process.GetProcesses().FirstOrDefault(x => procs.Contains(x.ProcessName.ToLower()));
            offsets = new GameOffsets();

            if (p == null || p.HasExited || Util.IsVACProtectedProcess(p))
                return false;

            // process is up, check if engine and server are both loaded yet
            ProcessModule engine = p.Modules.Cast<ProcessModule>().FirstOrDefault(x => x.ModuleName.ToLower() == "engine.dll");
            ProcessModule server = p.Modules.Cast<ProcessModule>().FirstOrDefault(x => x.ModuleName.ToLower() == "server.dll");

            if (engine == null || server == null)
                return false;

            // required engine stuff
            var scanner = new SignatureScanner(p, engine.BaseAddress, engine.ModuleMemorySize);

            if ((offsets.CurMapPtr = scanner.Scan(_curMapTarget)) == IntPtr.Zero
                || (offsets.CurTimePtr = scanner.Scan(_curTimeTarget)) == IntPtr.Zero
                || (offsets.GameDirPtr = scanner.Scan(_gameDirTarget)) == IntPtr.Zero
                || (offsets.HostStatePtr = scanner.Scan(_hostStateTarget)) == IntPtr.Zero)
                return false;

            if ((offsets.SignOnStatePtr = scanner.Scan(_signOnStateTarget1)) == IntPtr.Zero
                && (offsets.SignOnStatePtr = scanner.Scan(_signOnStateTarget2)) == IntPtr.Zero)
                return false;

            // required server stuff
            var serverScanner = new SignatureScanner(p, server.BaseAddress, server.ModuleMemorySize);

            if ((offsets.GlobalEntityListPtr = serverScanner.Scan(_globalEntityListTarget)) == IntPtr.Zero)
                return false;

            // entity offsets
            if ( !GetBaseEntityMemberOffset("m_fFlags", p, serverScanner, out offsets.BaseEntityFlagsOffset)
                || !GetBaseEntityMemberOffset("m_vecAbsOrigin", p, serverScanner, out offsets.BaseEntityAbsOriginOffset)
                || !GetBaseEntityMemberOffset("m_iName", p, serverScanner, out offsets.BaseEntityTargetNameOffset)
                || !GetBaseEntityMemberOffset("m_hViewEntity", p, serverScanner, out offsets.BasePlayerViewEntity))
                return false;

            // find m_pParent offset. the string "m_pParent" occurs more than once so we have to do something else
            // in old engine it's right before m_iParentAttachment. in new engine it's right before m_nTransmitStateOwnedCounter
            // TODO: test on all engines
            int tmp;
            if (!GetBaseEntityMemberOffset("m_nTransmitStateOwnedCounter", p, serverScanner, out tmp))
            {
                if (!GetBaseEntityMemberOffset("m_iParentAttachment", p, serverScanner, out tmp))
                    return false;
                tmp -= 4; // sizeof m_iParentAttachment
            }
            tmp -= 4; // sizeof m_nTransmitStateOwnedCounter (4 aligned byte)
            offsets.BaseEntityParentHandleOffset = tmp;

            Debug.WriteLine("CBaseServer::m_szMapname ptr = 0x" + offsets.CurMapPtr.ToString("X"));
            Debug.WriteLine("CGlobalVarsBase::curtime ptr = 0x" + offsets.CurTimePtr.ToString("X"));
            Debug.WriteLine("CBaseClientState::m_nSignonState ptr = 0x" + offsets.SignOnStatePtr.ToString("X"));
            Debug.WriteLine("CBaseEntityList::(CEntInfo)m_EntPtrArray ptr = 0x" + offsets.GlobalEntityListPtr.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_fFlags offset = 0x" + offsets.BaseEntityFlagsOffset.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_vecAbsOrigin offset = 0x" + offsets.BaseEntityAbsOriginOffset.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_iName offset = 0x" + offsets.BaseEntityTargetNameOffset.ToString("X"));
            Debug.WriteLine("CBaseEntity::m_pParent offset = 0x" + offsets.BaseEntityParentHandleOffset.ToString("X"));
            Debug.WriteLine("CBasePlayer::m_hViewEntity offset = 0x" + offsets.BasePlayerViewEntity.ToString("X"));

            #if DEBUG
            Debug.WriteLine("TryGetGameProcess took: " + sw.Elapsed);
            #endif

            return true;
        }
Example #6
0
        void HandleProcess(Process game, GameOffsets offsets, CancellationTokenSource cts)
        {
            Debug.WriteLine("HandleProcess " + game.ProcessName);

            var state = new GameState(game, offsets);
            this.InitGameState(state);

            var profiler = Stopwatch.StartNew();
            while (!game.HasExited && !cts.IsCancellationRequested)
            {
                // iteration must never take longer than 1 tick

                this.UpdateGameState(state);

                this.CheckGameState(state);

                state.UpdateCount++;
                TimedTraceListener.Instance.UpdateCount = state.UpdateCount;

                if (profiler.ElapsedMilliseconds >= TARGET_UPDATE_RATE)
                    Debug.WriteLine("**** update iteration took too long: " + profiler.ElapsedMilliseconds);
                //var sleep = Stopwatch.StartNew();
                //MapTimesForm.Instance.Text = profiler.Elapsed.ToString();
                Thread.Sleep(Math.Max(TARGET_UPDATE_RATE - (int)profiler.ElapsedMilliseconds, 1));
                //MapTimesForm.Instance.Text = sleep.Elapsed.ToString();
                profiler.Restart();
            }
        }
Example #7
0
 public GameState(Process game, GameOffsets offsets)
 {
     this.GameProcess = game;
     this.GameOffsets = offsets;
 }
Example #8
0
 public GameState(Process game, GameOffsets offsets)
 {
     this.GameProcess = game;
     this.GameOffsets = offsets;
 }