2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
6 // $Header: r:/t2repos/thief2/src/object/netman.h,v 1.31 2000/01/29 13:23:47 adurant Exp $
13 #include <propbase.h> // for sPropertyObjIter
16 F_DECLARE_INTERFACE(INetManager
);
18 ////////////////////////////////////////////////////////////
19 // NETWORKING COM INTERFACES
22 // Signature for the callback function registered for by systems that
23 // want to handle some of the messages coming in off the net.
24 typedef void (*tNetMessageParser
)(const sNetMsg_Generic
*pMsg
,
29 // Signature of a listener on the networking system. situation is whatever
30 // is happening right now; data is situation-dependent; pClientData is
31 // specified when the listener gets set up. If data is relevant, it
32 // should be a (tNetListenData *), as specified in netnotif.h.
33 typedef void (*tNetListenerCallback
)(eNetListenMsgs situation
,
37 // Signature of a callback function for SynchFlush.
38 typedef BOOL (*tNetSynchFlushCallback
)(void *pClientData
);
40 // Flags to pass to RegisterMessageParser
41 typedef enum eNetHandlerFlags_
43 // means that network statistics should be gathered assuming that
44 // the second byte of the message is a subparser index:
46 // means this message type should be allowed through even if we are
47 // in a NonNetworkLevel. Use with great care:
48 kNetAllowNonNetwork
= 1<<1,
50 typedef ulong eNetHandlerFlags
;
52 // The handle type returned from Listen()
53 typedef int tNetListenerHandle
;
55 //////////////////////////////////////////////////////////////////
57 // FOR_ALL_NET_PLAYERS(INetManager *netman, ObjID obj)
59 // A macro for looping through network players (doesn't include
60 // PlayerObject()). Can't be used in C, except at the beginning of a
61 // block due to the declaration. When the loop ends, pPlayerObj is
64 // BE CAREFUL NOT TO PUT A ';' AFTER THE "FOR_ALL_NET_PLAYERS" LINE
65 // (i.e. the null loop body).
67 #define FOR_ALL_NET_PLAYERS(pNetMan, pPlayerObj) \
68 sPropertyObjIter iter; \
69 (pNetMan)->NetPlayerIterStart(&iter); \
70 while ((pNetMan)->NetPlayerIterNext(&iter, (pPlayerObj)) || (*(pPlayerObj)=OBJ_NULL,FALSE))
72 // This version also includes the PlayerObject.
73 #define FOR_ALL_PLAYERS(pNetMan, pPlayerObj) \
74 sPropertyObjIter iter; \
75 (pNetMan)->NetPlayerIterStart(&iter); \
76 for (*(pPlayerObj) = PlayerObject(); \
77 *(pPlayerObj) != OBJ_NULL; \
78 (pNetMan)->NetPlayerIterNext(&iter, (pPlayerObj)) ? 0 : *(pPlayerObj) = OBJ_NULL)
80 // The longest allowed player name
81 #define MAX_PLAYER_NAME_LEN 32
84 #define INTERFACE INetManager
86 DECLARE_INTERFACE_( INetManager
, IUnknown
)
88 DECLARE_UNKNOWN_PURE();
90 // Is this a multi-player game, ready for sending & receiving messages.
91 STDMETHOD_(BOOL
, Networking
)(THIS
) PURE
;
93 // Is this a multi-player game, not necessarily ready for sending &
94 // receiving messages.
95 STDMETHOD_(BOOL
, IsNetworkGame
)(THIS
) PURE
;
97 // Current number of players, including yourself.
98 STDMETHOD_(ulong
, NumPlayers
)(THIS
) PURE
;
100 // PlayerNum is a number between 1 & NumPlayers that is unique
101 // for each player (1 == defaulthost). Note that the PlayerNum
102 // has one very important quality: it is consistent between loads.
103 // Therefore, it can be used with some confidence in properties.
104 STDMETHOD_(ulong
, MyPlayerNum
)(THIS
) PURE
;
105 STDMETHOD_(ulong
, ObjToPlayerNum
)(THIS_ ObjID player
) PURE
;
106 STDMETHOD_(ObjID
, PlayerNumToObj
)(THIS_ ulong player
) PURE
;
108 // Set the player's name on the network. Should be called before
110 STDMETHOD_(void, SetPlayerName
)(THIS_
const char *pName
) PURE
;
111 // Get the name of a player, given an ObjID. If the ObjID is OBJ_NULL,
112 // return the name of this player.
113 STDMETHOD_(const char *, GetPlayerName
)(THIS_ ObjID player
) PURE
;
114 // Get the net address of the specified player, as a string. If OBJ_NULL
115 // is passed in, will return the net address of the current player.
116 STDMETHOD_(const char *, GetPlayerAddress
)(THIS_ ObjID player
) PURE
;
118 // Prepare to host a networked game. pMedia gives the name of the
119 // media type to connect with; pSession gives the name of the session
120 // to establish. Both can be NULL. Returns TRUE iff the session was
121 // successfully established.
122 STDMETHOD_(BOOL
, Host
)(THIS_
const char *pMedia
, const char *pSession
)
125 // Join an existing networked game. Same params as for Host(), plus
126 // pAddress should be the IP address or DNS name of the host for this
127 // game. pAddress is mandatory. Returns TRUE iff we were able to join
129 STDMETHOD_(BOOL
, Join
)(THIS_
131 const char *pSession
,
132 const char *pAddress
) PURE
;
134 // Get/Set the timeout for this session. This is sometimes worth
135 // increasing, if a glitchy connection is sometimes causing networking
137 STDMETHOD_(ulong
, GetTimeout
)(THIS
) PURE
;
138 STDMETHOD_(void, SetTimeout
)(THIS_ ulong timeout
) PURE
;
140 // Temporarily suspend outgoing messages, except MetagameBroadcasts.
142 STDMETHOD_(void, SuspendMessaging
)(THIS
) PURE
;
143 // Is networking suspended? This method returns the stack count of
144 // Suspends. If it returns 0, messaging is not suspended.
145 STDMETHOD_(int, Suspended
)(THIS
) PURE
;
146 // Resume temporarily suspended outgoing messages.
147 STDMETHOD_(void, ResumeMessaging
)(THIS
) PURE
;
149 // Send this message to 'player'
150 // Note that you can *always* Send to yourself, even if networking is
151 // not currently turned on. This is to allow consistent host/client
152 // separation, without having to worry about whether networking is
154 STDMETHOD_(void, Send
)(THIS_
158 BOOL guaranteed
) PURE
;
160 // Send this message to all other players.
161 STDMETHOD_(void, Broadcast
)(THIS_
164 BOOL guaranteed
) PURE
;
166 // Send this message to all other player, even if we are not actually
167 // in game mode. Guaranteed is assumed for metagame messages. If
168 // always is TRUE, then this will go through even if we're in
169 // NonNetworkLevel. In that case, the message should have been
170 // created with the AllowNonNetwork flag set.
171 STDMETHOD_(void, MetagameBroadcast
)(THIS_
174 BOOL always
DEFAULT_TO(FALSE
))
177 // The host that hosts most in-world objects (i.e. not in someones
178 // inventory, nor an AI). This only works after all the
179 // initialization process is complete (Networking() is TRUE).
180 STDMETHOD_(ObjID
, DefaultHost
)(THIS
) PURE
;
181 // Is this machine the default host. Unlike DefaultHost(), this
182 // works very early in the intialization process (after
184 STDMETHOD_(BOOL
, AmDefaultHost
)(THIS
) PURE
;
185 // Get the name of the default host. This also works very early, pretty
186 // much right after we have connected. The host's name can be used as
187 // a rough-and-ready ID mechanism. Guaranteed to never return NULL.
188 STDMETHOD_(const char *, GetDefaultHostName
)(THIS
) PURE
;
190 // Game components can register a message parser for handling
191 // incoming messages.
192 STDMETHOD_(tNetMsgHandlerID
, RegisterMessageParser
)
194 tNetMessageParser parser
,
195 const char *moduleName
,
196 eNetHandlerFlags flags
,
197 void *pClientData
) PURE
;
199 ///////////////////////
201 // Routines for iterating over the network players (doesn't include
202 // the local player) (The property that this is based on is not
203 // public). No IterStop is necessary.
205 STDMETHOD_(void, NetPlayerIterStart
)
206 (THIS_ sPropertyObjIter
* iter
) CONSTFUNC PURE
;
207 STDMETHOD_(BOOL
, NetPlayerIterNext
)
208 (THIS_ sPropertyObjIter
* iter
,ObjID
* next
) CONSTFUNC PURE
;
210 // Register a listener, which will be called whenever the specified
211 // event happens. The returned handle can be passed to Unlisten().
212 STDMETHOD_(tNetListenerHandle
, Listen
)
214 tNetListenerCallback callback
,
215 eNetListenMsgs interests
,
216 void *pClientData
) PURE
;
218 // Convert to or from a global representation of an object, for
219 // when the object is not known to be hosted by either the sender
220 // or the receiver of the message.
221 STDMETHOD_(sGlobalObjID
, ToGlobalObjID
)(THIS_ ObjID obj
) PURE
;
222 STDMETHOD_(ObjID
, FromGlobalObjID
)(THIS_ sGlobalObjID
*otherObj
) PURE
;
224 // Get the ObjID of the player who sent the message currently being
225 // processed. This is available for subsystems that need to respond to
226 // a message, but are separated from the playerID by many layers of
227 // code. (In other words, it's a back-compatibility hack.)
228 // Returns PlayerObject() if we're not responding to a network message,
229 // including if we're not Networking().
230 STDMETHOD_(ObjID
, OriginatingPlayer
)(THIS
) PURE
;
232 // Begin the process of synchronizing with other network players.
233 // This should get called before any real networking, whenever we
234 // reset the object database.
235 STDMETHOD_(void, StartSynch
)(THIS
) PURE
;
237 // Declare that we are entering a level that should not be at all
238 // networked. Networking will be *entirely* suppressed until we get
239 // a NormalLevel(). Currently, this can only be switched at level
240 // transitions. Timing is critical: these calls should come between
241 // resetting the database and loading the new level, because even
242 // the beginnings of level loading can include important network
244 STDMETHOD_(void, NonNetworkLevel
)(THIS
) PURE
;
245 STDMETHOD_(void, NormalLevel
)(THIS
) PURE
;
247 // Flush all the buffers, and wait for all the other machines to
248 // do the same. This should be called after sending some message
249 // around that will cause all of the machines to do the same thing.
250 // That is, it assumes that the other machines are going into
251 // SynchFlush() at about the same time. Normally returns TRUE.
253 // IMPORTANT: THIS METHOD BLOCKS. It will wait until all of the
254 // machines are ready.
256 // Before calling SynchFlush(), you must call PreFlush() to set it up.
257 // This is necessary in order to avoid possible timing snafus.
258 // PreFlush() MUST be called immediately after receiving any
259 // network message that will lead to the SynchFlush(); it preps
260 // us to begin counting who has done their flushes. It is safe to
261 // call PreFlush() spuriously, if there is any worry about that.
263 // If a callback is specified, it will be called repeatedly while
264 // we sit and spin. It should normally return TRUE; if it ever
265 // returns FALSE, SynchFlush() will fail and return FALSE. This can
266 // be used to implement a timeout mechanism.
267 STDMETHOD_(void, PreFlush
)(THIS
) PURE
;
268 STDMETHOD_(BOOL
, SynchFlush
)(THIS_
269 tNetSynchFlushCallback callback
,
270 void *pClientData
) PURE
;
272 // Get the name of a player, given a player number. This version
273 // of GetPlayerName works relatively early in metagame, any time
274 // after you have been notified with a kNetMsgPlayerInfo message.
275 STDMETHOD_(const char *, GetPlayerNameByNum
)(THIS_
int playerNum
) PURE
;
276 // Get the net address of the specified player, as a string.
277 STDMETHOD_(const char *, GetPlayerAddressByNum
)(THIS_
int playerNum
) PURE
;
279 // End this networking session. Disconnects all clients if you are
281 STDMETHOD_(void, Leave
)(THIS
) PURE
;
283 // Stop worrying about this particular listener.
284 STDMETHOD_(void, Unlisten
)(THIS_ tNetListenerHandle handle
) PURE
;
286 // Establish a limit to the number of players allowed in the game.
287 // Any players above that limited will be rejected. Note that
288 // rejected players will still be able to successfully Join(), but
289 // they will get a kNetMsgRejected instead of kNetMsgHi. There is
290 // a non-crazy default, so this is optional, but should be set
291 // appropriately for the application.
292 STDMETHOD_(void, SetMaxPlayers
)(THIS_
int maxPlayers
) PURE
;
295 #define INetMan_Networking(p) COMCall0(p, Networking)
300 EXTERN
void NetManagerCreate(void);