Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
NetLobby.cpp
Go to the documentation of this file.
1 /* Project Starshatter 4.5
2  Destroyer Studios LLC
3  Copyright © 1997-2004. All Rights Reserved.
4 
5  SUBSYSTEM: Stars.exe
6  FILE: NetLobby.cpp
7  AUTHOR: John DiCamillo
8 
9 
10  OVERVIEW
11  ========
12  Base Class for Multiplayer Game Lobby classes
13 */
14 
15 #include "MemDebug.h"
16 #include "NetLobby.h"
17 #include "NetLobbyClient.h"
18 #include "NetLobbyServer.h"
19 #include "NetClientConfig.h"
20 #include "NetServerConfig.h"
21 #include "NetChat.h"
22 #include "NetUser.h"
23 
24 #include "NetMsg.h"
25 #include "NetData.h"
26 #include "NetLayer.h"
27 
28 #include "Player.h"
29 #include "Ship.h"
30 #include "ShipDesign.h"
31 #include "Campaign.h"
32 #include "Element.h"
33 #include "Mission.h"
34 
35 #include "NetHost.h"
36 #include "Game.h"
37 #include "Light.h"
38 #include "parseutil.h"
39 
40 // +--------------------------------------------------------------------+
41 
42 const int MAX_NET_FPS = 50;
43 const int MIN_NET_FRAME = 1000 / MAX_NET_FPS;
44 
45 const DWORD SHIP_ID_START = 0x0010;
46 const DWORD SHOT_ID_START = 0x0400;
47 
48 static NetLobby* instance = 0;
49 
50 static DWORD ship_id_key = SHIP_ID_START;
51 static DWORD shot_id_key = SHOT_ID_START;
52 
53 // +--------------------------------------------------------------------+
54 
55 NetLobby::NetLobby(bool temporary)
56 : link(0), local_user(0), last_send_time(0), active(true),
57 selected_mission(0), mission(0), status(0)
58 {
59  if (!temporary)
60  instance = this;
61 }
62 
64 {
65  if (instance == this)
66  instance = 0;
67 
68  unit_map.destroy();
69  users.destroy();
71  chat_log.destroy();
72 
73  if (local_user) {
74  delete local_user;
75  local_user = 0;
76  }
77 
78  if (link) {
79  delete link;
80  link = 0;
81  }
82 
83  mission = 0;
84 }
85 
86 // +--------------------------------------------------------------------+
87 
88 NetLobby*
90 {
91  return instance;
92 }
93 
94 // +--------------------------------------------------------------------+
95 
96 void
98 {
99  Send();
100  Recv();
101 }
102 
103 void
105 {
106  NetMsg* msg = link->GetMessage();
107 
108  while (msg) {
109  if (active) {
110  NetPeer* peer = link->FindPeer(msg->NetID());
111 
112  static char buffer[256];
113  char* text = 0;
114 
115  if (msg->Length() > 2) {
116  if (msg->Length() < 250) {
117  ZeroMemory(buffer, sizeof(buffer));
118  CopyMemory(buffer, msg->Data()+2, msg->Length()-2);
119  text = buffer;
120  }
121  else if (msg->Length() < 1024 * 1024) {
122  text = new(__FILE__,__LINE__) char[msg->Length()];
123  ZeroMemory(text, msg->Length());
124  CopyMemory(text, msg->Data()+2, msg->Length()-2);
125  }
126  }
127 
128  switch (msg->Type()) {
129  case NET_LOBBY_PING: DoPing(peer, text); break;
130  case NET_LOBBY_SERVER_INFO: DoServerInfo(peer, text); break;
131  case NET_LOBBY_SERVER_MODS: DoServerMods(peer, text); break;
132  case NET_LOBBY_LOGIN: DoLogin(peer, text); break;
133  case NET_LOBBY_LOGOUT: DoLogout(peer, text); break;
134 
135  case NET_LOBBY_AUTH_USER: DoAuthUser(peer, text); break;
136  case NET_LOBBY_USER_AUTH: DoUserAuth(peer, text); break;
137 
138  case NET_LOBBY_CHAT: DoChat(peer, text); break;
139  case NET_LOBBY_USER_LIST: DoUserList(peer, text); break;
140  case NET_LOBBY_BAN_USER: DoBanUser(peer, text); break;
141  case NET_LOBBY_MISSION_LIST: DoMissionList(peer, text); break;
142  case NET_LOBBY_MISSION_SELECT: DoMissionSelect(peer, text); break;
143  case NET_LOBBY_MISSION_DATA: DoMissionData(peer, text); break;
144  case NET_LOBBY_UNIT_LIST: DoUnitList(peer, text); break;
145  case NET_LOBBY_MAP_UNIT: DoMapUnit(peer, text); break;
146  case NET_LOBBY_GAME_START: DoGameStart(peer, text); break;
147  case NET_LOBBY_GAME_STOP: DoGameStop(peer, text); break;
148  case NET_LOBBY_EXIT: DoExit(peer, text); break;
149  }
150 
151  if (text && text != buffer)
152  delete [] text;
153  }
154 
155  delete msg;
156  msg = link->GetMessage();
157  }
158 }
159 
160 // +--------------------------------------------------------------------+
161 
162 void
164 {
165 }
166 
167 // +-------------------------------------------------------------------+
168 
169 DWORD
171 {
172  if (link)
173  return link->GetLag();
174 
175  return 0;
176 }
177 
178 // +-------------------------------------------------------------------+
179 
180 void
182 {
183  if (user != local_user) {
184  if (local_user) {
185  delete local_user;
186  local_user = 0;
187  }
188 
189  if (user) {
190  local_user = user;
191  local_user->SetHost(true);
192  }
193  }
194 }
195 
196 void
198 {
199 }
200 
201 void
203 {
204  if (user) {
205  if (user != local_user && !users.contains(user)) {
206  users.append(user);
207  Print("NetLobby User Logged In - name: '%s' id: %d host: %d\n",
208  user->Name().data(),
209  user->GetNetID(),
210  user->IsHost());
211  }
212  }
213 }
214 
215 void
217 {
218  if (user) {
219  if (user == local_user)
220  local_user = 0;
221 
222  else
223  users.remove(user);
224 
225  UnmapUnit(user->Name());
226 
227  Print("NetLobby User Logged Out - name: '%s' id: %d host: %d\n",
228  user->Name().data(),
229  user->GetNetID(),
230  user->IsHost());
231 
232  user->SetHost(false);
233  delete user;
234  }
235 }
236 
237 int
239 {
240  int num = 0;
241 
242  if (local_user)
243  num = 1;
244 
245  num += users.size();
246 
247  return num;
248 }
249 
250 NetUser*
252 {
253  for (int i = 0; i < users.size(); i++) {
254  NetUser* u = users[i];
255 
256  if (u->IsHost())
257  return u;
258  }
259 
260  return 0;
261 }
262 
263 bool
265 {
266  bool host = false;
267 
268  if (local_user && local_user->IsHost())
269  host = true;
270 
271  for (int i = 0; i < users.size() && !host; i++) {
272  if (users[i]->IsHost())
273  host = true;
274  }
275 
277  host = true;
278 
279  return host;
280 }
281 
282 bool
284 {
285  bool ok = false;
286 
287  if (user && users.contains(user)) {
288  if (host && !HasHost()) {
289  user->SetHost(true);
290  ok = true;
291  }
292  else if (!host) {
293  user->SetHost(false);
294  ok = true;
295  }
296  }
297 
298  return ok;
299 }
300 
301 NetUser*
303 {
304  return local_user;
305 }
306 
309 {
310  return users;
311 }
312 
315 {
316  return server_mods;
317 }
318 
319 NetUser*
321 {
322  for (int i = 0; i < users.size(); i++) {
323  NetUser* u = users[i];
324  if (u->GetAddress().IPAddr() == addr.IPAddr())
325  return u;
326  }
327 
328  return 0;
329 }
330 
331 NetUser*
332 NetLobby::FindUserByName(const char* name)
333 {
334  if (local_user && !_stricmp(local_user->Name(), name))
335  return local_user;
336 
337  for (int i = 0; i < users.size(); i++) {
338  NetUser* u = users[i];
339  if (!_stricmp(u->Name(), name))
340  return u;
341  }
342 
343  return 0;
344 }
345 
346 NetUser*
348 {
349  for (int i = 0; i < users.size(); i++) {
350  NetUser* u = users[i];
351  if (u->GetNetID() == id)
352  return u;
353  }
354 
355  return 0;
356 }
357 
358 // +--------------------------------------------------------------------+
359 
360 void
362 {
363  params.destroy();
364 
365  BlockReader reader(msg.data(), msg.length());
366  Scanner lexer(&reader);
367 
368  Token name = lexer.Get();
369 
370  while (name.type() == Token::AlphaIdent) {
371  Token value = lexer.Get();
372  if (value.type() != Token::EOT) {
373  Text val = value.symbol();
374 
375  if (val[0] == '"' && val[val.length()-1] == '"') {
376  val = val.substring(1, val.length()-2);
377  }
378 
379  NetLobbyParam* param = new(__FILE__,__LINE__) NetLobbyParam(name.symbol(), val);
380  params.append(param);
381 
382  name = lexer.Get();
383  }
384 
385  else {
386  name = Token(Token::EOT);
387  }
388  }
389 }
390 
391 // +--------------------------------------------------------------------+
392 
393 bool
395 {
396  Sleep(500);
397  return false;
398 }
399 
400 // +-------------------------------------------------------------------+
401 
402 void
403 NetLobby::AddChat(NetUser* user, const char* msg, bool route)
404 {
405  if (user && msg && *msg)
406  chat_log.append(new(__FILE__,__LINE__) NetChatEntry(user, msg));
407 }
408 
411 {
412  return chat_log;
413 }
414 
415 void
417 {
418  chat_log.destroy();
419 }
420 
421 // +-------------------------------------------------------------------+
422 
425 {
426  return campaigns;
427 }
428 
429 // +-------------------------------------------------------------------+
430 
431 void
433 {
434  if (elem)
435  unit_map.append(new(__FILE__,__LINE__) NetUnitEntry(elem, index));
436 }
437 
440 {
441  return unit_map;
442 }
443 
444 void
446 {
447  unit_map.destroy();
448 }
449 
450 void
451 NetLobby::MapUnit(int n, const char* user, bool lock)
452 {
453  if (n >= 0 && n < unit_map.size()) {
454  NetUnitEntry* unit = unit_map[n];
455 
456  if (!lock && unit->GetLocked())
457  return;
458 
459  if (user && *user) {
460  for (int i = 0; i < unit_map.size(); i++) {
461  NetUnitEntry* u = unit_map[i];
462  if (u->GetUserName() == user) {
463  if (!lock && u->GetLocked()) return;
464  u->SetUserName("");
465  }
466  }
467  }
468 
469  unit->SetUserName(user);
470  unit->SetLock(lock);
471  }
472 }
473 
474 void
475 NetLobby::UnmapUnit(const char* user)
476 {
477  if (user && *user) {
478  for (int i = 0; i < unit_map.size(); i++) {
479  NetUnitEntry* u = unit_map[i];
480  if (u->GetUserName() == user) {
481  u->SetUserName("");
482  u->SetLock(false);
483  return;
484  }
485  }
486  }
487 }
488 
489 bool
490 NetLobby::IsMapped(const char* user)
491 {
492  if (user && *user) {
493  for (int i = 0; i < unit_map.size(); i++) {
494  NetUnitEntry* u = unit_map[i];
495  if (u->GetUserName() == user) {
496  return true;
497  }
498  }
499  }
500 
501  return false;
502 }
503 
504 // +--------------------------------------------------------------------+
505 
506 void
508 {
509  if (selected_mission != id) {
510  selected_mission = id;
511  ClearUnitMap();
512 
513  int mission_id = selected_mission;
514  int campaign_id = -1;
515  Campaign* campaign = 0;
516  mission = 0;
517 
518  campaign_id = mission_id >> NET_CAMPAIGN_SHIFT;
519  mission_id = mission_id & NET_MISSION_MASK;
520 
522  while (++c_iter) {
523  campaign = c_iter.value();
524 
525  if (campaign->GetCampaignId() == campaign_id) {
526  mission = campaign->GetMission(mission_id);
527  break;
528  }
529  }
530 
531  if (campaign && mission) {
532  Campaign::SelectCampaign(campaign->Name());
533  campaign->SetMissionId(mission_id);
534 
536  while (++iter) {
537  MissionElement* elem = iter.value();
538 
539  if (elem->IsPlayable()) {
540  if (elem->Count() == 1) {
541  AddUnitMap(elem);
542  }
543  else {
544  for (int i = 0; i < elem->Count(); i++)
545  AddUnitMap(elem, i+1);
546  }
547  }
548  }
549  }
550 
551  else {
552  selected_mission = 0;
553  mission = 0;
554  }
555  }
556 }
557 
558 // +--------------------------------------------------------------------+
559 
560 bool
562 {
563  if (instance)
564  return instance->IsClient();
565  return false;
566 }
567 
568 bool
570 {
571  if (instance)
572  return instance->IsServer();
573  return false;
574 }
575 
576 // +-------------------------------------------------------------------+
577 // +-------------------------------------------------------------------+
578 // +-------------------------------------------------------------------+
579 
581 : index(n), lock(false), lives(1), hull(100), role(0)
582 {
583  if (e) {
584  elem = e->Name();
585  iff = e->GetIFF();
586 
587  if (e->GetDesign())
588  design = e->GetDesign()->name;
589  }
590 }
591 
592 NetUnitEntry::NetUnitEntry(const char* e, const char* d, int i, int n)
593 : elem(e), design(d), iff(i), index(n), lock(false), lives(1),
594 hull(100), role(0)
595 { }
596 
598 { }
599 
600 Text
602 {
603  if (elem) {
604  static char buffer[1024];
605 
606  sprintf_s(buffer, "name \"%s\" index %d design \"%s\" iff %d user \"%s\" lives %d hull %d role %d lock %d ",
607  elem.data(),
608  index,
609  design.data(),
610  iff,
611  user.data(),
612  lives,
613  hull,
614  role,
615  lock);
616 
617  return buffer;
618  }
619 
620  return "name \"Not Found\" ";
621 }
622 
623 // +--------------------------------------------------------------------+
624 // +--------------------------------------------------------------------+
625 // +--------------------------------------------------------------------+
626 
628 : nplayers(0), hosted(0), status(0), port(0), gameport(0), save(false), ping_time(0)
629 { }
630