Starshatter_Open
Open source Starshatter engine
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
StarServer.cpp
Go to the documentation of this file.
1 /* Project Starshatter 5.0
2  Destroyer Studios LLC
3  Copyright © 1997-2007. All Rights Reserved.
4 
5  SUBSYSTEM: Stars
6  FILE: StarServer.cpp
7  AUTHOR: John DiCamillo
8 
9 */
10 
11 #include "MemDebug.h"
12 
13 #include "StarServer.h"
14 #include "Campaign.h"
15 #include "CombatRoster.h"
16 #include "Galaxy.h"
17 #include "Mission.h"
18 #include "Sim.h"
19 #include "SimEvent.h"
20 #include "Ship.h"
21 #include "Contact.h"
22 #include "QuantumDrive.h"
23 #include "Power.h"
24 #include "SystemDesign.h"
25 #include "WeaponDesign.h"
26 #include "Shot.h"
27 #include "Drive.h"
28 #include "Explosion.h"
29 #include "FlightDeck.h"
30 #include "RadioMessage.h"
31 #include "RadioTraffic.h"
32 #include "Random.h"
33 #include "ModConfig.h"
34 
35 #include "NetLayer.h"
36 #include "NetGame.h"
37 #include "NetHost.h"
38 #include "NetServer.h"
39 #include "HttpServer.h"
40 #include "HttpServletExec.h"
41 #include "NetAdminServer.h"
42 #include "NetLobbyServer.h"
43 #include "NetServerConfig.h"
44 
45 #include "Token.h"
46 #include "MachineInfo.h"
47 #include "Game.h"
48 #include "Keyboard.h"
49 #include "Mouse.h"
50 #include "EventDispatch.h"
51 #include "MultiController.h"
52 #include "DataLoader.h"
53 #include "ParseUtil.h"
54 #include "Resource.h"
55 
56 // +--------------------------------------------------------------------+
57 
59 
60 static Mission* current_mission = 0;
61 static double time_til_change = 0;
62 static bool exit_latch = true;
63 
64 extern const char* versionInfo;
65 
66 // +--------------------------------------------------------------------+
67 
69 : loader(0), time_mark(0), minutes(0), game_mode(MENU_MODE),
70 admin_server(0), lobby_server(0)
71 {
72  if (!instance)
73  instance = this;
74 
75  app_name = "Starserver 5.0";
76  title_text = "Starserver";
77  palette_name = "alpha";
78 
79  Game::server = true;
80  Game::show_mouse = true;
81 
84  int loadstat = loader->EnableDatafile("shatter.dat");
85 
86  if (loadstat != DataLoader::DATAFILE_OK) {
87  const char* err_msg = loadstat == DataLoader::DATAFILE_INVALID ?
88  "The file 'shatter.dat' appears to have been damaged. Please re-install Starshatter." :
89  "Starshatter cannot open the file 'shatter.dat'. Please re-install Starshatter.";
90 
91  ::MessageBox(hwnd, err_msg, "Starshatter - Error", MB_OK);
92  ::Print(err_msg);
93  ::Print("\n\nFATAL ERROR: EXIT.");
94  exit(-1);
95  }
96 
97 #ifndef STARSHATTER_DEMO_RELEASE
98  if (loader->FindFile("start.dat"))
99  loader->EnableDatafile("start.dat");
100 #endif
101 
102  // no images or sounds in server mode:
103  loader->EnableMedia(false);
104 }
105 
107 {
108  delete admin_server;
109  delete lobby_server;
110 
111  admin_server = 0;
112  lobby_server = 0;
113 
114  // delete all the ships and stuff
115  // BEFORE getting rid of the system
116  // and weapons catalogs!
117  delete world;
118  world = 0; // don't let base class double delete the world
119 
120  Drive::Close();
123  Campaign::Close();
125  Galaxy::Close();
127  Ship::Close();
133 
134  instance = 0;
135 
136  Game::server = false;
137 }
138 
139 // +--------------------------------------------------------------------+
140 
141 bool
142 StarServer::Init(HINSTANCE hi, HINSTANCE hpi, LPSTR cmdline, int nCmdShow)
143 {
144  if (loader)
145  loader->UseFileSystem(false);
146 
147  return Game::Init(hi, hpi, cmdline, nCmdShow);
148 }
149 
150 // +--------------------------------------------------------------------+
151 
152 bool
154 {
155  if (!Game::InitGame())
156  return false;
157 
158  RandomInit();
161  SystemDesign::Initialize("sys.def");
162  WeaponDesign::Initialize("wep.def");
167 
174 
176  minutes = 0;
177 
179  if (!server_config)
180  return false;
181 
182  ::Print("\n\n\nStarshatter Server Init\n");
183  ::Print("-----------------------\n");
184  ::Print("Server Name: %s\n", (const char*) server_config->Name());
185  ::Print("Server Type: %d\n", server_config->GetGameType());
186 
187  if (server_config->GetMission().length() > 0)
188  ::Print("Server Mission: %s\n", (const char*) server_config->GetMission());
189 
190  ::Print("Lobby Server Port: %d\n", server_config->GetLobbyPort());
191  ::Print("Admin Server Port: %d\n", server_config->GetAdminPort());
192  ::Print("-----------------------\n");
193 
194  NetLobbyServer* nls = new(__FILE__,__LINE__) NetLobbyServer;
196  nas->SetServerName(server_config->Name());
197 
198  lobby_server = nls;
199  admin_server = nas;
200 
201  return true;
202 }
203 
204 // +--------------------------------------------------------------------+
205 
206 void
208 {
209  if (game_mode == m)
210  return;
211 
212  if (m == LOAD_MODE) {
213  Print(" game_mode = LOAD_MODE\n");
214  paused = true;
215  }
216 
217  else if (m == PLAY_MODE) {
218  Print(" game_mode = PLAY_MODE\n");
219 
220  if (!world) {
221  CreateWorld();
223  }
224 
225  // stand alone server should wait for players to connect
226  // before unpausing the simulation...
228  Pause(true);
229  }
230 
231  else if (m == MENU_MODE) {
232  Print(" game_mode = MENU_MODE\n");
233  paused = true;
234 
235  Sim* sim = (Sim*) world;
236 
237  if (sim)
238  sim->UnloadMission();
239  }
240 
241  game_mode = m;
242 }
243 
244 // +--------------------------------------------------------------------+
245 
246 void
247 StarServer::SetNextMission(const char* script)
248 {
249  if (lobby_server)
251 }
252 
253 // +--------------------------------------------------------------------+
254 
255 void
257 {
259 
260  // create world
261  if (!world) {
262  Sim* sim = new(__FILE__,__LINE__) Sim(0);
263  world = sim;
264  Print(" World Created.\n");
265  }
266 }
267 
268 void
270 {
271  Memory::Check();
272 
273  current_mission = 0;
274 
275  if (Campaign::GetCampaign()) {
276  current_mission = Campaign::GetCampaign()->GetMission();
277  }
278 
279  Sim* sim = (Sim*) world;
280 
281  if (sim) {
282  sim->UnloadMission();
283 
284  if (current_mission) {
285  sim->LoadMission(current_mission);
286  sim->ExecMission();
287  sim->SetTestMode(false);
288 
289  Print(" Mission Instantiated.\n");
290  }
291 
292  else {
293  Print(" *** WARNING: StarServer::InstantiateMission() - no mission selected ***\n");
294  }
295  }
296 
297  Memory::Check();
298 }
299 
300 // +--------------------------------------------------------------------+
301 
302 bool
304 {
305  if (active && paused) {
306  UpdateWorld();
307  GameState();
308  }
309 
310  else if (!active) {
311  UpdateWorld();
312  GameState();
313  Sleep(10);
314  }
315 
316  Game::GameLoop();
317  return false; // must return false to keep processing
318  // true tells the outer loop to sleep until a
319  // windows event is available
320 }
321 
322 // +--------------------------------------------------------------------+
323 
324 void
326 {
327  long new_time = real_time;
328  double delta = new_time - frame_time;
330  gui_seconds = delta * 0.001;
331 
332  if (frame_time == 0)
333  gui_seconds = 0;
334 
335  time_comp = 1;
336 
337  if (delta < max_frame_length * 1000)
338  seconds = delta * 0.001;
339 
340  frame_time = new_time;
341 
342  Galaxy* galaxy = Galaxy::GetInstance();
343  if (galaxy) galaxy->ExecFrame();
344 
345  Campaign* campaign = Campaign::GetCampaign();
346  if (campaign) campaign->ExecFrame();
347 
348  if (paused) {
349  if (world)
350  world->ExecFrame(0);
351  }
352 
353  else {
354  game_time += (DWORD) (seconds * 1000);
355 
357 
358  if (world)
360  }
361 
362  static DWORD refresh_time = 0;
363  if (RealTime() - refresh_time > 1000) {
364  refresh_time = RealTime();
365  RedrawWindow(hwnd, 0, 0, RDW_ERASE|RDW_INVALIDATE);
366  }
367 }
368 
369 // +--------------------------------------------------------------------+
370 
371 void
373 {
374  if (lobby_server) {
376 
378  paused = NetGame::NumPlayers() < 1;
379  }
380 
381  if (game_mode == MENU_MODE) {
382  Sleep(30);
383  }
384 
385  else if (game_mode == LOAD_MODE) {
386  CreateWorld();
388 
390  }
391 
392  else if (game_mode == PLAY_MODE) {
393  if (Game::GameTime() - time_mark > 60000) {
395  minutes++;
396  if (minutes > 60)
397  Print(" TIME %2d:%02d:00\n", minutes/60, minutes%60);
398  else
399  Print(" TIME %2d:00\n", minutes);
400  }
401 
402  Sleep(10);
403  }
404 
405  Memory::Check();
406 }
407 
408 // +--------------------------------------------------------------------+
409 
410 bool
412 {
413  PAINTSTRUCT paintstruct;
414  HDC hdc = BeginPaint(hwnd, &paintstruct);
415 
416  Text txt_title = title_text;
417  Text txt_mode;
418  Text txt_users = Game::GetText("server.no-users");
419  char buf[256];
420 
421  txt_title += " ";
422  txt_title += versionInfo;
423 
424  switch (game_mode) {
425  case LOAD_MODE:
426  case MENU_MODE:
427  txt_mode = Game::GetText("server.mode.lobby");
428 
429  if (lobby_server) {
430  sprintf_s(buf, Game::GetText("server.users").data(), lobby_server->NumUsers());
431  txt_users = buf;
432  }
433  break;
434 
435  case PLAY_MODE:
436  txt_mode = Game::GetText("server.mode.active");
437  if (lobby_server) {
438  sprintf_s(buf, Game::GetText("server.users-and-players").data(), lobby_server->NumUsers(), NetGame::NumPlayers());
439  }
440  else {
441  sprintf_s(buf, Game::GetText("server.players").data(), NetGame::NumPlayers());
442  }
443  txt_users = buf;
444  break;
445 
446  default:
447  txt_mode = Game::GetText("server.mode.other");
448  break;
449  }
450 
452  txt_mode += " " + Game::GetText("server.alt.persistent");
453 
454  if (paused)
455  txt_mode += " " + Game::GetText("server.alt.paused");
456 
457  TextOut(hdc, 4, 4, txt_title, txt_title.length());
458  TextOut(hdc, 4, 22, txt_mode, txt_mode.length());
459  TextOut(hdc, 4, 40, txt_users, txt_users.length());
460 
461  Sim* sim = Sim::GetSim();
462  if (sim && sim->GetMission()) {
463  Mission* mission = sim->GetMission();
464  Text txt_msn = Game::GetText("server.mission");
465  txt_msn += mission->Name();
466  TextOut(hdc, 4, 58, txt_msn, txt_msn.length());
467  }
468 
469  EndPaint(hwnd, &paintstruct);
470  return true;
471 }
472 
473 // +--------------------------------------------------------------------+
474 
475 DWORD WINAPI StarServerShutdownProc(LPVOID link)
476 {
477  StarServer* stars = (StarServer*) link;
478 
479  Sleep(3000);
480 
481  if (stars) {
482  stars->Exit();
483  return 0;
484  }
485 
486  return (DWORD) E_POINTER;
487 }
488 
489 DWORD WINAPI StarServerRestartProc(LPVOID link)
490 {
491  StarServer* stars = (StarServer*) link;
492 
493  Sleep(3000);
494 
495 #ifdef STARSHATTER_DEMO_RELEASE
496 
497  if (stars) {
498  char cmdline[256];
499  strcpy_s(cmdline, "StarDemo -server");
500 
501  STARTUPINFO s;
502  ZeroMemory(&s, sizeof(s));
503  s.cb = sizeof(s);
504 
505  PROCESS_INFORMATION pi;
506  ZeroMemory(&pi, sizeof(pi));
507 
508  CreateProcess("StarDemo.exe", cmdline, 0, 0, 0, 0, 0, 0, &s, &pi);
509  stars->Exit();
510  return 0;
511  }
512 
513 #else
514 
515  if (stars) {
516  char cmdline[256];
517  strcpy_s(cmdline, "stars -server");
518 
519  STARTUPINFO s;
520  ZeroMemory(&s, sizeof(s));
521  s.cb = sizeof(s);
522 
523  PROCESS_INFORMATION pi;
524  ZeroMemory(&pi, sizeof(pi));
525 
526  CreateProcess("stars.exe", cmdline, 0, 0, 0, 0, 0, 0, &s, &pi);
527  stars->Exit();
528  CloseHandle( pi.hProcess );
529  CloseHandle( pi.hThread );
530  return 0;
531  }
532 
533 #endif
534 
535  return (DWORD) E_POINTER;
536 }
537 
538 void
539 StarServer::Shutdown(bool restart)
540 {
541  DWORD thread_id = 0;
542 
543  if (restart)
544  CreateThread(0, 4096, StarServerRestartProc, (LPVOID) this, 0, &thread_id);
545  else
546  CreateThread(0, 4096, StarServerShutdownProc, (LPVOID) this, 0, &thread_id);
547 }