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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Additional shared object cache functionality for the GC
//
//=============================================================================
#ifndef GCCLIENT_SHAREDOBJECTCACHE_H
#define GCCLIENT_SHAREDOBJECTCACHE_H
#ifdef _WIN32
#pragma once
#endif
#include "sharedobjectcache.h"
class CMsgSOCacheSubscribed;
class CMsgSOCacheSubscribed_SubscribedType;
namespace GCSDK
{
/// Enumerate different events that might trigger a callback to an ISharedObjectListener
enum ESOCacheEvent
{
/// Dummy sentinel value
eSOCacheEvent_None = 0,
/// We received a our first update from the GC and are subscribed
eSOCacheEvent_Subscribed = 1,
/// We lost connection to GC or GC notified us that we are no longer subscribed.
/// Objects stay in the cache, but we no longer receive updates
eSOCacheEvent_Unsubscribed = 2,
/// We received a full update from the GC on a cache for which we were already subscribed.
/// This can happen if connectivity is lost, and then restored before we realized it was lost.
eSOCacheEvent_Resubscribed = 3,
/// We received an incremental update from the GC about specific object(s) being
/// added, updated, or removed from the cache
eSOCacheEvent_Incremental = 4,
/// A lister was added to the cache
/// @see CGCClientSharedObjectCache::AddListener
eSOCacheEvent_ListenerAdded = 5,
/// A lister was removed from the cache
/// @see CGCClientSharedObjectCache::RemoveListener
eSOCacheEvent_ListenerRemoved = 6,
};
//----------------------------------------------------------------------------
// Purpose: Allow game components to register themselves to hear about inventory
// changes when they are received from the server
//----------------------------------------------------------------------------
class ISharedObjectListener
{
public:
/// Called when a new object is created in a cache we are currently subscribed to, or when we are added
/// as a listener to a cache which already has objects in it
///
/// eEvent will be one of:
/// - eSOCacheEvent_Subscribed
/// - eSOCacheEvent_Resubscribed
/// - eSOCacheEvent_Incremental
/// - eSOCacheEvent_ListenerAdded
virtual void SOCreated( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent ) = 0;
/// Called when we are about to update objects in our cache but haven't done any of the work yet.
///
/// eEvent will be one of:
/// - eSOCacheEvent_Resubscribed
/// - eSOCacheEvent_Incremental
virtual void PreSOUpdate( const CSteamID & steamIDOwner, ESOCacheEvent eEvent ) = 0;
/// Called when an object is updated in a cache we are currently subscribed to.
///
/// eEvent will be one of:
/// - eSOCacheEvent_Resubscribed
/// - eSOCacheEvent_Incremental
virtual void SOUpdated( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent ) = 0;
/// Called when we're finished updating objects in our cache for this batch.
///
/// eEvent will be one of:
/// - eSOCacheEvent_Resubscribed
/// - eSOCacheEvent_Incremental
virtual void PostSOUpdate( const CSteamID & steamIDOwner, ESOCacheEvent eEvent ) = 0;
/// Called when an object is about to be deleted in a cache we are currently subscribed to.
/// The object will have already been removed from the cache, but is still valid.
///
/// eEvent will be one of:
/// - eSOCacheEvent_Incremental
/// - eSOCacheEvent_Resubscribed
virtual void SODestroyed( const CSteamID & steamIDOwner, const CSharedObject *pObject, ESOCacheEvent eEvent ) = 0;
/// Called to notify a listener that he is subscribed to the cache.
///
/// eEvent will be one of:
/// - eSOCacheEvent_Subscribed
/// - eSOCacheEvent_Resubscribed
/// - eSOCacheEvent_ListenerAdded
///
/// A listener is guaranteed that it will not receive incremental updates (SOCreated,
/// SOUpdated, SODestroyed) while not subscribed. (Before the SOCacheSubscribed or
/// after SOCacheUnsubscribed.) However, note that it may be possible to receive
/// an SOCacheSubscribed message while already subscribed. This can happen if the
/// GC loses and restores connection, or otherwise decides that a full update is
/// necessary.
virtual void SOCacheSubscribed( const CSteamID & steamIDOwner, ESOCacheEvent eEvent ) = 0;
/// Called to notify a listener that he is no longer subscribed to the cache.
/// if he is being removed as a listener, then he will no longer receive
/// updates. Otherwise, he might receive another SOCacheSubscribed
/// message, followed by further update notifications.
///
/// eEvent will be one of:
/// - eSOCacheEvent_Unsubscribed
/// - eSOCacheEvent_ListenerRemoved
virtual void SOCacheUnsubscribed( const CSteamID & steamIDOwner, ESOCacheEvent eEvent ) = 0;
};
//----------------------------------------------------------------------------
// Purpose: The part of a shared object cache that handles all objects of a
// single type.
//----------------------------------------------------------------------------
class CGCClientSharedObjectContext
{
public:
CGCClientSharedObjectContext( const CSteamID & steamIDOwner );
bool BAddListener( ISharedObjectListener *pListener );
bool BRemoveListener( ISharedObjectListener *pListener );
void SOCreated( const CSharedObject *pObject, ESOCacheEvent eEvent ) const;
void PreSOUpdate( GCSDK::ESOCacheEvent eEvent ) const;
void SOUpdated( const CSharedObject *pObject, ESOCacheEvent eEvent ) const;
void PostSOUpdate( GCSDK::ESOCacheEvent eEvent ) const;
void SODestroyed( const CSharedObject *pObject, ESOCacheEvent eEvent ) const;
void SOCacheSubscribed( const CSteamID & steamIDOwner, ESOCacheEvent eEvent ) const;
void SOCacheUnsubscribed( const CSteamID & steamIDOwner, ESOCacheEvent eEvent ) const;
const CSteamID & GetOwner() const { return m_steamIDOwner; }
const CUtlVector< ISharedObjectListener * > & GetListeners() const { return m_vecListeners; }
private:
CSteamID m_steamIDOwner;
CUtlVector<ISharedObjectListener *> m_vecListeners;
};
//----------------------------------------------------------------------------
// Purpose: The part of a shared object cache that handles all objects of a
// single type.
//----------------------------------------------------------------------------
class CGCClientSharedObjectTypeCache : public CSharedObjectTypeCache
{
public:
CGCClientSharedObjectTypeCache( int nTypeID, const CGCClientSharedObjectContext & context );
virtual ~CGCClientSharedObjectTypeCache();
bool BParseCacheSubscribedMsg( const CMsgSOCacheSubscribed_SubscribedType & msg, CUtlVector<CSharedObject*> &vecCreatedObjects, CUtlVector<CSharedObject*> &vecUpdatedObjects, CUtlVector<CSharedObject*> &vecObjectsToDestroy );
CSharedObject *BCreateFromMsg( const void *pvData, uint32 unSize, bool *bUpdatedExisting );
bool BDestroyFromMsg( const void *pvData, uint32 unSize );
bool BUpdateFromMsg( const void *pvData, uint32 unSize );
void RemoveAllObjects( CUtlVector<CSharedObject*> &vecObjects );
private:
const CGCClientSharedObjectContext & m_context;
};
//----------------------------------------------------------------------------
// Purpose: A cache of a bunch of shared objects of different types. This class
// is shared between clients, gameservers, and the GC and is
// responsible for sending messages from the GC to cause object
// creation/destruction/updating on the clients/gameservers.
//----------------------------------------------------------------------------
class CGCClientSharedObjectCache : public CSharedObjectCache
{
friend class CGCSOUpdateMultipleJob;
public:
CGCClientSharedObjectCache( const CSteamID & steamIDOwner = CSteamID() );
virtual ~CGCClientSharedObjectCache();
/// Have we received at least one update from the GC?
bool BIsInitialized() const { return m_bInitialized; }
/// Are we currently subscribed to updates from the GC?
bool BIsSubscribed() const { return m_bSubscribed; }
/// Who owns this cache?
virtual const CSteamID & GetOwner() const { return m_context.GetOwner(); }
/// Adds a listener interface to the object. A call to re-add
/// a listener that's already listening is harmlessly ignored.
///
/// If the cache is currently subscribed, then the listener will
/// immediately receive a SOCacheSubscribed call.
void AddListener( ISharedObjectListener *pListener );
/// Removes a listener interface on the object. Returns true
/// if we were listening and removed OK, false if we were not
/// previously listening and the call was ignored
///
/// If the cache is currently subscribed and we were listening,
/// then the listener will immediately receive a SOCacheUnsubscribed
/// call.
bool RemoveListener( ISharedObjectListener *pListener );
CGCClientSharedObjectTypeCache *FindTypeCache( int nClassID ) { return (CGCClientSharedObjectTypeCache *)FindBaseTypeCache( nClassID ); }
CGCClientSharedObjectTypeCache *CreateTypeCache( int nClassID ) { return (CGCClientSharedObjectTypeCache *)CreateBaseTypeCache( nClassID ); }
bool BParseCacheSubscribedMsg( const CMsgSOCacheSubscribed & msg );
void NotifyUnsubscribe();
void NotifyResubscribedUpToDate();
bool BCreateFromMsg( int nTypeID, const void *pvData, uint32 unSize );
bool BDestroyFromMsg( int nTypeID, const void *pvData, uint32 unSize );
bool BUpdateFromMsg( int nTypeID, const void *pvData, uint32 unSize );
#ifdef DBGFLAG_VALIDATE
virtual void Validate( CValidator &validator, const char *pchName );
#endif
protected:
private:
virtual CSharedObjectTypeCache *AllocateTypeCache( int nClassID ) const OVERRIDE { return new CGCClientSharedObjectTypeCache( nClassID, m_context ); }
CGCClientSharedObjectTypeCache *GetTypeCacheByIndex( int nIndex ) { return (CGCClientSharedObjectTypeCache *)CSharedObjectCache::GetTypeCacheByIndex( nIndex ); }
CGCClientSharedObjectContext m_context;
bool m_bInitialized;
bool m_bSubscribed;
};
} // namespace GCSDK
#endif //GCCLIENT_SHAREDOBJECTCACHE_H
|