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  if (loader->FindFile("start.dat"))
98  loader->EnableDatafile("start.dat");
99 
100  // no images or sounds in server mode:
101  loader->EnableMedia(false);
102 }
103 
105 {
106  delete admin_server;
107  delete lobby_server;
108 
109  admin_server = 0;
110  lobby_server = 0;
111 
112  // delete all the ships and stuff
113  // BEFORE getting rid of the system
114  // and weapons catalogs!
115  delete world;
116  world = 0; // don't let base class double delete the world
117 
118  Drive::Close();
121  Campaign::Close();
123  Galaxy::Close();
125  Ship::Close();
131 
132  instance = 0;
133 
134  Game::server = false;
135 }
136 
137 // +--------------------------------------------------------------------+
138 
139 bool
140 StarServer::Init(HINSTANCE hi, HINSTANCE hpi, LPSTR cmdline, int nCmdShow)
141 {
142  if (loader)
143  loader->UseFileSystem(false);
144 
145  return Game::Init(hi, hpi, cmdline, nCmdShow);
146 }
147 
148 // +--------------------------------------------------------------------+
149 
150 bool
152 {
153  if (!Game::InitGame())
154  return false;
155 
156  RandomInit();
159  SystemDesign::Initialize("sys.def");
160  WeaponDesign::Initialize("wep.def");
165 
172 
174  minutes = 0;
175 
177  if (!server_config)
178  return false;
179 
180  ::Print("\n\n\nStarshatter Server Init\n");
181  ::Print("-----------------------\n");
182  ::Print("Server Name: %s\n", (const char*) server_config->Name());
183  ::Print("Server Type: %d\n", server_config->GetGameType());
184 
185  if (server_config->GetMission().length() > 0)
186  ::Print("Server Mission: %s\n", (const char*) server_config->GetMission());
187 
188  ::Print("Lobby Server Port: %d\n", server_config->GetLobbyPort());
189  ::Print("Admin Server Port: %d\n", server_config->GetAdminPort());
190  ::Print("-----------------------\n");
191 
192  NetLobbyServer* nls = new(__FILE__,__LINE__) NetLobbyServer;
194  nas->SetServerName(server_config->Name());
195 
196  lobby_server = nls;
197  admin_server = nas;
198 
199  return true;
200 }
201 
202 // +--------------------------------------------------------------------+
203 
204 void
206 {
207  if (game_mode == m)
208  return;
209 
210  if (m == LOAD_MODE) {
211  Print(" game_mode = LOAD_MODE\n");
212  paused = true;
213  }
214 
215  else if (m == PLAY_MODE) {
216  Print(" game_mode = PLAY_MODE\n");
217 
218  if (!world) {
219  CreateWorld();
221  }
222 
223  // stand alone server should wait for players to connect
224  // before unpausing the simulation...
226  Pause(true);
227  }
228 
229  else if (m == MENU_MODE) {
230  Print(" game_mode = MENU_MODE\n");
231  paused = true;
232 
233  Sim* sim = (Sim*) world;
234 
235  if (sim)
236  sim->UnloadMission();
237  }
238 
239  game_mode = m;
240 }
241 
242 // +--------------------------------------------------------------------+
243 
244 void
245 StarServer::SetNextMission(const char* script)
246 {
247  if (lobby_server)
249 }
250 
251 // +--------------------------------------------------------------------+
252 
253 void
255 {
257 
258  // create world
259  if (!world) {
260  Sim* sim = new(__FILE__,__LINE__) Sim(0);
261  world = sim;
262  Print(" World Created.\n");
263  }
264 }
265 
266 void
268 {
269  Memory::Check();
270 
271  current_mission = 0;
272 
273  if (Campaign::GetCampaign()) {
274  current_mission = Campaign::GetCampaign()->GetMission();
275  }
276 
277  Sim* sim = (Sim*) world;
278 
279  if (sim) {
280  sim->UnloadMission();
281 
282  if (current_mission) {
283  sim->LoadMission(current_mission);
284  sim->ExecMission();
285  sim->SetTestMode(false);
286 
287  Print(" Mission Instantiated.\n");
288  }
289 
290  else {
291  Print(" *** WARNING: StarServer::InstantiateMission() - no mission selected ***\n");
292  }
293  }
294 
295  Memory::Check();
296 }
297 
298 // +--------------------------------------------------------------------+
299 
300 bool
302 {
303  if (active && paused) {
304  UpdateWorld();
305  GameState();
306  }
307 
308  else if (!active) {
309  UpdateWorld();
310  GameState();
311  Sleep(10);
312  }
313 
314  Game::GameLoop();
315  return false; // must return false to keep processing
316  // true tells the outer loop to sleep until a
317  // windows event is available
318 }
319 
320 // +--------------------------------------------------------------------+
321 
322 void
324 {
325  long new_time = real_time;
326  double delta = new_time - frame_time;
328  gui_seconds = delta * 0.001;
329 
330  if (frame_time == 0)
331  gui_seconds = 0;
332 
333  time_comp = 1;
334 
335  if (delta < max_frame_length * 1000)
336  seconds = delta * 0.001;
337 
338  frame_time = new_time;
339 
340  Galaxy* galaxy = Galaxy::GetInstance();
341  if (galaxy) galaxy->ExecFrame();
342 
343  Campaign* campaign = Campaign::GetCampaign();
344  if (campaign) campaign->ExecFrame();
345 
346  if (paused) {
347  if (world)
348  world->ExecFrame(0);
349  }
350 
351  else {
352  game_time += (DWORD) (seconds * 1000);
353 
355 
356  if (world)
358  }
359 
360  static DWORD refresh_time = 0;
361  if (RealTime() - refresh_time > 1000) {
362  refresh_time = RealTime();
363  RedrawWindow(hwnd, 0, 0, RDW_ERASE|RDW_INVALIDATE);
364  }
365 }
366 
367 // +--------------------------------------------------------------------+
368 
369 void
371 {
372  if (lobby_server) {
374 
376  paused = NetGame::NumPlayers() < 1;
377  }
378 
379  if (game_mode == MENU_MODE) {
380  Sleep(30);
381  }
382 
383  else if (game_mode == LOAD_MODE) {
384  CreateWorld();
386 
388  }
389 
390  else if (game_mode == PLAY_MODE) {
391  if (Game::GameTime() - time_mark > 60000) {
393  minutes++;
394  if (minutes > 60)
395  Print(" TIME %2d:%02d:00\n", minutes/60, minutes%60);
396  else
397  Print(" TIME %2d:00\n", minutes);
398  }
399 
400  Sleep(10);
401  }
402 
403  Memory::Check();
404 }
405 
406 // +--------------------------------------------------------------------+
407 
408 bool
410 {
411  PAINTSTRUCT paintstruct;
412  HDC hdc = BeginPaint(hwnd, &paintstruct);
413 
414  Text txt_title = title_text;
415  Text txt_mode;
416  Text txt_users = Game::GetText("server.no-users");
417  char buf[256];
418 
419  txt_title += " ";
420  txt_title += versionInfo;
421 
422  switch (game_mode) {
423  case LOAD_MODE:
424  case MENU_MODE:
425  txt_mode = Game::GetText("server.mode.lobby");
426 
427  if (lobby_server) {
428  sprintf_s(buf, Game::GetText("server.users").data(), lobby_server->NumUsers());
429  txt_users = buf;
430  }
431  break;
432 
433  case PLAY_MODE:
434  txt_mode = Game::GetText("server.mode.active");
435  if (lobby_server) {
436  sprintf_s(buf, Game::GetText("server.users-and-players").data(), lobby_server->NumUsers(), NetGame::NumPlayers());
437  }
438  else {
439  sprintf_s(buf, Game::GetText("server.players").data(), NetGame::NumPlayers());
440  }
441  txt_users = buf;
442  break;
443 
444  default:
445  txt_mode = Game::GetText("server.mode.other");
446  break;
447  }
448 
450  txt_mode += " " + Game::GetText("server.alt.persistent");
451 
452  if (paused)
453  txt_mode += " " + Game::GetText("server.alt.paused");
454 
455  TextOut(hdc, 4, 4, txt_title, txt_title.length());
456  TextOut(hdc, 4, 22, txt_mode, txt_mode.length());
457  TextOut(hdc, 4, 40, txt_users, txt_users.length());
458 
459  Sim* sim = Sim::GetSim();
460  if (sim && sim->GetMission()) {
461  Mission* mission = sim->GetMission();
462  Text txt_msn = Game::GetText("server.mission");
463  txt_msn += mission->Name();
464  TextOut(hdc, 4, 58, txt_msn, txt_msn.length());
465  }
466 
467  EndPaint(hwnd, &paintstruct);
468  return true;
469 }
470 
471 // +--------------------------------------------------------------------+
472 
473 DWORD WINAPI StarServerShutdownProc(LPVOID link)
474 {
475  StarServer* stars = (StarServer*) link;
476 
477  Sleep(3000);
478 
479  if (stars) {
480  stars->Exit();
481  return 0;
482  }
483 
484  return (DWORD) E_POINTER;
485 }
486 
487 DWORD WINAPI StarServerRestartProc(LPVOID link)
488 {
489  StarServer* stars = (StarServer*) link;
490 
491  Sleep(3000);
492 
493  if (stars) {
494  char cmdline[256];
495  strcpy_s(cmdline, "stars -server");
496 
497  STARTUPINFO s;
498  ZeroMemory(&s, sizeof(s));
499  s.cb = sizeof(s);
500 
501  PROCESS_INFORMATION pi;
502  ZeroMemory(&pi, sizeof(pi));
503 
504  CreateProcess("stars.exe", cmdline, 0, 0, 0, 0, 0, 0, &s, &pi);
505  stars->Exit();
506  CloseHandle( pi.hProcess );
507  CloseHandle( pi.hThread );
508  return 0;
509  }
510 
511  return (DWORD) E_POINTER;
512 }
513 
514 void
515 StarServer::Shutdown(bool restart)
516 {
517  DWORD thread_id = 0;
518 
519  if (restart)
520  CreateThread(0, 4096, StarServerRestartProc, (LPVOID) this, 0, &thread_id);
521  else
522  CreateThread(0, 4096, StarServerShutdownProc, (LPVOID) this, 0, &thread_id);
523 }