aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/client/client_thinklist.h
blob: 3d3e174485aab6eab34909ac5c28dd36f0103edb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================//

#ifndef CLIENT_THINKLIST_H
#define CLIENT_THINKLIST_H
#ifdef _WIN32
#pragma once
#endif


#include "igamesystem.h"
#include "utllinkedlist.h"
#include "cliententitylist.h"
#include "iclientthinkable.h"
#include "utlrbtree.h"


#define CLIENT_THINK_ALWAYS	-1293
#define CLIENT_THINK_NEVER	-1


#define INVALID_THINK_HANDLE ClientThinkList()->GetInvalidThinkHandle()


class CClientThinkList : public IGameSystemPerFrame
{
public:

							CClientThinkList();
	virtual					~CClientThinkList();
	
	virtual char const		*Name() { return "CClientThinkList"; }
	virtual bool			IsPerFrame() { return true; }

	// Set the next time at which you want to think. You can also use
	// one of the CLIENT_THINK_ defines.
	void					SetNextClientThink( ClientEntityHandle_t hEnt, float nextTime );
	
	// Remove an entity from the think list.
	void					RemoveThinkable( ClientEntityHandle_t hEnt );

	// Use to initialize your think handles in IClientThinkables.
	ClientThinkHandle_t		GetInvalidThinkHandle();

	// This is called after network updating and before rendering.
	void					PerformThinkFunctions();

	// Call this to destroy a thinkable object - deletes the object post think.
	void					AddToDeleteList( ClientEntityHandle_t hEnt );	
	void					RemoveFromDeleteList( ClientEntityHandle_t hEnt );

// IClientSystem implementation.
public:

	virtual bool Init();
	virtual void PostInit() {};
	virtual void Shutdown();
	virtual void LevelInitPreEntity();
	virtual void LevelInitPostEntity() {}
	virtual void LevelShutdownPreEntity();
	virtual void LevelShutdownPostEntity();
	virtual void PreRender();
	virtual void PostRender() { }
	virtual void Update( float frametime );
	virtual void OnSave() {}
	virtual void OnRestore() {}
	virtual void SafeRemoveIfDesired() {}

private:
	struct ThinkEntry_t
	{
		ClientEntityHandle_t	m_hEnt;
		float					m_flNextClientThink;
		float					m_flLastClientThink;
		int						m_nIterEnum;
	};

	struct ThinkListChanges_t
	{
		ClientEntityHandle_t	m_hEnt;
		ClientThinkHandle_t		m_hThink;
		float					m_flNextTime;
	};

// Internal stuff.
private:
	void			SetNextClientThink( ClientThinkHandle_t hThink, float nextTime );
	void			RemoveThinkable( ClientThinkHandle_t hThink );
	void			PerformThinkFunction( ThinkEntry_t *pEntry, float curtime );
	ThinkEntry_t*	GetThinkEntry( ClientThinkHandle_t hThink );
	void			CleanUpDeleteList();

	// Add entity to frame think list
	void			AddEntityToFrameThinkList( ThinkEntry_t *pEntry, bool bAlwaysChain, int &nCount, ThinkEntry_t **ppFrameThinkList );

private:
	CUtlLinkedList<ThinkEntry_t, unsigned short>	m_ThinkEntries;

	CUtlVector<ClientEntityHandle_t>	m_aDeleteList;
	CUtlVector<ThinkListChanges_t>		m_aChangeList;

	// Makes sure the entries are thinked once per frame in the face of hierarchy
	int m_nIterEnum;
	bool m_bInThinkLoop;
};


// -------------------------------------------------------------------------------- //
// Inlines.
// -------------------------------------------------------------------------------- //

inline ClientThinkHandle_t CClientThinkList::GetInvalidThinkHandle()
{
	return (ClientThinkHandle_t)(uintp)m_ThinkEntries.InvalidIndex();
}


inline CClientThinkList::ThinkEntry_t* CClientThinkList::GetThinkEntry( ClientThinkHandle_t hThink )
{
	return &m_ThinkEntries[ (unsigned long)hThink ];
}


inline CClientThinkList* ClientThinkList()
{
	extern CClientThinkList g_ClientThinkList;
	return &g_ClientThinkList;
}


#endif // CLIENT_THINKLIST_H