Rise
The Vieneo Province
Networking.cpp
Go to the documentation of this file.
1 #include "Networking.h"
2 #include <RakNetStatistics.h>
3 #include "PacketPriority.h"
4 
5 #include "GameClass.h"
7 #include "DXUT.h"
9 #include "RakSleep.h"
11 #include "MathUtilities.h"
12 
13 #include <io.h>
14 
16 {
17  game = g;
18 
19  serverC = RakNet::UNASSIGNED_SYSTEM_ADDRESS;
20  patchbytes = 0L;
21  rcvdbytes = 0L;
22  retryconnect = 0;
23  p = nullptr;
24 
25  rakPeer = RakNet::RakPeerInterface::GetInstance();
26 
27  RakNet::SocketDescriptor socketdesc;
28  socketdesc.port = 0; // anything else locks more than one client from connecting
29  socketdesc.hostAddress[0] = 0; // INADDR_ANY
30  const RakNet::StartupResult startupResult = rakPeer->Startup(1, &socketdesc, 1);
31  if (startupResult != RakNet::StartupResult::RAKNET_STARTED)
32  game->logger->Log("NetFactory->Startup", Logger::Level::Fatal);
33 
34  Trace("Connecting to server...");
35  const RakNet::ConnectionAttemptResult connectResult = Connect();
36  if (connectResult != RakNet::ConnectionAttemptResult::CONNECTION_ATTEMPT_STARTED)
37  DXUT_ERR_MSGBOX(L"NetFactory->Connect", NULL);
39 }
40 
41 void Networking::Trace(const char* msg, Logger::Level severity) const
42 {
43  char newmsg[999];
44  sprintf_s(newmsg, sizeof newmsg, "NETWORK: %s", msg);
45  game->logger->Log(newmsg, severity);
46 }
47 
49 {
50  if (!rakPeer)
51  return;
52 
53  Trace("Shutting down network factory...");
54  rakPeer->Shutdown(5000);
55  RakNet::RakPeerInterface::DestroyInstance(rakPeer);
56  rakPeer = nullptr;
57 }
58 
59 void Networking::SendToServer(void* pData, DWORD dwSize, bool bGuaranteed, PacketOrdering order) const
60 {
61  char newdata[999];
62 #pragma warning( disable : 4309 )
63  newdata[0] = static_cast<char>(ID_USER_PACKET_ENUM);
64 #pragma warning( disable : 4309 )
65  memcpy_s(&newdata[1], 998, pData, dwSize);
66 
67  PacketReliability reliability;
68  if (bGuaranteed)
69  {
70  if (order == ORDERING_NONE)
71  reliability = RELIABLE;
72  else
73  reliability = RELIABLE_ORDERED;
74  }
75  else
76  {
77  reliability = UNRELIABLE;
78  }
79 
80  rakPeer->Send(newdata, dwSize + 1, MEDIUM_PRIORITY, reliability, ORDERING_NONE, serverC, false);
81 }
82 
83 void Networking::SendTelemetry(SClientPacketNew* pData) const
84 {
85  char newdata[999];
86 #pragma warning( disable : 4309 )
87  newdata[0] = static_cast<char>(ID_USER_PACKET_TELEMETRY);
88 #pragma warning( disable : 4309 )
89  memcpy_s(&newdata[1], 998, pData, sizeof SClientPacketNew);
90  rakPeer->Send(newdata, sizeof SClientPacketNew + 1, MEDIUM_PRIORITY, UNRELIABLE_SEQUENCED, ORDERING_TELEMETRY, serverC, false);
91 }
92 
93 void Networking::SendErrorReport(SErrorPacket* pData) const
94 {
95  if (!rakPeer)
96  return;
97 
98  char newdata[999];
99 #pragma warning( disable : 4309 )
100  newdata[0] = static_cast<char>(ID_USER_PACKET_ERROR);
101 #pragma warning( disable : 4309 )
102  memcpy_s(&newdata[1], 998, pData, sizeof SErrorPacket);
103  rakPeer->Send(newdata, sizeof SErrorPacket + 1, IMMEDIATE_PRIORITY, RELIABLE_ORDERED, ORDERING_ERRORS, serverC, false);
104 }
105 
107 {
108  return rakPeer->GetLastPing(serverC);
109 }
110 
111 void Networking::SendEvent(EventType eventType, float extent) const
112 {
113  if (playerships[0].simulator)
114  return;
115 
116  SClientPacket outpacket; // NOLINT
117  outpacket.type = 12; // events
118  outpacket.f_x = extent;
119  outpacket.f_y = 0.0f; // NULL
120  outpacket.f_w = static_cast<float>(eventType);
121  outpacket.f_z = 0.0f; // NULL
122  SendToServer(&outpacket, sizeof(SClientPacket), true);
123 }
124 
125 void Networking::SendTraceFile(const char* fileContents) const
126 {
127  if (!rakPeer)
128  return;
129 
130  const int length = strlen(fileContents);
131  char* newdata = new char[length + 2];
132  newdata[0] = static_cast<char>(ID_USER_PACKET_LOGFILE);
133  memcpy_s(&newdata[1], length, fileContents, length);
134  newdata[length + 1] = 0; // include null terminator
135  rakPeer->Send(newdata, length + 2, IMMEDIATE_PRIORITY, RELIABLE, ORDERING_NONE, serverC, false);
136  RakSleep(0);
137  SAFE_DELETE_ARRAY(newdata);
138 }
139 
140 void Networking::SendScreenShot(const char* fileContents, int length) const
141 {
142  if (!rakPeer)
143  return;
144 
145  rakPeer->Send(fileContents, length, LOW_PRIORITY, RELIABLE, ORDERING_NONE, serverC, false);
146 }
147 
148 RakNet::RakNetStatistics* Networking::GetStatistics() const
149 {
150  return rakPeer->GetStatistics(serverC);
151 }
152 
153 RakNet::ConnectionAttemptResult Networking::Connect() const
154 {
155  return rakPeer->Connect(hostC, portC, nullptr, 0, nullptr);
156 }
157 
158 void Networking::Flush() const
159 {
160  RakNet::RakNetStatistics* stats;
161  do
162  {
163  RakSleep(0);
164  stats = rakPeer->GetStatistics(serverC);
165  } while (stats->messageInSendBuffer[0] || stats->messageInSendBuffer[1] || stats->messageInSendBuffer[2] || stats->messageInSendBuffer[3]);
166 }
167 
168 void Networking::RequestVerbiage(const int helpId) const
169 {
170  SClientPacket outpacket;
171  outpacket.type = 40; // request help verbiage
172  outpacket.f_x = static_cast<float>(helpId);
173  outpacket.f_y = static_cast<float>(game->config.language);
174  outpacket.f_z = 0.0f; // NULL
175  outpacket.f_w = 0.0f; // NULL
176  SendToServer(&outpacket, sizeof(SClientPacket), true);
177 }
178 
179 void Networking::SendChatMessage(unsigned char channel, unsigned char player, const WCHAR* message) const
180 {
181  char newdata[TRANSMIT_CHAT_SIZE * 2 + 3]; // for WCHAR to char, and type, and channel
182 #pragma warning( disable : 4309 )
183  newdata[0] = static_cast<char>(ID_USER_PACKET_CHAT);
184 #pragma warning( disable : 4309 )
185  newdata[1] = channel;
186  newdata[2] = player; // obviously the server is going to know who we are but to regurgitate this we need the server to update the player ID
187  memcpy_s(&newdata[3], TRANSMIT_CHAT_SIZE * 2, message, (wcslen(message) + 1) * 2); // include null and convert to char
188  rakPeer->Send(newdata, (static_cast<int>(wcslen(message)) + 1) * 2 + 3, MEDIUM_PRIORITY, RELIABLE_ORDERED, ORDERING_CHAT, serverC, false);
189 }
190 
192 {
193  char msg[199];
194  sprintf_s(msg, sizeof msg, "Networking::FrameMove (displaystage %i)", displaystage);
195  game->logger->AddToCallStack(msg);
196 
197  if (!rakPeer)
198  return;
199 
200  p = rakPeer->Receive();
201  while (p)
202  {
203  switch (displaystage)
204  {
206  switch (p->data[0])
207  {
208  case ID_CONNECTION_REQUEST_ACCEPTED:
209  {
210  Trace("Connected!");
211  serverC = p->systemAddress;
212  rakPeer->SetOccasionalPing(true);
213  rakPeer->SetTimeoutTime(30000, RakNet::UNASSIGNED_SYSTEM_ADDRESS);
214  }
215  break;
216 
217  case ID_USER_PACKET_ENUM:
218  {
219  switch (p->length - 1)
220  {
221  case sizeof SServerPacket:
222  {
223  SServerPacket datapacket;
224  memcpy_s(&datapacket, sizeof SServerPacket, &p->data[1], p->length - 1);
225  switch (datapacket.type)
226  {
227  case 0: // Configuration packet received
228  {
230 
231  const float average_ping = static_cast<float>(rakPeer->GetAveragePing(serverC)) * 0.001f;
232  g_UniverseTime = datapacket.f_x + average_ping;
233  DXUTGetGlobalTimer()->Reset();
234  DXUTGetGlobalTimer()->GetElapsedTime();
235  Trace("Configuration received!");
236  sprintf_s(msg, sizeof msg, " g_UniverseTime: %f", datapacket.f_x);
237  Trace(msg);
238  sprintf_s(msg, sizeof msg, " ping to server: %f", average_ping);
239  Trace(msg);
240  sprintf_s(msg, sizeof msg, " ping to client: %f", datapacket.f_y);
241  Trace(msg);
242  sprintf_s(msg, sizeof msg, " adjustment: %f", average_ping);
243  Trace(msg);
244  sprintf_s(msg, sizeof msg, " f_Uphours: %f", datapacket.f_z);
245  Trace(msg);
246 
247  f_Uphours = datapacket.f_z;
248 
249  game->GUI->ourplayerC = datapacket.array;
250  ourcockpit.ourplyrC = datapacket.array;
251 
252  sprintf_s(msg, sizeof msg, "Our slot number: %i", ourcockpit.ourplyrC);
253  Trace(msg);
254 
255  sprintf_s(msg, sizeof msg, "Requesting MOTD language: %i", game->config.language);
256  Trace(msg);
257 
259  }
260  break;
261 
262  case 3: // Conclusion (version too old) moved here in 2.2.16.6 on 6/26/2020
263  {
264  if (datapacket.f_y == 4.0f) // incompatible version
265  {
266  if (!game->GUI->isSteam)
267  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_LOGIN_VERSIONTOOOLD].c_str(), game->GUI->strings[L_SPLASH_VALIDATINGINSTALL].c_str(), MB_ICONHAND | MB_OK);
268  else
269  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_LOGIN_VERSIONTOOOLDSTEAM].c_str(), game->GUI->strings[L_SPLASH_VALIDATINGINSTALL].c_str(), MB_ICONHAND | MB_OK);
270  PostQuitMessage(0);
271  }
272  else
273  {
274  sprintf_s(msg, sizeof msg, "Unexpected conclusion Y type: %.0f", datapacket.f_y);
275  Trace(msg, Logger::Level::Warn);
276  }
277  }
278  break;
279 
280  case 34: // ignore radio transmissions in Splash
281  break;
282 
283  case 38: // patch information
284  {
285  patchbytes = static_cast<unsigned long>(datapacket.f_x);
286  rcvdbytes = 0L;
287  sprintf_s(msg, sizeof msg, "STATUS_SPLASH autopatcher expecting total bytes: %i", patchbytes);
288  Trace(msg);
289  }
290  break;
291 
292  default:
293  {
294  sprintf_s(msg, sizeof msg, "STATUS_SPLASH unknown SServerPacket packet type: %i", datapacket.type);
295  Trace(msg, Logger::Level::Warn);
296  }
297  break;
298  }
299  }
300  break;
301 
302  case sizeof SPacketBig:
303  {
304  SPacketBig datapacket;
305  memcpy_s(&datapacket, sizeof SPacketBig, &p->data[1], p->length - 1);
306  switch (datapacket.type)
307  {
308  case 14: // dock data ignored?
309  break;
310 
311  case 29: // patching finished
312  Trace("Patching finished!");
313 
315  rcvdbytes = patchbytes = 0L;
316 
317  strcpy_s(game->config.patchdate, 24, datapacket.msg);
319 
320  char newpatchdate[99];
321  sprintf_s(newpatchdate, sizeof newpatchdate, "STATUS_SPLASH autopatcher patchdate.txt now: %s", game->config.patchdate);
322  Trace(newpatchdate);
323  break;
324 
325  default:
326  sprintf_s(msg, sizeof msg, "STATUS_SPLASH unknown SPacketBig packet type: %i", datapacket.type);
327  Trace(msg, Logger::Level::Warn);
328  break;
329  }
330  break;
331  }
332 
333  default:
334  sprintf_s(msg, sizeof msg, "STATUS_SPLASH unknown packet length: %i", p->length - 1);
335  Trace(msg, Logger::Level::Warn);
336  break;
337  }
338  break;
339  }
340 
341  case ID_CONNECTION_ATTEMPT_FAILED:
342  case ID_NO_FREE_INCOMING_CONNECTIONS:
343  {
344  const RakNet::ConnectionAttemptResult result = Connect();
345  if (result != RakNet::ConnectionAttemptResult::CONNECTION_ATTEMPT_STARTED)
346  game->logger->Log("NetFactory->Connect", Logger::Level::Fatal);
347  else
348  {
349  if (p->data[0] == ID_CONNECTION_ATTEMPT_FAILED)
350  Trace("Retrying (ID_CONNECTION_ATTEMPT_FAILED)...", Logger::Level::Info);
351  else
352  Trace("Retrying (ID_NO_FREE_INCOMING_CONNECTIONS)...", Logger::Level::Info);
353  }
354  retryconnect++;
355  break;
356  }
357 
358  case ID_USER_PACKET_PATCH:
359  {
360  // 0 position is patch packet identifier
361 
362  // 1 position is action 0 is delete, 1 is add, 2 is modify
363  const char actionCode = p->data[1];
364 
365  // 2 position is pathAndFileName, 128 total length
366  char pathAndFileName[128];
367  memcpy_s(pathAndFileName, 128, &p->data[2], 128);
368 
369  // 3 position starts the data to length - 130
370  const int fileLength = p->length - 130;
371  rcvdbytes += fileLength;
372 
373  sprintf_s(msg, sizeof msg, "STATUS_SPLASH autopatcher action %i bytes %i: %s", actionCode, fileLength, pathAndFileName);
374  Trace(msg);
375 
376  if (actionCode == 0)
377  {
378  const int result = _unlink(pathAndFileName);
379  if (result == -1 && errno != ENOENT) // if it isn't there we got no problem!
380  {
381  sprintf_s(msg, sizeof msg, "Autopatcher could not delete file \"%s\": %i", pathAndFileName, errno);
382  Trace(msg, Logger::Level::Error);
383  }
384  }
385  else if (actionCode == 1)
386  {
387  for (size_t endIndex = 1; endIndex < strlen(pathAndFileName); endIndex++)
388  {
389  if (pathAndFileName[endIndex] == '\\')
390  {
391  pathAndFileName[endIndex] = 0;
392  _mkdir(pathAndFileName);
393  pathAndFileName[endIndex] = '\\';
394  }
395  }
396 
397  int file;
398  _sopen_s(&file, pathAndFileName, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY | _O_SEQUENTIAL, _SH_SECURE, _S_IWRITE);
399  if (file == -1)
400  {
401  switch (errno)
402  {
403  case EACCES: sprintf_s(msg, sizeof msg, "Autopatcher could not create file \"%s\": EACCES", pathAndFileName); break;
404  case EEXIST: sprintf_s(msg, sizeof msg, "Autopatcher could not create file \"%s\": EEXIST", pathAndFileName); break;
405  case EINVAL: sprintf_s(msg, sizeof msg, "Autopatcher could not create file \"%s\": EINVAL", pathAndFileName); break;
406  case EMFILE: sprintf_s(msg, sizeof msg, "Autopatcher could not create file \"%s\": EMFILE", pathAndFileName); break;
407  case ENOENT: sprintf_s(msg, sizeof msg, "Autopatcher could not create file \"%s\": ENOENT", pathAndFileName); break;
408  default: sprintf_s(msg, sizeof msg, "Autopatcher could not create file \"%s\": %i", pathAndFileName, errno);
409  }
410  Trace(msg, Logger::Level::Fatal);
411  }
412  _write(file, &p->data[130], fileLength);
413  _close(file);
414  }
415  else if (actionCode == 2)
416  {
417  bool restart = false;
418  if (strcmp(pathAndFileName, "Rise.exe") == 0)
419  {
420  restart = true;
421  strcpy_s(pathAndFileName, 128, "Rise1.exe");
422  }
423  if (strcmp(pathAndFileName, "steam_api.dll") == 0)
424  {
425  restart = true;
426  strcpy_s(pathAndFileName, 128, "steam_api1.dll");
427  }
428  if (strcmp(pathAndFileName, "bass.dll") == 0)
429  {
430  restart = true;
431  strcpy_s(pathAndFileName, 128, "bass1.dll");
432  }
433  if (strcmp(pathAndFileName, "bass_fx.dll") == 0)
434  {
435  restart = true;
436  strcpy_s(pathAndFileName, 128, "bass_fx1.dll");
437  }
438  if (strcmp(pathAndFileName, "RakNet.dll") == 0)
439  {
440  restart = true;
441  strcpy_s(pathAndFileName, 128, "RakNet1.dll");
442  }
443  if (strcmp(pathAndFileName, "discord-rpc.dll") == 0)
444  {
445  restart = true;
446  strcpy_s(pathAndFileName, 128, "discord-rpc1.dll");
447  }
448  if (strcmp(pathAndFileName, "FreeTrackClient.dll") == 0)
449  {
450  restart = true;
451  strcpy_s(pathAndFileName, 128, "FreeTrackClient1.dll");
452  }
453 
454  for (size_t endIndex = 1; endIndex < strlen(pathAndFileName); endIndex++)
455  {
456  if (pathAndFileName[endIndex] == '\\')
457  {
458  pathAndFileName[endIndex] = 0;
459  _mkdir(pathAndFileName);
460  pathAndFileName[endIndex] = '\\';
461  }
462  }
463 
464  int file;
465  _sopen_s(&file, pathAndFileName, _O_WRONLY | _O_CREAT | _O_TRUNC | _O_BINARY | _O_SEQUENTIAL, _SH_SECURE, _S_IWRITE);
466  if (file == -1)
467  {
468  if (errno == EACCES)
469  sprintf_s(msg, sizeof msg, "Autopatcher could not modify file \"%s\": Permission denied", pathAndFileName);
470  else
471  sprintf_s(msg, sizeof msg, "Autopatcher could not modify file \"%s\": %i", pathAndFileName, errno);
472  Trace(msg, Logger::Level::Fatal);
473  }
474  _write(file, &p->data[130], fileLength);
475  _close(file);
476 
477  if (restart)
478  {
479  Trace("The Rise binaries have been updated and must be restarted!");
480  MessageBox(DXUTGetHWND(), L"The Rise binaries have been updated and must be restarted!", L"Finished Patching", MB_ICONINFORMATION | MB_OK);
481 #ifndef _DEBUG
482  PostQuitMessage(0);
483 #endif
484  }
485  }
486  break;
487  }
488 
489  case ID_USER_PACKET_HELP:
490  {
491  Trace("Got MOTD through ID_USER_PACKET_HELP!");
492  //WCHAR chat[510];
493  WCHAR newchat[510];
494  memcpy_s(newchat, sizeof newchat, &p->data[1], sizeof newchat);
495  //size_t index = 0;
496  //for (size_t i = 0; i < wcslen(chat); i++)
497  //{
498  // if (i < wcslen(chat) - 1 && chat[i] == 92 && chat[i + 1] == 'n')
499  // {
500  // newchat[index++] = L' '; // no idea why I have to do this on some but not all \n coming from server lol
501  // newchat[index++] = L'\n'; // no idea why I have to do this on some but not all \n coming from server lol
502  // newchat[index++] = L' '; // no idea why I have to do this on some but not all \n coming from server lol
503  // i++;
504  // }
505  // else if (chat[i] == '\n')
506  // {
507  // newchat[index++] = L' ';
508  // newchat[index++] = L'\n';
509  // newchat[index++] = L' ';
510  // }
511  // else
512  // {
513  // newchat[index++] = chat[i];
514  // }
515  //}
516  //newchat[index] = 0;
517 
518  HRESULT hr;
519 
520  // MOTD text
521  game->GUI->motd.clear();
522  size_t startOfLine = 0;
523  size_t lastGoodSpaceIndex = 0;
524  for (size_t i = 0; i < wcslen(newchat) - startOfLine; i++)
525  {
526  size_t i1 = wcslen(newchat) - startOfLine - 1;
527  // taking substring from startOfLine for X characters
528  WCHAR tempStr[510];
529  wcscpy_s(tempStr, 510, &newchat[startOfLine]);
530  // truncate
531  tempStr[i + 1] = 0;
532  // render and calculate
533  RECT rect = RECT();
534  try
535  {
536  V(game->GUI->g_pFont->DrawTextW(game->GUI->g_pTextSprite, tempStr, -1, &rect, DT_CALCRECT, 0xFFFFFFFF));
537  }
538  catch (...)
539  {
540  // apparently we get an exception trying to calculate "\n "?
541  }
542  // evaluate
543  if (rect.right < 210 && i != i1)
544  {
545  if (tempStr[i] == L' ' || tempStr[i] == L'!' || tempStr[i] == L'。' || tempStr[i] == L',')
546  lastGoodSpaceIndex = i;
547  }
548  else
549  {
550  // back up to lastGoodSpaceIndex and push
551  if (lastGoodSpaceIndex != 0 && i != i1)
552  {
553  if (tempStr[lastGoodSpaceIndex] == L' ')
554  tempStr[lastGoodSpaceIndex] = 0;
555  else
556  tempStr[lastGoodSpaceIndex + 1] = 0;
557  }
558  game->GUI->motd.emplace_back(tempStr);
559  if (i == i1)
560  break;
561  if (lastGoodSpaceIndex != 0)
562  startOfLine += lastGoodSpaceIndex + 1;
563  else
564  startOfLine += wcslen(tempStr) + 1;
565  i = 0;
566  lastGoodSpaceIndex = 0;
567  }
568  }
569  }
570  break;
571 
572  case ID_RAKVOICE_DATA: // Ignoring in Splash page
573  break;
574 
575  default:
576  {
577  sprintf_s(msg, sizeof msg, "STATUS_SPLASH unknown packet ID: %i", p->data[0]);
578  Trace(msg, Logger::Level::Warn);
579  break;
580  }
581  }
582  break;
583 
585  {
586  switch (p->data[0])
587  {
588  case ID_USER_PACKET_ENUM:
589  {
590  switch (p->length - 1)
591  {
592  case sizeof SServerPacket:
593  {
594  SServerPacket datapacket;
595  memcpy_s(&datapacket, sizeof SServerPacket, &p->data[1], p->length - 1);
596  switch (datapacket.type)
597  {
598  case 24: // Result of immigration request
599  {
600  game->GUI->rxbuffer += p->length;
601  // 24=immigration x=validationtest(0=newhandle,1=referral), y=validationpass1fail0, z=, array=(0=done! 1=handle taken 2=can'tfindreferral, 3=updated, 4=validation)
602  if (datapacket.array == 0 || datapacket.array == 3)
603  {
604  char* newdata = new char[game->GUI->pBuffer->GetBufferSize() + 1];
605  newdata[0] = static_cast<char>(ID_USER_PACKET_AVATAR);
606  // include null and convert to char
607  memcpy_s(&newdata[1], game->GUI->pBuffer->GetBufferSize(), game->GUI->pBuffer->GetBufferPointer(), game->GUI->pBuffer->GetBufferSize());
608  rakPeer->Send(newdata, game->GUI->pBuffer->GetBufferSize() + 1, MEDIUM_PRIORITY, RELIABLE, ORDERING_NONE, serverC, false);
609  game->GUI->txbuffer += static_cast<short>(game->GUI->pBuffer->GetBufferSize()) + 1;
610  SAFE_DELETE_ARRAY(newdata);
611  SAFE_RELEASE(game->GUI->pBuffer);
612  game->UpdateTrackedResource("pBuffer", 3);
613 
614  game->sound->loopintro = false;
615  game->GUI->immigrationPassed = true;
616 
617  if (datapacket.array == 0)
618  {
619  SClientPacket outpacket;
620  outpacket.type = 3; // Request completion of data (online player data and immigration info)
621  outpacket.f_x = 0.0f; // NULL
622  outpacket.f_y = 0.0f; // NULL
623  outpacket.f_z = 0.0f; // NULL
624  outpacket.f_w = 0.0f; // NULL
625  SendToServer(&outpacket, sizeof(SClientPacket), true);
626 
627  strcpy_s(game->GUI->player[game->GUI->ourplayerC].callsign, sizeof game->GUI->player[game->GUI->ourplayerC].callsign, game->config.defaultuser);
628  }
629  }
630  else if (datapacket.array == 4) // validator
631  {
632  game->GUI->rxbuffer += p->length;
633  if (datapacket.f_x == 0.0f) // handle
634  {
635  if (datapacket.f_y == 1.0f)
636  game->GUI->handleValid = 2; // passed
637  else
638  {
639  game->GUI->handleValid = 0; // failed
640  if (datapacket.f_z == 1.0f)
641  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_RESERVED].c_str(), game->GUI->strings[L_MESSAGE_CALLSIGN].c_str(), MB_ICONHAND | MB_OK);
642  else if (datapacket.f_z == 2.0f)
643  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_VULGARITY].c_str(), game->GUI->strings[L_MESSAGE_CALLSIGN].c_str(), MB_ICONHAND | MB_OK);
644  else if (datapacket.f_z == 3.0f)
645  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_DUPLICATE].c_str(), game->GUI->strings[L_MESSAGE_CALLSIGN].c_str(), MB_ICONHAND | MB_OK);
646  else if (datapacket.f_z == 4.0f)
647  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_SPACES].c_str(), game->GUI->strings[L_MESSAGE_CALLSIGN].c_str(), MB_ICONHAND | MB_OK);
648  else if (datapacket.f_z == 6.0f)
649  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_SYMBOLS].c_str(), game->GUI->strings[L_MESSAGE_CALLSIGN].c_str(), MB_ICONHAND | MB_OK);
650  else if (datapacket.f_z == 9.0f)
651  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_TOOSHORT].c_str(), game->GUI->strings[L_MESSAGE_CALLSIGN].c_str(), MB_ICONHAND | MB_OK);
652  }
653  }
654  else if (datapacket.f_x == 1.0f) // referral
655  {
656  if (datapacket.f_y == 1.0f)
657  game->GUI->referralValid = 2; // passed
658  else
659  {
660  game->GUI->referralValid = 0; // failed
661  if (datapacket.f_z == 5.0f)
662  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_NOTFOUND].c_str(), game->GUI->strings[L_MESSAGE_REFERRAL].c_str(), MB_ICONHAND | MB_OK);
663  }
664  }
665  else if (datapacket.f_x == 2.0f) // charname
666  {
667  if (datapacket.f_y == 1.0f)
668  game->GUI->charnameValid = 2; // passed
669  else
670  {
671  game->GUI->charnameValid = 0; // failed
672  if (datapacket.f_z == 2.0f)
673  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_VULGARITY].c_str(), game->GUI->strings[L_MESSAGE_CHARNAME].c_str(), MB_ICONHAND | MB_OK);
674  else if (datapacket.f_z == 3.0f)
675  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_DUPLICATE].c_str(), game->GUI->strings[L_MESSAGE_CHARNAME].c_str(), MB_ICONHAND | MB_OK);
676  else if (datapacket.f_z == 6.0f)
677  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_SYMBOLS].c_str(), game->GUI->strings[L_MESSAGE_CHARNAME].c_str(), MB_ICONHAND | MB_OK);
678  else if (datapacket.f_z == 7.0f)
679  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_NUMBERS].c_str(), game->GUI->strings[L_MESSAGE_CALLSIGN].c_str(), MB_ICONHAND | MB_OK);
680  }
681  }
682  else if (datapacket.f_x == 3.0f) // email
683  {
684  if (datapacket.f_y == 1.0f)
685  game->GUI->emailValid = 2; // passed
686  else
687  {
688  game->GUI->emailValid = 0; // failed
689  if (datapacket.f_z == 3.0f)
690  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_DUPLICATE].c_str(), game->GUI->strings[L_MESSAGE_EMAIL].c_str(), MB_ICONHAND | MB_OK);
691  else if (datapacket.f_z == 8.0f)
692  MessageBoxW(DXUTGetHWND(), game->GUI->strings[L_MESSAGE_INVALID].c_str(), game->GUI->strings[L_MESSAGE_EMAIL].c_str(), MB_ICONHAND | MB_OK);
693  }
694  }
695  }
696  else
697  {
699  }
700  break;
701  }
702  default:
704  break;
705  }
706  break;
707  }
708 
709  case sizeof SPacketBig:
710  {
711  // ignoring a reference frame packet for now
712  SPacketBig datapacket;
713  memcpy_s(&datapacket, sizeof(SPacketBig), &p->data[1], p->length - 1);
714  switch (datapacket.type)
715  {
716  case 12: // Suggested name
717  {
718  game->GUI->rxbuffer += p->length;
719  game->GUI->g_HUD.GetButton(IDC_SUGGEST)->SetEnabled(true);
720  game->GUI->charnameValid = 2;
721  game->GUI->g_HUD.GetRadioButton(IDC_MALE)->SetChecked(datapacket.array == 1);
722  game->GUI->g_HUD.GetRadioButton(IDC_FEMALE)->SetChecked(datapacket.array == 2);
723  game->GUI->SexChangeOperation(datapacket.array);
724  WCHAR str[199];
725  swprintf_s(str, 199, L"%S", datapacket.msg);
726  game->GUI->g_HUD.GetEditBox(IDC_CHARNAME)->SetText(str);
727  game->GUI->g_HUD.GetEditBox(IDC_SIGNATUREHINT)->SetText(str);
728  break;
729  }
730  case 13: // Suggested callsign
731  {
732  game->GUI->rxbuffer += p->length;
733  game->GUI->handleValid = 2;
734  WCHAR str[199];
735  swprintf_s(str, 199, L"%S", datapacket.msg);
736  game->GUI->g_HUD.GetEditBox(IDC_HANDLE)->SetText(str);
737  break;
738  }
739  default:
740  {
742  //char msg[199];
743  //sprintf_s(msg, 199, "STATUS_CREATE unknown SPacketBig packet type: %i", datapacket.type);
744  //Trace(msg, Logger::Level::Warn);
745  break;
746  }
747  }
748  break;
749  }
750  default:
752  break;
753  }
754  }
755  break;
756 
757  default:
759  break;
760  }
761  }
762  break;
763 
765  //if (p->data[0] == ID_USER_PACKET_HELP)
766  //{
767  // Trace("Got verbiage in STATUS_LOGIN phase!");
768  // WCHAR chat[512];
769  // memcpy_s(chat, 1024, &p->data[1], 1024); // 512 * 2 bytes
770  // for (size_t i = 0; i < wcslen(chat) - 1; i++)
771  // {
772  // if (chat[i] == 92 && chat[i + 1] == 'n')
773  // {
774  // chat[i] = L' ';
775  // chat[i + 1] = L'\n'; // no idea why I have to do this on some but not all \n coming from server lol
776  // }
777  // }
778  // MessageBox(DXUTGetHWND(), chat, L"Login Response", MB_OK);
779  //}
780  //else
782  break;
783 
784  default: // loading and game
786  break;
787  }
788 
789  rakPeer->DeallocatePacket(p);
790  p = rakPeer->Receive();
791  }
792 
793  RakSleep(0); // must be here to give the RakNet thread a chance to do work
794 
795  if (displaystage == GameState::STATUS_GAME)
796  {
797  for (UINT i = 0; i < game->bus->commandStream.size(); i++)
798  {
799  const Command command = game->bus->commandStream.at(i);
800 
801  if (command.name == "UnloadCargoBay")
802  {
803  SClientPacket outpacket = SClientPacket();
804  outpacket.type = 18; // cargo ops
805  outpacket.f_x = 0.0f; // unload
806  outpacket.f_y = static_cast<float>(command.ivalues[0]); // bay number
807  outpacket.f_z = 0.0f; // NULL
808  outpacket.f_w = static_cast<float>(command.ivalues[1]); // vehicle id
809  game->networking->SendToServer(&outpacket, sizeof(SClientPacket), true);
810 
811  game->bus->commandStream.erase(game->bus->commandStream.begin() + i);
812  }
813  else if (command.name == "UpdateMfdPage")
814  {
815  game->networking->SendEvent(EventType::EVENT_SELECT_PAGE, static_cast<float>(command.ivalues[0]));
816  // @todo we aren't sending ivalues[1] which is the "last page"
817 
818  game->bus->commandStream.erase(game->bus->commandStream.begin() + i);
819  }
820  }
821  }
822 
823  sprintf_s(msg, sizeof msg, "Networking::FrameMove END (displaystage %i)", displaystage);
824  game->logger->AddToCallStack(msg);
825 }
826 
827 void Networking::RakNetMessageHandler(RakNet::Packet* packet) const
828 {
829  char msg[999];
830 
831  sprintf_s(msg, sizeof msg, "Networking::RakNetMessageHandler (type %i)", packet->data[0]);
832  game->logger->AddToCallStack(msg);
833 
834  switch (packet->data[0])
835  {
836  case ID_RAKVOICE_DATA:
837  {
838  //if (ourcockpit.gndvehicle)
839  // break;
840  if (ourcockpit.power <= 0.5f)
841  break;
842  if (playerships[0].simulator)
843  break;
844  if (game->GUI->player[ourcockpit.ourplyrC].frame == REF_INANOTHER ||
845  (game->GUI->player[ourcockpit.ourplyrC].frame == REF_BUILDING && game->GUI->player[ourcockpit.ourplyrC].bldg == 2)) // vehicle or control tower
846  {
847  Trace("Received audio data! Playing...", Logger::Level::Info);
848  game->sound->PlayAudioData(&p->data[1], p->length - 1);
849  }
850  }
851  break;
852 
853  case ID_USER_PACKET_SUPER: // when we log in, when we get in and out of ships, loaded and unloaded in bays, in and out of interiors
854  {
855  Trace("ID_USER_PACKET_SUPER received!");
856 
857  deathinhibit = 5.0f;
858 
859  SSuperPacket datapacket = SSuperPacket();
860  memcpy_s(&datapacket, sizeof SSuperPacket, &packet->data[1], packet->length - 1);
861 
862  sprintf_s(msg, sizeof msg, " Our reference %i!", datapacket.reference);
863  Trace(msg);
864  playerships[0].reference = datapacket.reference;
865  if (datapacket.reference >= REF_DOCKCPOC)
866  {
867  playerships[0].dockoffset.x = datapacket.positionx;
868  playerships[0].dockoffset.y = datapacket.positiony;
869  playerships[0].dockoffset.z = datapacket.positionz;
870  playerships[0].dockingvel.x = datapacket.velocityx;
871  playerships[0].dockingvel.y = datapacket.velocityy;
872  playerships[0].dockingvel.z = datapacket.velocityz;
873  D3DXVec3Add(&playerships[0].position, &playerships[0].dockoffset, &allobjects[datapacket.reference - REF_DOCKCPOC].position);
874  D3DXVec3Add(&playerships[0].velocity, &playerships[0].dockingvel, &allobjects[datapacket.reference - REF_DOCKCPOC].velocity);
875  sprintf_s(msg, sizeof msg, " Dock positionX %.3f Y %.3f Z %.3f (%.3f)!", allobjects[datapacket.reference - REF_DOCKCPOC].position.x, allobjects[datapacket.reference - REF_DOCKCPOC].position.y, allobjects[datapacket.reference - REF_DOCKCPOC].position.z, D3DXVec3Length(&allobjects[datapacket.reference - REF_DOCKCPOC].position));
876  Trace(msg);
877  sprintf_s(msg, sizeof msg, " Dock velocityX %.3f Y %.3f Z %.3f (%.3f)!", allobjects[datapacket.reference - REF_DOCKCPOC].velocity.x, allobjects[datapacket.reference - REF_DOCKCPOC].velocity.y, allobjects[datapacket.reference - REF_DOCKCPOC].velocity.z, D3DXVec3Length(&allobjects[datapacket.reference - REF_DOCKCPOC].velocity));
878  Trace(msg);
879  }
880  else
881  {
882  playerships[0].position.x = datapacket.positionx;
883  playerships[0].position.y = datapacket.positiony;
884  playerships[0].position.z = datapacket.positionz;
885  playerships[0].velocity.x = datapacket.velocityx;
886  playerships[0].velocity.y = datapacket.velocityy;
887  playerships[0].velocity.z = datapacket.velocityz;
888  }
892 
893  sprintf_s(msg, sizeof msg, " Our positionX %.3f Y %.3f Z %.3f (%.3f)!", playerships[0].position.x, playerships[0].position.y, playerships[0].position.z, D3DXVec3Length(&playerships[0].position));
894  Trace(msg);
895  sprintf_s(msg, sizeof msg, " Our posleftX %.3f Y %.3f Z %.3f (%.3f)!", playerships[0].posleft.x, playerships[0].posleft.y, playerships[0].posleft.z, D3DXVec3Length(&playerships[0].posleft));
896  Trace(msg);
897  sprintf_s(msg, sizeof msg, " Our positerX %.3f Y %.3f Z %.3f (%.3f)!", playerships[0].positer.x, playerships[0].positer.y, playerships[0].positer.z, D3DXVec3Length(&playerships[0].positer));
898  Trace(msg);
899  sprintf_s(msg, sizeof msg, " Our velocityX %.3f Y %.3f Z %.3f (%.3f)!", playerships[0].velocity.x, playerships[0].velocity.y, playerships[0].velocity.z, D3DXVec3Length(&playerships[0].velocity));
900  Trace(msg);
901  sprintf_s(msg, sizeof msg, " Our velleftX %.3f Y %.3f Z %.3f (%.3f)!", playerships[0].velleft.x, playerships[0].velleft.y, playerships[0].velleft.z, D3DXVec3Length(&playerships[0].velleft));
902  Trace(msg);
903  sprintf_s(msg, sizeof msg, " Our veliterX %.3f Y %.3f Z %.3f (%.3f)!", playerships[0].veliter.x, playerships[0].veliter.y, playerships[0].veliter.z, D3DXVec3Length(&playerships[0].veliter));
904  Trace(msg);
905 
906  D3DXVECTOR3 gthrust;
907  float radius;
908  playerships[0].barycentric = Viewscreen::CalculateBarycentric(&playerships[0].position, &gthrust, &radius);
909 
910  playerships[0].orientation.x = datapacket.orientationx;
911  playerships[0].orientation.y = datapacket.orientationy;
912  playerships[0].orientation.z = datapacket.orientationz;
913  playerships[0].orientation.w = datapacket.orientationw;
914 
915  game->viewscreen->rooms.clear();
916 
917  static int oldPlayerFrame = -1;
918  game->GUI->player[ourcockpit.ourplyrC].frame = datapacket.playerFrame;
919 
920  if (datapacket.playerFrame == REF_INANOTHER) // means we are in a vehicle
921  {
922  playerships[0].type = datapacket.vehicleType;
923  game->GUI->player[ourcockpit.ourplyrC].hdg = game->GUI->player[ourcockpit.ourplyrC].smoothhdg = 0.0f;
924  playerships[0].pitch = datapacket.pitch1 / 32767.0f * rotlimitC;
925  playerships[0].roll = datapacket.roll1 / 32767.0f * rotlimitC;
926  playerships[0].yaw = datapacket.yaw1 / 32767.0f * rotlimitC;
927  playerships[0].bay = datapacket.bay;
928  }
929  else // in a building
930  {
932  // Fix for sumta getting 150 mph wind in the apartment first time he starts
934 
935  game->GUI->player[ourcockpit.ourplyrC].bldg = datapacket.playerBldg;
936  game->GUI->player[ourcockpit.ourplyrC].floor = static_cast<int>(datapacket.floor);
937  playerships[0].pitch = playerships[0].roll = playerships[0].yaw = 0.0f;
938 
939  if (datapacket.playerFrame == REF_SIMBAY)
940  {
941  if (!playerships[0].simulator)
942  {
943  game->GUI->player[ourcockpit.ourplyrC].hdg = static_cast<float>(90); // entrance facing the room
944  game->GUI->player[ourcockpit.ourplyrC].x = -948;
945  game->GUI->player[ourcockpit.ourplyrC].y = -228;
946  }
947  else if (playerships[0].type == VehicleType::W6Manx)
948  {
949  game->GUI->player[ourcockpit.ourplyrC].hdg = D3DX_HALFPI; // right outside simulator facing simulator
950  game->GUI->player[ourcockpit.ourplyrC].x = 2500;
951  game->GUI->player[ourcockpit.ourplyrC].y = -114;
952  }
953  else if (playerships[0].type == VehicleType::T19)
954  {
955  game->GUI->player[ourcockpit.ourplyrC].hdg = D3DX_HALFPI; // right outside simulator facing simulator
956  game->GUI->player[ourcockpit.ourplyrC].x = 1500;
957  game->GUI->player[ourcockpit.ourplyrC].y = -114;
958  }
959  playerships[0].type = SimBay;
960 
961  // 300x222 boxes for foyers and sim bay entrances
962  RECT westEntrance;
963  westEntrance.left = -948; westEntrance.right = -648;
964  westEntrance.bottom = -336; westEntrance.top = -114;
965  game->viewscreen->rooms.emplace_back(westEntrance);
966  RECT westHall;
967  westHall.left = -648; westHall.right = 350;
968  westHall.bottom = -336; westHall.top = -114;
969  game->viewscreen->rooms.emplace_back(westHall);
970  RECT bay1;
971  bay1.left = 350; bay1.right = 650;
972  bay1.bottom = -336; bay1.top = -114;
973  game->viewscreen->rooms.emplace_back(bay1);
974  RECT hall2;
975  hall2.left = 650; hall2.right = 1350;
976  hall2.bottom = -336; hall2.top = -114;
977  game->viewscreen->rooms.emplace_back(hall2);
978  RECT bay2;
979  bay2.left = 1350; bay2.right = 1650;
980  bay2.bottom = -336; bay2.top = -114;
981  game->viewscreen->rooms.emplace_back(bay2);
982  RECT hall3;
983  hall3.left = 1650; hall3.right = 2350;
984  hall3.bottom = -336; hall3.top = -114;
985  game->viewscreen->rooms.emplace_back(hall3);
986  RECT bay3;
987  bay3.left = 2350; bay3.right = 2650;
988  bay3.bottom = -336; bay3.top = -114;
989  game->viewscreen->rooms.emplace_back(bay3);
990  RECT eastHall;
991  eastHall.left = 2650; eastHall.right = 3670;
992  eastHall.bottom = -336; eastHall.top = -114;
993  game->viewscreen->rooms.emplace_back(eastHall);
994  RECT eastEntrance;
995  eastEntrance.left = 3670; eastEntrance.right = 3970;
996  eastEntrance.bottom = -336; eastEntrance.top = -114;
997  game->viewscreen->rooms.emplace_back(eastEntrance);
998  }
999  else if (datapacket.playerFrame == REF_BUILDING)
1000  {
1001  switch (datapacket.playerBldg)
1002  {
1003  case 1:
1004  {
1005  playerships[0].type = Apartment;
1006  if (oldPlayerFrame != -1) // they came from a car or something
1007  {
1008  game->GUI->player[ourcockpit.ourplyrC].hdg = static_cast<float>(-45);
1009  game->GUI->player[ourcockpit.ourplyrC].x = 0;
1010  game->GUI->player[ourcockpit.ourplyrC].y = -1671;
1011  }
1012  else // start them in bedroom
1013  {
1014  game->GUI->player[ourcockpit.ourplyrC].hdg = static_cast<float>(-63);
1015  game->GUI->player[ourcockpit.ourplyrC].x = -193;
1016  game->GUI->player[ourcockpit.ourplyrC].y = -446;
1017  }
1018 
1019  const LONG buffer = 31;
1020  const LONG centerX = 0;
1021  const LONG centerY = -129;
1022 
1023  RECT livingRoom;
1024  livingRoom.left = -1042 + buffer + centerX; livingRoom.right = 100 - buffer + centerX;
1025  livingRoom.top = 739 - buffer + centerY; livingRoom.bottom = 51 + buffer + centerY;
1026  game->viewscreen->rooms.emplace_back(livingRoom);
1027  RECT hall;
1028  hall.left = -100 + buffer + centerX; hall.right = 100 - buffer + centerX;
1029  hall.top = 51 + buffer + centerY; hall.bottom = -862 + buffer + centerY;
1030  game->viewscreen->rooms.emplace_back(hall);
1031  RECT hallToKitchen;
1032  hallToKitchen.left = -124 - buffer + centerX; hallToKitchen.right = -100 + buffer + centerX;
1033  hallToKitchen.top = -662 - buffer + centerY; hallToKitchen.bottom = -862 + buffer + centerY;
1034  game->viewscreen->rooms.emplace_back(hallToKitchen);
1035  RECT northKitchen;
1036  northKitchen.left = -1042 + buffer + centerX; northKitchen.right = -124 - buffer + centerX;
1037  northKitchen.top = -662 - buffer + centerY; northKitchen.bottom = -968 + buffer + centerY;
1038  game->viewscreen->rooms.emplace_back(northKitchen);
1039  RECT middleKitchen;
1040  middleKitchen.left = -932 + buffer + centerX; middleKitchen.right = -124 - buffer + centerX;
1041  middleKitchen.top = -968 + buffer + centerY; middleKitchen.bottom = -1115 - buffer + centerY;
1042  game->viewscreen->rooms.emplace_back(middleKitchen);
1043  RECT leftKitchen;
1044  leftKitchen.left = -932 + centerX; leftKitchen.right = -589 + buffer + centerX;
1045  leftKitchen.top = -1115 - buffer + centerY; leftKitchen.bottom = -1456 + centerY;
1046  game->viewscreen->rooms.emplace_back(leftKitchen);
1047  RECT rightKitchen;
1048  rightKitchen.left = -589 + buffer + centerX; rightKitchen.right = -124 - buffer + centerX;
1049  rightKitchen.top = -1115 - buffer + centerY; rightKitchen.bottom = -1573 + buffer + centerY;
1050  game->viewscreen->rooms.emplace_back(rightKitchen);
1051  RECT foyer; // entrance is 0, -1671
1052  foyer.left = -124 - buffer + centerX; foyer.right = 100 - buffer + centerX;
1053  foyer.top = -1373 - buffer + centerY; foyer.bottom = -1573 + buffer + centerY;
1054  game->viewscreen->rooms.emplace_back(foyer);
1055  RECT livingToBedroom;
1056  livingToBedroom.left = -825 + buffer + centerX; livingToBedroom.right = -659 - buffer + centerX;
1057  livingToBedroom.top = 51 + buffer + centerY; livingToBedroom.bottom = 27 - buffer + centerY;
1058  game->viewscreen->rooms.emplace_back(livingToBedroom);
1059  RECT northBedroom;
1060  northBedroom.left = -903 + buffer + centerX; northBedroom.right = -547 + centerX; // no buffer to chair on right
1061  northBedroom.top = 27 - buffer + centerY; northBedroom.bottom = -106 + centerY; // no buffer to line up with chair leg
1062  game->viewscreen->rooms.emplace_back(northBedroom);
1063  RECT midBedroom;
1064  midBedroom.left = -903 + buffer + centerX; midBedroom.right = -442 + centerX;
1065  midBedroom.top = -106 + centerY; midBedroom.bottom = -255 + centerY;
1066  game->viewscreen->rooms.emplace_back(midBedroom);
1067  RECT dresser;
1068  dresser.left = -903 + buffer + centerX; dresser.right = -684 + centerX;
1069  dresser.top = -255 + centerY; dresser.bottom = -321 + centerY;
1070  game->viewscreen->rooms.emplace_back(dresser);
1071  RECT southBedroom;
1072  southBedroom.left = -684 + centerX; southBedroom.right = -183 + centerX;
1073  southBedroom.top = -255 + centerY; southBedroom.bottom = -387 + buffer + centerY;
1074  game->viewscreen->rooms.emplace_back(southBedroom);
1075  RECT bedToBath;
1076  bedToBath.left = -632 + buffer + centerX; bedToBath.right = -495 - buffer + centerX;
1077  bedToBath.top = -387 + centerY; bedToBath.bottom = -556 + centerY;
1078  game->viewscreen->rooms.emplace_back(bedToBath);
1079  RECT toilet;
1080  toilet.left = -495 - buffer + centerX; toilet.right = -396 + centerX;
1081  toilet.top = -411 - buffer + centerY; toilet.bottom = -523 + centerY;
1082  game->viewscreen->rooms.emplace_back(toilet);
1083  RECT shower;
1084  shower.left = -396 + centerX; shower.right = -252 - buffer + centerX;
1085  shower.top = -411 - buffer + centerY; shower.bottom = -638 + buffer + centerY;
1086  game->viewscreen->rooms.emplace_back(shower);
1087  }
1088  break;
1089  case 2:
1090  playerships[0].type = ControlTower;
1091  game->GUI->player[ourcockpit.ourplyrC].hdg = static_cast<float>(-360);
1092  game->GUI->player[ourcockpit.ourplyrC].x = -107;
1093  game->GUI->player[ourcockpit.ourplyrC].y = -258;
1094  break; // control tower
1095  default:
1096  Trace("Unhandled building number!", Logger::Level::Error);
1097  break;
1098  }
1099  }
1100 
1102  //&game->GUI->player[ourcockpit.ourplyrC].x, &game->GUI->player[ourcockpit.ourplyrC].y,
1103  //&game->viewscreen->leftright, &game->viewscreen->updown, &game->viewscreen->rolltilt);
1104 
1105  game->GUI->player[ourcockpit.ourplyrC].smoothhdg = D3DXToRadian(game->GUI->player[ourcockpit.ourplyrC].hdg);
1106  game->GUI->player[ourcockpit.ourplyrC].smoothx = static_cast<float>(game->GUI->player[ourcockpit.ourplyrC].x) * INTERIOR_SCALE;
1107  game->GUI->player[ourcockpit.ourplyrC].smoothy = static_cast<float>(game->GUI->player[ourcockpit.ourplyrC].y) * INTERIOR_SCALE;
1108  game->GUI->player[ourcockpit.ourplyrC].startx = static_cast<float>(game->GUI->player[ourcockpit.ourplyrC].x);
1109  game->GUI->player[ourcockpit.ourplyrC].starty = static_cast<float>(game->GUI->player[ourcockpit.ourplyrC].y);
1110 
1111  // take 12 cm off for eye height from top of head
1112  ourcockpit.chaireye.z = static_cast<float>(game->GUI->player[ourcockpit.ourplyrC].heightCm - 12) * 0.00001f;
1113 
1114  ourcockpit.power = 1.0f;
1115  ourcockpit.startcycle = 2;
1118  }
1119 
1120  oldPlayerFrame = datapacket.playerFrame;
1121 
1122  if (datapacket.reference == REF_INANOTHER)
1123  {
1124  if (datapacket.inarray == 0)
1125  Trace("datapacket.inarray is 0!", Logger::Level::Warn);
1126 
1127  playerships[0].inarray = datapacket.inarray;
1128 
1129  // we may not have the type information yet, and this slot may not be visible yet, but we can assume that the information we got about our vehicle
1130  // is same as the parent!
1131 
1132  playerships[datapacket.inarray].position.x = datapacket.positionx;
1133  playerships[datapacket.inarray].position.y = datapacket.positiony;
1134  playerships[datapacket.inarray].position.z = datapacket.positionz;
1135  playerships[datapacket.inarray].precisionx = datapacket.positionx;
1136  playerships[datapacket.inarray].precisiony = datapacket.positiony;
1137  playerships[datapacket.inarray].precisionz = datapacket.positionz;
1138  playerships[datapacket.inarray].velocity.x = datapacket.velocityx;
1139  playerships[datapacket.inarray].velocity.y = datapacket.velocityy;
1140  playerships[datapacket.inarray].velocity.z = datapacket.velocityz;
1141  playerships[datapacket.inarray].orientation.x = datapacket.orientationx;
1142  playerships[datapacket.inarray].orientation.y = datapacket.orientationy;
1143  playerships[datapacket.inarray].orientation.z = datapacket.orientationz;
1144  playerships[datapacket.inarray].orientation.w = datapacket.orientationw;
1145  playerships[datapacket.inarray].pitch = datapacket.pitch1 / 32767.0f * rotlimitC;
1146  playerships[datapacket.inarray].roll = datapacket.roll1 / 32767.0f * rotlimitC;
1147  playerships[datapacket.inarray].yaw = datapacket.yaw1 / 32767.0f * rotlimitC;
1148  playerships[datapacket.inarray].reference = datapacket.parentReference;
1149  playerships[datapacket.inarray].pitchdeflect = datapacket.pitchDeflect;
1150  playerships[datapacket.inarray].rolldeflect = datapacket.rollDeflect;
1151  playerships[datapacket.inarray].yawdeflect = datapacket.yawDeflect;
1152  }
1153 
1154  //if (datapacket.reference == REF_ONGROUND || datapacket.reference == REF_APNMODE ||
1155  // (datapacket.reference == REF_INANOTHER && (datapacket.parentReference == REF_ONGROUND || datapacket.parentReference == REF_APNMODE)) ||
1156  // datapacket.reference == REF_BUILDING) // don't need for windowless environment or simbay
1157  //{
1158  // // repositioning to waypoint on ground means we may be on a different grid
1159  // game->viewscreen->ptrGrid->CalculateCubeAndTcp(); // handles his own locking
1160 
1161  // // clear old and request new grid
1162  // if (!ground.initialized)
1163  // {
1164  // Trace("RakNetMessageHandler calling RWG due to SUPER packet...");
1165  // game->viewscreen->ptrGrid->RequestWholeGrid();
1166  // }
1167  //}
1168  //else
1169  //{
1170  // Trace("Built-in packet hold was not required...");
1171  //}
1172 
1173 #pragma region Old ship type = 9 data
1174 
1175  int vehicleType, allegiance;
1176  unsigned int vehicleId;
1177  char bitstring[99], trimcolor[8];
1178 
1179  playerships[0].hullname[0] = 0;
1181  {
1182  sprintf_s(msg, sizeof msg, "Released m_pddsHullDynamicTexture slot %i!", 0);
1183  Trace(msg);
1184  SAFE_RELEASE(game->viewscreen->m_pddsHullDynamicTexture[0]);
1185  sprintf_s(msg, sizeof msg, "m_pddsHullDynamicTexture[%i]", 0);
1186  game->UpdateTrackedResource(msg, 3);
1187  }
1188 
1189  Trace(datapacket.oldShipData);
1190 
1191  int reference;
1192  const int results = sscanf_s(datapacket.oldShipData, "%[^,],%[^,],%d,%[^,],%[^,],%[^,],%d,%u,%d,%d,%[^\n]",
1193  playerships[0].IVR, 6, bitstring, sizeof bitstring, &vehicleType, playerships[0].owner, 13, trimcolor, 8, playerships[0].logofile, 8, &reference, &vehicleId, &allegiance, &playerships[0].ownerId, playerships[0].hullname, 23);
1194  // 53267, 001001001000, 3, rana, #FFFFFF, 123_456, -1, 462, 0, 123, GEORGE WASHINGTON
1195  if (results < 10)
1196  {
1197  Trace(datapacket.oldShipData, Logger::Error);
1198  sprintf_s(msg, sizeof msg, "Could only parse %i of 10 required (11 optional) items from type 9 data SUPER_PACKET!", results);
1199  Trace(msg, Logger::Fatal);
1200  return;
1201  }
1202 
1203  playerships[0].sequence = 0;
1204 
1205  _strupr_s(playerships[0].hullname, sizeof playerships[0].hullname);
1206 
1207  if (playerships[0].type == VehicleType::C98 ||
1208  playerships[0].type == VehicleType::C2 ||
1209  playerships[0].type == VehicleType::T27 ||
1210  playerships[0].type == VehicleType::C2A ||
1211  playerships[0].type == VehicleType::T120 ||
1212  playerships[0].type == VehicleType::T121)
1213  playerships[0].groundvehicle = true;
1214  else
1215  playerships[0].groundvehicle = false;
1216 
1217  char hexcolor[11];
1218  sprintf_s(hexcolor, 11, "0x00%s", &trimcolor[1]);
1219  playerships[0].trimcolor = strtol(hexcolor, nullptr, 0);
1220 
1221  playerships[0].vehicleId = static_cast<unsigned short>(vehicleId);
1222 
1223  sprintf_s(msg, sizeof msg, "ship data IVR %s vehicleId %i slot %i", playerships[0].IVR, vehicleId, 0);
1224  Trace(msg);
1225 
1226  const Sscan scan = game->bus->Scanner.Get(vehicleId);
1227  if (scan.initialized)
1228  {
1230  // check that he isn't listed as a parent id of a vehicle we previously scanned
1231  if (playerships[0].reference != REF_INANOTHER)
1232  game->bus->Scanner.InsertUpdateParent(vehicleId, 0);
1233  }
1234  else
1235  playerships[0].align = 1;
1236 
1237  playerships[0].allegiance = allegiance;
1238 
1239  playerships[0].police = bitstring[0] == '1';
1240  playerships[0].specialight = bitstring[1] == '1';
1241  playerships[0].tow = bitstring[2] == '1';
1242  playerships[0].docked = bitstring[3] == '1';
1243  playerships[0].logolight = bitstring[4] == '1';
1244  playerships[0].simulator = bitstring[5] == '1';
1245  playerships[0].geardown = bitstring[6] == '1';
1246  playerships[0].headlight = bitstring[7] == '1';
1247  playerships[0].baydoor = bitstring[8] == '1';
1248  playerships[0].domelight = bitstring[9] == '1';
1249  playerships[0].reposess = bitstring[10] == '1';
1250  playerships[0].stolen = bitstring[11] == '1';
1251 
1252  playerships[0].active = true;
1253  playerships[0].visible = true;
1254 
1255  game->viewscreen->SetProjectionMatrices(); // for if simulator changes
1256 
1257 #pragma endregion
1258 
1259 #pragma region Things the server persists about our vehicle
1260 
1262  ourcockpit.parkingBrake = datapacket.parkingBrake;
1263  else
1264  ourcockpit.parkingBrake = false;
1265 
1266  game->bus->YawDamperStatus = datapacket.yawDamper;
1267  game->bus->AntiIce = datapacket.antiIce;
1268  ourcockpit.radioPower = datapacket.radioPower;
1269  ourcockpit.weatherRadarPower = datapacket.weatherRadarPower;
1270  ourcockpit.remoteAssayPower = datapacket.remoteAssayPower;
1271  game->viewscreen->ptrPropulsion->airframeTempCelsius = static_cast<float>(datapacket.hullTempCelsius) * 0.1f;
1272  game->viewscreen->ptrPropulsion->iceAccumulationMm = datapacket.iceAccumulationMm;
1273  game->bus->PitchTrimScalar = static_cast<float>(datapacket.pitchTrim) / 32767.0f;
1274 
1275 #pragma endregion
1276 
1277  game->viewscreen->LoadVehicleProfile(0, true);
1278 
1279  // @warn Flaps have to be done AFTER LoadVehicleProfile is called
1280  playerships[0].flapdown = 0;
1281  sprintf_s(msg, sizeof msg, "Looking for a flap setting %.3f (%i settings)", datapacket.flapsDown, ourcockpit.flapSettings.size());
1282  Trace(msg);
1283 
1284  for (size_t i = 0; i < ourcockpit.flapSettings.size(); i++)
1285  {
1286  if (fabsf(datapacket.flapsDown * static_cast<float>(ourcockpit.flapMaxDegrees) - static_cast<float>(ourcockpit.flapSettings.at(i))) < 1.0f)
1287  {
1288  sprintf_s(msg, sizeof msg, "Found a flap setting %i (%i degrees)", i, ourcockpit.flapSettings.at(i));
1289  Trace(msg);
1290  game->bus->flapSettingTE = i;
1291  playerships[0].flapdown = static_cast<float>(ourcockpit.flapSettings.at(i)) / static_cast<float>(ourcockpit.flapMaxDegrees);
1292  for (unsigned short s = 0; s < playerships[0].components; s++)
1293  {
1294  // ReSharper disable once CppDefaultCaseNotHandledInSwitchStatement
1295  switch (playerships[0].componentarray[s].type)
1296  {
1297  case 16: // flaps (TE)
1298  case 68: // flaps (LE)
1299  {
1304  }
1305  break;
1306  }
1307  }
1308  break;
1309  }
1310  }
1311 
1312 #pragma region Things that are not saved on the server that need to be persisted!
1313 
1314  for (int i = 0; i < MAX_ENGINES; i++)
1315  {
1316  game->bus->EngineThrustLever[i] = 0.0f;
1317  game->bus->EngineThrustOutput[i] = 0.0f;
1318  game->bus->ThrustReverserCommand[i] = false;
1319  }
1320 
1321  g_bAugment = true;
1322 
1323 #pragma endregion
1324 
1325 #pragma region Things that are not saved on the server that need to be reset!
1326 
1327  ourcockpit.tirespeedKph = 0.0f;
1328  ourcockpit.tach = 0.0f;
1329 
1330  dead = 0; // for if we are coming back out of simulator
1331 
1332  if (playerships[0].simulator)
1333  {
1335  game->bus->FlightFreeze = true;
1337  }
1338  else
1339  game->bus->FlightFreeze = false;
1340 
1343 
1344 #pragma endregion
1345 
1346  // Stuff added 12/09/2020
1347  if (datapacket.selectedTarget >= 0)
1348  {
1349  // got to find it
1350  bool found = false;
1351  for (short i = 0; i < MAX_SCAN; i++)
1352  {
1353  if (playerships[game->viewscreen->scanslot[i]].vehicleId == datapacket.selectedTarget)
1354  {
1355  found = true;
1356  game->bus->targetC = i;
1357  break;
1358  }
1359  }
1360  if (!found)
1361  {
1362  game->bus->targetC = -1;
1364  }
1365  }
1366  else
1367  game->bus->targetC = static_cast<short>(datapacket.selectedTarget);
1368 
1369  game->displays->ChangePage("MFD", datapacket.selectedPage);
1370 
1371  ourcockpit.gearshift = datapacket.currentGear;
1372 
1373  game->bus->MapScaleInnerRingKm = datapacket.mapZoom;
1374 
1375  playerships[0].pitchdeflect = datapacket.pitchDeflect;
1376  playerships[0].rolldeflect = datapacket.rollDeflect;
1377  playerships[0].yawdeflect = datapacket.yawDeflect;
1379  }
1380  break;
1381 
1382  case ID_USER_PACKET_TELEMETRY:
1383  {
1384  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 1");
1385 
1386  SServerPacketNew datapacket;
1387  memcpy_s(&datapacket, sizeof SServerPacketNew, &packet->data[1], packet->length - 1);
1388 
1389  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 2");
1390 
1391  if (datapacket.array >= MAX_SCAN)
1392  {
1393  sprintf_s(msg, sizeof msg, "Telemetry tried accessing array element %i!", datapacket.array);
1394  Trace(msg, Logger::Level::Fatal);
1395  }
1396  else if (datapacket.array == 0)
1397  {
1398  Trace("Got telemetry about us!", Logger::Level::Error);
1399  return;
1400  }
1401  else if (datapacket.sequence < playerships[datapacket.array].sequence)
1402  {
1403  sprintf_s(msg, sizeof msg, "Telemetry discarded old out-of-sequence packet for slot %i!", datapacket.array);
1404  Trace(msg);
1405  return;
1406  }
1407 
1408  playerships[datapacket.array].sequence = datapacket.sequence;
1409 
1410  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 3");
1411 
1412  if (!playerships[datapacket.array].active) // is the slot initialized
1413  {
1414  sprintf_s(msg, sizeof msg, "Telemetry for vehicle not yet initialized (%i)...", datapacket.array);
1415  Trace(msg);
1416  playerships[datapacket.array].clientinit = true;
1417  }
1418 
1419  if (!playerships[datapacket.array].inhibitvisibility)
1420  playerships[datapacket.array].visible = true; // got telemetry
1421 
1422  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 4");
1423 
1424  // Update acceleration
1425  if (!g_bRunning || playerships[datapacket.array].clientinit)
1426  {
1427  playerships[datapacket.array].acc.x = static_cast<float>(datapacket.ai) / 32767.0f * MaxAcceleration;
1428  playerships[datapacket.array].acc.y = static_cast<float>(datapacket.aj) / 32767.0f * MaxAcceleration;
1429  playerships[datapacket.array].acc.z = static_cast<float>(datapacket.ak) / 32767.0f * MaxAcceleration;
1430  playerships[datapacket.array].acciter = playerships[datapacket.array].accleft = centerC;
1431  }
1432  else
1433  {
1434  D3DXVECTOR3 acc;
1435  acc.x = static_cast<float>(datapacket.ai) / 32767.0f * MaxAcceleration;
1436  acc.y = static_cast<float>(datapacket.aj) / 32767.0f * MaxAcceleration;
1437  acc.z = static_cast<float>(datapacket.ak) / 32767.0f * MaxAcceleration;
1438  playerships[datapacket.array].accleft = acc - playerships[datapacket.array].acc;
1439  playerships[datapacket.array].acciter = playerships[datapacket.array].accleft; // 1 seconds
1440  }
1441 
1442  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 5");
1443 
1444  // Update thrust
1445  if (!g_bRunning || playerships[datapacket.array].clientinit)
1446  {
1447  playerships[datapacket.array].tx = static_cast<float>(datapacket.tx) / 127.0f;
1448  playerships[datapacket.array].ty = static_cast<float>(datapacket.ty) / 127.0f;
1449  playerships[datapacket.array].tz = static_cast<float>(datapacket.tz) / 127.0f;
1450  playerships[datapacket.array].txleft = playerships[datapacket.array].txiter = 0;
1451  playerships[datapacket.array].tyleft = playerships[datapacket.array].tyiter = 0;
1452  playerships[datapacket.array].tzleft = playerships[datapacket.array].tziter = 0;
1453  }
1454  else
1455  {
1456  playerships[datapacket.array].txleft = static_cast<float>(datapacket.tx) / 127.0f - playerships[datapacket.array].tx;
1457  playerships[datapacket.array].tyleft = static_cast<float>(datapacket.ty) / 127.0f - playerships[datapacket.array].ty;
1458  playerships[datapacket.array].tzleft = static_cast<float>(datapacket.tz) / 127.0f - playerships[datapacket.array].tz;
1459  playerships[datapacket.array].txiter = playerships[datapacket.array].txleft; // 1 second
1460  playerships[datapacket.array].tyiter = playerships[datapacket.array].tyleft; // 1 second
1461  playerships[datapacket.array].tziter = playerships[datapacket.array].tzleft; // 1 second
1462  }
1463 
1464  bool tofromdock = false;
1465  static char oldreference[MAX_SCAN];
1466  if (oldreference[datapacket.array] != playerships[datapacket.array].reference &&
1467  (oldreference[datapacket.array] != -1 || playerships[datapacket.array].reference != -1))
1468  {
1469  tofromdock = true;
1470  }
1471  oldreference[datapacket.array] = playerships[datapacket.array].reference;
1472 
1473  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 6");
1474 
1475  // Update velocity
1476  if (!g_bRunning || tofromdock || playerships[datapacket.array].clientinit)
1477  {
1478  if (playerships[datapacket.array].reference < REF_INANOTHER)
1479  playerships[datapacket.array].velocity = datapacket.velocity;
1480  else
1481  playerships[datapacket.array].dockingvel = datapacket.velocity;
1482  playerships[datapacket.array].veliter = playerships[datapacket.array].velleft = centerC;
1483  }
1484  else
1485  {
1486  if (playerships[datapacket.array].reference < REF_INANOTHER)
1487  playerships[datapacket.array].velleft = datapacket.velocity - playerships[datapacket.array].velocity;
1488  else
1489  playerships[datapacket.array].velleft = datapacket.velocity - playerships[datapacket.array].dockingvel;
1490  playerships[datapacket.array].veliter = playerships[datapacket.array].velleft; // 1 seconds
1491  }
1492 
1493  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 7");
1494 
1495  // Update position
1496  if (!g_bRunning || tofromdock || playerships[datapacket.array].clientinit)
1497  {
1498  if (playerships[datapacket.array].reference < REF_INANOTHER)
1499  {
1500  playerships[datapacket.array].precisionx = static_cast<double>(datapacket.position.x);
1501  playerships[datapacket.array].precisiony = static_cast<double>(datapacket.position.y);
1502  playerships[datapacket.array].precisionz = static_cast<double>(datapacket.position.z);
1503 
1504  playerships[datapacket.array].position = datapacket.position;
1505  }
1506  else
1507  playerships[datapacket.array].dockoffset = datapacket.position;
1508  playerships[datapacket.array].posleft = playerships[datapacket.array].positer = centerC;
1509  }
1510  else // is already in progress
1511  {
1512  if (playerships[datapacket.array].reference < REF_INANOTHER)
1513  playerships[datapacket.array].posleft = datapacket.position - playerships[datapacket.array].position;
1514  else
1515  playerships[datapacket.array].posleft = datapacket.position - playerships[datapacket.array].dockoffset;
1516  playerships[datapacket.array].positer = playerships[datapacket.array].posleft;// *0.25f; // 4 seconds
1517  }
1518 
1519  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 8");
1520 
1521  // Update orientation
1522  if (!g_bRunning || playerships[datapacket.array].clientinit)
1523  {
1524  playerships[datapacket.array].orientation = datapacket.orientation;
1525  playerships[datapacket.array].orientiter = playerships[datapacket.array].orientleft = D3DXQUATERNION(0, 0, 0, 0);
1526  }
1527  else
1528  {
1529  playerships[datapacket.array].orientleft = datapacket.orientation - playerships[datapacket.array].orientation;
1530  playerships[datapacket.array].orientiter = playerships[datapacket.array].orientleft;// *0.5f; // 2 seconds
1531  }
1532 
1533  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 9");
1534 
1535  // Update pitchyawroll
1536  if (!g_bRunning || playerships[datapacket.array].clientinit)
1537  {
1538  playerships[datapacket.array].pitch = static_cast<float>(datapacket.pitch1) / 32767.0f * rotlimitC;
1539  playerships[datapacket.array].roll = static_cast<float>(datapacket.roll1) / 32767.0f * rotlimitC;
1540  playerships[datapacket.array].yaw = static_cast<float>(datapacket.yaw1) / 32767.0f * rotlimitC;
1541  playerships[datapacket.array].pitchleft = playerships[datapacket.array].pitchiter = 0;
1542  playerships[datapacket.array].rollleft = playerships[datapacket.array].rolliter = 0;
1543  playerships[datapacket.array].yawleft = playerships[datapacket.array].yawiter = 0;
1544  }
1545  else
1546  {
1547  playerships[datapacket.array].pitchleft = static_cast<float>(datapacket.pitch1) / 32767.0f * rotlimitC - playerships[datapacket.array].pitch;
1548  playerships[datapacket.array].pitchiter = playerships[datapacket.array].pitchleft;// *0.5f; // 2 seconds
1549  playerships[datapacket.array].rollleft = static_cast<float>(datapacket.roll1) / 32767.0f * rotlimitC - playerships[datapacket.array].roll;
1550  playerships[datapacket.array].rolliter = playerships[datapacket.array].rollleft;// *0.5f; // 2 seconds
1551  playerships[datapacket.array].yawleft = static_cast<float>(datapacket.yaw1) / 32767.0f * rotlimitC - playerships[datapacket.array].yaw;
1552  playerships[datapacket.array].yawiter = playerships[datapacket.array].yawleft;// *0.5f; // 2 seconds
1553  }
1554 
1555  playerships[datapacket.array].pitchdeflect = static_cast<float>(datapacket.pitchdeflect) / 127.0f;
1556  playerships[datapacket.array].rolldeflect = static_cast<float>(datapacket.rolldeflect) / 127.0f;
1557  playerships[datapacket.array].yawdeflect = static_cast<float>(datapacket.yawdeflect) / 127.0f;
1558 
1559  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 10");
1560 
1561  if (playerships[datapacket.array].clientinit)
1562  {
1563  playerships[datapacket.array].clientinit = false;
1564  sprintf_s(msg, sizeof msg, "First telemetry for slot %i received!", datapacket.array);
1565  Trace(msg);
1566  sprintf_s(msg, sizeof msg, " %f %f %f,%f %f %f", playerships[datapacket.array].position.x, playerships[datapacket.array].position.y, playerships[datapacket.array].position.z, playerships[datapacket.array].velocity.x, playerships[datapacket.array].velocity.y, playerships[datapacket.array].velocity.z);
1567  Trace(msg);
1568  }
1569  else if (playerships[datapacket.array].reference == REF_INANOTHER && playerships[datapacket.array].inarray == 0)
1570  {
1571  sprintf_s(msg, sizeof msg, "Got telemetry for vehicle that is inside our bay!");
1572  Trace(msg);
1573  sprintf_s(msg, sizeof msg, " %f %f %f,%f %f %f", playerships[datapacket.array].position.x, playerships[datapacket.array].position.y, playerships[datapacket.array].position.z, playerships[datapacket.array].velocity.x, playerships[datapacket.array].velocity.y, playerships[datapacket.array].velocity.z);
1574  Trace(msg);
1575  }
1576 
1577  game->logger->AddToCallStack("ID_USER_PACKET_TELEMETRY 11");
1578  }
1579  break;
1580 
1581  case ID_USER_PACKET_ENUM: // Custom message from server
1582  {
1583  sprintf_s(msg, sizeof msg, "RakNetMessageHandler ID_USER_PACKET_ENUM (size %i)", packet->length - 1);
1584  game->logger->AddToCallStack(msg);
1585 
1586  switch (packet->length - 1)
1587  {
1588  case sizeof SServerPacket:
1589  {
1590  SServerPacket datapacket;
1591  memcpy_s(&datapacket, sizeof SServerPacket, &packet->data[1], packet->length - 1);
1592 
1593  sprintf_s(msg, sizeof msg, "SServerPacket %i %.1f %.1f %.1f %.1f %i", datapacket.type, datapacket.f_x, datapacket.f_y, datapacket.f_z, datapacket.f_w, datapacket.array);
1594  game->logger->AddToCallStack(msg);
1595 
1596  switch (datapacket.type)
1597  {
1598  case 1: // Server removes online player
1599  // went offline
1600  if (datapacket.array == 255) // support
1601  {
1602  // if (datapacket.f_x==0.0f) // offline
1603  // {
1604  // strcpy_s(msg, sizeof(msg), "Support logged off");
1605  }
1606  else
1607  game->GUI->PlayerOffline(datapacket.array);
1608  break;
1609 
1610  case 2: // docking status
1611  sprintf_s(msg, sizeof msg, "Server sent dock assignment (%.0f, %.0f)", datapacket.f_x, datapacket.f_y);
1612  Trace(msg);
1613  playerships[0].portassigned = static_cast<char>(datapacket.f_x);
1614  playerships[0].docked = datapacket.f_y == 1.0f;
1615  if (playerships[0].docked) dockprogress = 1.0f; // if they send that we are docked it must be on startup or on transfer
1616  break;
1617 
1618  case 3: // Server sends conclusion of data
1619 
1620  game->GUI->loginstr[0] = 0; // clear error text
1621  if (datapacket.f_y == 0.0f) // EOT
1622  {
1623  sprintf_s(msg, sizeof msg, "Server sent data conclusion (ourshipC %.0f, g_bEnabled %i)", datapacket.f_x, g_bEnabled);
1624  Trace(msg);
1625  game->GUI->isInjected = datapacket.f_z == 1.0f;
1626  game->GUI->IsAdmin = datapacket.f_w == 1.0f;
1627  g_bGotConclusion = true;
1628 
1629  SClientPacket outpacket;
1630  outpacket.type = 7;
1631  outpacket.f_x = 1.0f; // add peer
1632  outpacket.f_y = 0.0f; // UNUSED
1633  outpacket.f_z = 1.0f; // viewscreen peer
1634  outpacket.f_w = 1.0f; // propulsion
1635  SendToServer(&outpacket, sizeof SClientPacket, true);
1636 
1637  // send all the player devices
1638  for (size_t device = 0; device < game->viewscreen->ptrJoystick->deviceList.size(); device++)
1639  {
1640  SDeviceMessage deviceMessage;
1641  ZeroMemory(&deviceMessage, sizeof SDeviceMessage);
1642  const DIDEVICEINSTANCE deviceInstance = game->viewscreen->ptrJoystick->deviceList.at(device);
1643  wcscpy_s(deviceMessage.name, 160, deviceInstance.tszInstanceName);
1644  deviceMessage.deviceType = LOBYTE(deviceInstance.dwDevType);
1645  deviceMessage.deviceSubtype = HIBYTE(deviceInstance.dwDevType);
1646  deviceMessage.forceFeedback = deviceInstance.guidFFDriver != MYGUID_NULL ? 1 : 0;
1647 
1648  if (game->config.inputConfigLookLateral.guid == deviceInstance.guidInstance)
1649  {
1650  deviceMessage.channelAxisLookLateral = game->config.inputConfigLookLateral.axis;
1651  deviceMessage.channelInvLookLateral = game->config.inputConfigLookLateral.invert ? 1 : 0;
1652  }
1653  else
1654  deviceMessage.channelAxisLookLateral = -1; // not configured
1655 
1656  if (game->config.inputConfigLookVertical.guid == deviceInstance.guidInstance)
1657  {
1658  deviceMessage.channelAxisLookVertical = game->config.inputConfigLookVertical.axis;
1659  deviceMessage.channelInvLookVertical = game->config.inputConfigLookVertical.invert ? 1 : 0;
1660  }
1661  else
1662  deviceMessage.channelAxisLookVertical = -1; // not configured
1663 
1664  if (game->config.inputConfigWalkLateral.guid == deviceInstance.guidInstance)
1665  {
1666  deviceMessage.channelAxisTurn = game->config.inputConfigWalkLateral.axis;
1667  deviceMessage.channelInvTurn = game->config.inputConfigWalkLateral.invert ? 1 : 0;
1668  }
1669  else
1670  deviceMessage.channelAxisTurn = -1; // not configured
1671 
1672  if (game->config.inputConfigWalkVertical.guid == deviceInstance.guidInstance)
1673  {
1674  deviceMessage.channelAxisWalk = game->config.inputConfigWalkVertical.axis;
1675  deviceMessage.channelInvWalk = game->config.inputConfigWalkVertical.invert ? 1 : 0;
1676  }
1677  else
1678  deviceMessage.channelAxisWalk = -1; // not configured
1679 
1680  if (game->config.inputConfigPitch.guid == deviceInstance.guidInstance)
1681  {
1682  deviceMessage.channelAxisPitch = game->config.inputConfigPitch.axis;
1683  deviceMessage.channelInvPitch = game->config.inputConfigPitch.invert ? 1 : 0;
1684  }
1685  else
1686  deviceMessage.channelAxisPitch = -1; // not configured
1687 
1688  if (game->config.inputConfigPitchTrim.guid == deviceInstance.guidInstance)
1689  {
1690  deviceMessage.channelAxisPitchTrim = game->config.inputConfigPitchTrim.axis;
1691  deviceMessage.channelInvPitchTrim = game->config.inputConfigPitchTrim.invert ? 1 : 0;
1692  }
1693  else
1694  deviceMessage.channelAxisPitchTrim = -1; // not configured
1695 
1696  if (game->config.inputConfigRoll.guid == deviceInstance.guidInstance)
1697  {
1698  deviceMessage.channelAxisRoll = game->config.inputConfigRoll.axis;
1699  deviceMessage.channelInvRoll = game->config.inputConfigRoll.invert ? 1 : 0;
1700  }
1701  else
1702  deviceMessage.channelAxisRoll = -1; // not configured
1703 
1704  if (game->config.inputConfigYaw.guid == deviceInstance.guidInstance)
1705  {
1706  deviceMessage.channelAxisYaw = game->config.inputConfigYaw.axis;
1707  deviceMessage.channelInvYaw = game->config.inputConfigYaw.invert ? 1 : 0;
1708  }
1709  else
1710  deviceMessage.channelAxisYaw = -1; // not configured
1711 
1712  if (game->config.inputConfigThrustLeft.guid == deviceInstance.guidInstance)
1713  {
1714  deviceMessage.channelAxisThrustLeft = game->config.inputConfigThrustLeft.axis;
1715  deviceMessage.channelInvThrustLeft = game->config.inputConfigThrustLeft.invert ? 1 : 0;
1716  deviceMessage.channelSplitThrustLeft = game->config.inputConfigThrustLeft.split ? 1 : 0;
1717  }
1718  else
1719  deviceMessage.channelAxisThrustLeft = -1; // not configured
1720 
1721  if (game->config.inputConfigThrustRight.guid == deviceInstance.guidInstance)
1722  {
1723  deviceMessage.channelAxisThrustRight = game->config.inputConfigThrustRight.axis;
1724  deviceMessage.channelInvThrustRight = game->config.inputConfigThrustRight.invert ? 1 : 0;
1725  deviceMessage.channelSplitThrustRight = game->config.inputConfigThrustRight.split ? 1 : 0;
1726  }
1727  else
1728  deviceMessage.channelAxisThrustRight = -1; // not configured
1729 
1730  if (game->config.inputConfigLeftToeBrake.guid == deviceInstance.guidInstance)
1731  {
1732  deviceMessage.channelAxisLeftToeBrake = game->config.inputConfigLeftToeBrake.axis;
1733  deviceMessage.channelInvLeftToeBrake = game->config.inputConfigLeftToeBrake.invert ? 1 : 0;
1734  deviceMessage.channelSplitLeftToeBrake = game->config.inputConfigLeftToeBrake.split ? 1 : 0;
1735  }
1736  else
1737  deviceMessage.channelAxisLeftToeBrake = -1; // not configured
1738 
1739  if (game->config.inputConfigRightToeBrake.guid == deviceInstance.guidInstance)
1740  {
1741  deviceMessage.channelAxisRightToeBrake = game->config.inputConfigRightToeBrake.axis;
1742  deviceMessage.channelInvRightToeBrake = game->config.inputConfigRightToeBrake.invert ? 1 : 0;
1743  deviceMessage.channelSplitRightToeBrake = game->config.inputConfigRightToeBrake.split ? 1 : 0;
1744  }
1745  else
1746  deviceMessage.channelAxisRightToeBrake = -1; // not configured
1747 
1748  if (game->config.inputConfigSteer.guid == deviceInstance.guidInstance)
1749  {
1750  deviceMessage.channelAxisSteer = game->config.inputConfigSteer.axis;
1751  deviceMessage.channelInvSteer = game->config.inputConfigSteer.invert ? 1 : 0;
1752  }
1753  else
1754  deviceMessage.channelAxisSteer = -1; // not configured
1755 
1756 
1757  if (game->config.inputConfigGas.guid == deviceInstance.guidInstance)
1758  {
1759  deviceMessage.channelAxisGas = game->config.inputConfigGas.axis;
1760  deviceMessage.channelInvGas = game->config.inputConfigGas.invert ? 1 : 0;
1761  deviceMessage.channelSplitGas = game->config.inputConfigGas.split ? 1 : 0;
1762  }
1763  else
1764  deviceMessage.channelAxisGas = -1; // not configured
1765 
1766  if (game->config.inputConfigBrake.guid == deviceInstance.guidInstance)
1767  {
1768  deviceMessage.channelAxisBrake = game->config.inputConfigBrake.axis;
1769  deviceMessage.channelInvBrake = game->config.inputConfigBrake.invert ? 1 : 0;
1770  deviceMessage.channelSplitBrake = game->config.inputConfigBrake.split ? 1 : 0;
1771  }
1772  else
1773  deviceMessage.channelAxisBrake = -1; // not configured
1774 
1775  deviceMessage.testMarker = 18;
1776 
1777  char newdata[sizeof SDeviceMessage + 1];
1778 #pragma warning( disable : 4309 )
1779  newdata[0] = static_cast<char>(ID_USER_PACKET_DEVICE);
1780 #pragma warning( disable : 4309 )
1781  memcpy_s(&newdata[1], sizeof SDeviceMessage, &deviceMessage, sizeof deviceMessage);
1782  rakPeer->Send(newdata, sizeof SDeviceMessage + 1, MEDIUM_PRIORITY, RELIABLE, ORDERING_NONE, serverC, false);
1783  }
1784 
1785  // send the video card type
1786  SPacketBig bigpacket;
1787  bigpacket.type = 0;
1788  sprintf_s(bigpacket.msg, 78, "%.77S", DXUTGetDeviceStats());
1789  bigpacket.ship = bigpacket.array = bigpacket.inarray = 0; // all unused
1790  SendToServer(&bigpacket, sizeof SPacketBig, true);
1791 
1792  // user name and processor information
1793  bigpacket.type = 1;
1794  DWORD bufferSize = 78;
1795  GetUserNameA(bigpacket.msg, &bufferSize);
1796  bigpacket.array = 0; // UNUSED, should be cores
1797  bigpacket.inarray = static_cast<unsigned char>(GetActiveProcessorCount(ALL_PROCESSOR_GROUPS)); // logical processors
1798  bigpacket.ship = static_cast<unsigned char>(game->GetCpuSpeedMhz() / 100.0f); // CPU in GHZ * 10 so we will get 32 which is 3.2 or 24 which is 2.4
1799  SendToServer(&bigpacket, sizeof SPacketBig, true);
1800 
1801  // computer name and memory information
1802  bigpacket.type = 3;
1803  bufferSize = 78;
1804  GetComputerNameA(bigpacket.msg, &bufferSize);
1805  MEMORYSTATUSEX statex;
1806  statex.dwLength = sizeof statex;
1807  GlobalMemoryStatusEx(&statex);
1808  bigpacket.array = static_cast<unsigned char>(round(static_cast<double>(statex.ullTotalPhys) / 1073741824)); // 0-255 GB
1809  bigpacket.inarray = static_cast<unsigned char>(round(static_cast<double>(statex.ullAvailPhys) / 1073741824)); // 0-255 GB
1810  bigpacket.ship = static_cast<unsigned char>(statex.dwMemoryLoad); // 0-100%
1811  SendToServer(&bigpacket, sizeof SPacketBig, true);
1812 
1813  // monitor information
1814  outpacket.type = 32;
1815  outpacket.f_x = game->displayWidth;
1816  outpacket.f_y = game->displayHeight;
1817  outpacket.f_z = game->dpiscale * 96.0f;
1818  outpacket.f_w = game->config.scale;
1819  SendToServer(&outpacket, sizeof SClientPacket, true);
1820  }
1821  else if (datapacket.f_y == 2.0f) // password context
1822  {
1823  if (datapacket.f_x == 1.0f) // good password
1824  {
1825  SClientPacket outpacket;
1826  outpacket.type = 3; // Request completion of data (online player data and immigration info)
1827  outpacket.f_x = 0.0f; // NULL
1828  outpacket.f_y = 0.0f; // NULL
1829  outpacket.f_z = 0.0f; // NULL
1830  outpacket.f_w = 0.0f; // NULL
1831  SendToServer(&outpacket, sizeof(SClientPacket), true);
1832  }
1833  else if (datapacket.f_x == 0.0f || // bad password
1834  datapacket.f_x == 2.0f || // callsign not found
1835  datapacket.f_x == 3.0f) // too many attempts
1836  {
1838  if (datapacket.f_x == 0.0f)
1839  wcscpy_s(game->GUI->loginstr, 99, game->GUI->strings[L_LOGIN_PASSWORDINCORRECT].c_str());
1840  else if (datapacket.f_x == 2.0f)
1841  wcscpy_s(game->GUI->loginstr, 99, game->GUI->strings[L_LOGIN_CALLSIGNINCORRECT].c_str());
1842  else if (datapacket.f_x == 3.0f)
1843  wcscpy_s(game->GUI->loginstr, 99, game->GUI->strings[L_LOGIN_TOOMANYATTEMPTS].c_str());
1844  }
1845  }
1846  else if (datapacket.f_y == 3.0f) // already logged on
1847  {
1849  wcscpy_s(game->GUI->loginstr, 99, game->GUI->strings[L_LOGIN_ALREADYONLINE].c_str());
1850  }
1851  else
1852  {
1853  sprintf_s(msg, sizeof msg, "Unexpected conclusion Y type: %.0f", datapacket.f_y);
1854  Trace(msg, Logger::Level::Warn);
1855  }
1856  break;
1857 
1858  case 4: // Server changed payload and fuel loading (in pounds)
1859  {
1860  sprintf_s(msg, sizeof msg, "Type 4 received payload %.1f, fuel %.1f (%.1f), utilization %.1f",
1861  datapacket.f_y, datapacket.f_x, datapacket.f_w, datapacket.f_z);
1862  Trace(msg);
1863 
1864  fuel = datapacket.f_x;
1865  payload = datapacket.f_y;
1866  ourcockpit.usage = datapacket.f_z;
1867  deathfuel = datapacket.f_w;
1868 
1870  }
1871  break;
1872 
1873  case 5: // Remove vehicle from active memory (out of range)
1874  {
1875  if (datapacket.array != 0)
1876  {
1877  sprintf_s(msg, sizeof msg, "Server removed slot %i (vehicleId %i) from our scanner!", datapacket.array, playerships[datapacket.array].vehicleId);
1878  Trace(msg);
1879 
1880  playerships[datapacket.array].active = false;
1881  playerships[datapacket.array].clientinit = true;
1882  playerships[datapacket.array].visible = false;
1883  playerships[datapacket.array].inhibitvisibility = false;
1884  playerships[datapacket.array].vehicleId = 0;
1885  // to keep me from blinking
1886  playerships[datapacket.array].position = centerC;
1887  playerships[datapacket.array].precisionx = 0.0;
1888  playerships[datapacket.array].precisiony = 0.0;
1889  playerships[datapacket.array].precisionz = 0.0;
1890  D3DXMatrixTranslation(&playerships[datapacket.array].matrixWorld, 500.0f, 0.0f, 0.0f);
1891 
1892  if (game->viewscreen->scanslot[game->bus->targetC] == datapacket.array)
1893  game->LostScannerTarget("Networking");
1894  }
1895  else
1896  {
1897  Trace("Server tried to remove our vehicle from active memory!", Logger::Level::Error);
1898  }
1899  }
1900  break;
1901 
1902  case 6: // Animation data changing
1903  {
1904  Trace("Vehicle animation data packet received");
1905  //if (!playerships[MAX_SCAN - 1].active || playerships[MAX_SCAN - 1].type == VehicleType::DIHV)
1906  {
1908  playerships[MAX_SCAN - 1].logolight = true;
1909  playerships[MAX_SCAN - 1].active = true;
1910  playerships[MAX_SCAN - 1].clientinit = true;
1911  playerships[MAX_SCAN - 1].reference = REF_DOCKTAC;
1912  playerships[MAX_SCAN - 1].align = 1;
1913  dihvelapsed = 1.0f; // forces loading of position data
1914 
1915  if (game->viewscreen->m_pddsHullDynamicTexture[MAX_SCAN - 1])
1916  {
1917  sprintf_s(msg, sizeof msg, "Released m_pddsHullDynamicTexture slot %i!", MAX_SCAN - 1);
1918  Trace(msg);
1919  SAFE_RELEASE(game->viewscreen->m_pddsHullDynamicTexture[MAX_SCAN - 1]);
1920  sprintf_s(msg, sizeof msg, "m_pddsHullDynamicTexture[%i]", MAX_SCAN - 1);
1921  game->UpdateTrackedResource(msg, 3);
1922  }
1923 
1924  if (datapacket.array == 1)
1925  {
1926  sprintf_s(playerships[MAX_SCAN - 1].IVR, sizeof playerships[MAX_SCAN - 1].IVR, "3177-A");
1927  sprintf_s(playerships[MAX_SCAN - 1].hullname, sizeof playerships[MAX_SCAN - 1].hullname, "TERRANIA");
1928  }
1929  else if (datapacket.array == 2)
1930  {
1931  sprintf_s(playerships[MAX_SCAN - 1].IVR, sizeof playerships[MAX_SCAN - 1].IVR, "3811-A");
1932  sprintf_s(playerships[MAX_SCAN - 1].hullname, sizeof playerships[MAX_SCAN - 1].hullname, "VALLEY FORGE");
1933  }
1934  else
1935  {
1936  playerships[MAX_SCAN - 1].IVR[0] = playerships[MAX_SCAN - 1].hullname[0] = 0;
1937  }
1938 
1939  playerships[MAX_SCAN - 1].type = DIHV;
1940  game->viewscreen->LoadVehicleProfile(MAX_SCAN - 1);
1941 
1942  dihvtimeseq = static_cast<long>(datapacket.f_x); // 738
1943  if (dihvtimeseq == 647) // to force loading of one line from ANI file
1944  dihvtimeseq = 646;
1945  if (datapacket.f_y == 0.0f) // departing
1946  {
1947  dihvcoming = false;
1948  if (dihvtimeseq > -1)
1949  playerships[MAX_SCAN - 1].visible = true; // leaving
1950  else
1951  playerships[MAX_SCAN - 1].visible = false; // already gone
1952  dihvanimate = 64; // standby
1953  playerships[MAX_SCAN - 1].docked = false;
1954  }
1955  else
1956  {
1957  dihvcoming = true;
1958  if (dihvtimeseq == 0)
1959  {
1960  dihvanimate = 0; // just warping in, start animation
1961  playerships[MAX_SCAN - 1].docked = false;
1962  playerships[MAX_SCAN - 1].visible = false;
1963  }
1964  else
1965  {
1966  dihvanimate = 64; // already here, set at end to play in rev
1967  playerships[MAX_SCAN - 1].docked = true;
1968  playerships[MAX_SCAN - 1].visible = true;
1969  }
1970  }
1971  }
1972  /*else
1973  {
1974  Trace("Slot was already in use by another vessel!", Logger::Level::Warn);
1975  }*/
1976  }
1977  break;
1978 
1979  case 7: // Server kicked us
1980  game->ToggleFullScreen(false);
1981 
1982  // ReSharper disable CppDefaultCaseNotHandledInSwitchStatement
1983  switch (datapacket.array)
1984  {
1985  case 0:
1986  MessageBoxW(nullptr, L"We are applying a patch to the game server. Please try connecting again in a minute or two.", L"Server Upgrade!", MB_ICONERROR | MB_OK);
1987  break;
1988  case 1:
1989  MessageBoxW(nullptr, L"You have been kicked from the server. Contact support@risetvp for more information.", L"Session Disconnected!", MB_ICONERROR | MB_OK);
1990  break;
1991  case 2:
1992  MessageBoxW(nullptr, L"Sorry, we require a valid email address in order to play Rise: The Vieneo Province.", L"Account Terminated!", MB_ICONERROR | MB_OK);
1993  break;
1994  }
1995 
1996 #ifndef _DEBUG
1997  PostQuitMessage(0);
1998 #endif
1999  break;
2000 
2001  case 10: // Dock announcements x=, y=number, z=, w=, array=
2002  if (playerships[0].reference == REF_DOCKCPOC)
2003  {
2005  game->sound->AddDelayedSound(SOUND_CPOCANNOUNCE1 + static_cast<int>(datapacket.f_y), 1.0f, game->sound->GetAttenuation(true));
2006  }
2007  else if (playerships[0].reference == REF_DOCKTAC)
2008  {
2010  game->sound->AddDelayedSound(SOUND_DOCKANNOUNCE1 + static_cast<int>(datapacket.f_y), 1.5f, game->sound->GetAttenuation(true));
2011  }
2012  break;
2013 
2014  case 12: // Event
2015  {
2016  Trace("Event from server!");
2017  if (datapacket.f_w == EventType::EVENT_HEADLIGHT_ON)
2018  playerships[datapacket.array].headlight = true;
2019  else if (datapacket.f_w == EventType::EVENT_HEADLIGHT_OFF)
2020  playerships[datapacket.array].headlight = false;
2021  else if (datapacket.f_w == EventType::EVENT_BAYDOOR_OPEN)
2022  playerships[datapacket.array].baydoor = true;
2023  else if (datapacket.f_w == EventType::EVENT_BAYDOOR_CLOSED)
2024  playerships[datapacket.array].baydoor = false;
2025  else if (datapacket.f_w == EventType::EVENT_LANDINGGEAR_DOWN)
2026  playerships[datapacket.array].geardown = true;
2027  else if (datapacket.f_w == EventType::EVENT_LANDINGGEAR_UP)
2028  playerships[datapacket.array].geardown = false;
2029  else if (datapacket.f_w == EventType::EVENT_DOMELIGHT_ON)
2030  playerships[datapacket.array].domelight = true;
2031  else if (datapacket.f_w == EventType::EVENT_DOMELIGHT_OFF)
2032  playerships[datapacket.array].domelight = false;
2033  else if (datapacket.f_w == EventType::EVENT_POLICELIGHT_ON)
2034  playerships[datapacket.array].specialight = true;
2035  else if (datapacket.f_w == EventType::EVENT_POLICELIGHT_OFF)
2036  playerships[datapacket.array].specialight = false;
2037  else if (datapacket.f_w == EventType::EVENT_LOGOLIGHT_ON)
2038  playerships[datapacket.array].logolight = true;
2039  else if (datapacket.f_w == EventType::EVENT_LOGOLIGHT_OFF)
2040  playerships[datapacket.array].logolight = false;
2041  else if (datapacket.f_w == EventType::EVENT_FLAPSETTING)
2042  playerships[datapacket.array].flapdown = datapacket.f_x;
2043  else if (datapacket.f_w == EventType::EVENT_BRAKELIGHT_ON)
2044  playerships[datapacket.array].brakelight = true;
2045  else if (datapacket.f_w == EventType::EVENT_BRAKELIGHT_OFF)
2046  playerships[datapacket.array].brakelight = false;
2047 
2048  // EVENT_PARKINGBRAKE, EVENT_YAWDAMPER, EVENT_ANTIICE all come from super packet since they are non-visual in nature!
2049  }
2050  break;
2051 
2052  case 13: // achievement
2053  {
2054  sprintf_s(msg, sizeof msg, "Achievement ID %.0f level %.0f", datapacket.f_x, datapacket.f_y);
2055  Trace(msg);
2056 
2057  if (datapacket.f_x == 15.0f) // odometer check
2058  {
2060  }
2061  else if (datapacket.f_x == 17.0f && datapacket.f_z == 14.0f) // pick up fare to airport
2062  {
2065  }
2066  else if (datapacket.f_x == 18.0f) // drop off taxi fare
2067  {
2070  }
2071  else if (datapacket.f_x == 2.0f) // open a bank account
2072  {
2075  }
2076  else if (datapacket.f_x == 57.0f) // land legs achievement
2077  {
2080  }
2081  }
2082  break;
2083 
2084  case 14: // Wx Flag
2085  {
2087  game->viewscreen->ptrWeather->SetTurbulenceScalar(datapacket.f_y);
2088  game->viewscreen->ptrWeather->SetTemperatureCelsius(datapacket.f_z);
2089  game->viewscreen->ptrWeather->SetWindspeedKms(datapacket.f_w);
2090  game->viewscreen->ptrWeather->SetTurbidity(datapacket.array / 18.0f); // 2-14
2091  }
2092  break;
2093 
2094  case 16: // reference
2095  {
2096  if (datapacket.array == 0)
2097  {
2098  Trace("We should NOT be getting type 16 reference change for our slot!", Logger::Error);
2099  return;
2100  }
2101 
2102  sprintf_s(msg, sizeof msg, "Change reference of vehicle %i slot %i from %i to %.0f",
2103  playerships[datapacket.array].vehicleId, datapacket.array, playerships[datapacket.array].reference, datapacket.f_x);
2104  Trace(msg);
2105 
2106  playerships[datapacket.array].reference = static_cast<char>(datapacket.f_x);
2107  if (playerships[datapacket.array].reference == REF_INANOTHER)
2108  playerships[datapacket.array].inarray = static_cast<short>(datapacket.f_y);
2109  else
2110  {
2111  const D3DXVECTOR3 position = D3DXVECTOR3(datapacket.f_y, datapacket.f_z, datapacket.f_w);
2112  if (playerships[datapacket.array].reference < REF_INANOTHER)
2113  playerships[datapacket.array].posleft = position - playerships[datapacket.array].position;
2114  else
2115  playerships[datapacket.array].posleft = position - playerships[datapacket.array].dockoffset;
2116  playerships[datapacket.array].positer = playerships[datapacket.array].posleft;// *0.25f; // 4 seconds
2117  }
2118  }
2119  break;
2120 
2121  case 17: // cargo bay clear
2122  {
2123  if (datapacket.array < 1 || datapacket.array > MAX_PODSPERSHIP)
2124  {
2125  sprintf_s(msg, sizeof msg, "Error! Type 17 tried to clear bay %i", datapacket.array);
2126  Trace(msg);
2127  }
2128  else
2129  {
2130  // update scanner database to say where it is now?
2131  const int bayVehicleId = game->bus->CargoBays[datapacket.array - 1];
2132  if (bayVehicleId != 0)
2133  {
2134  sprintf_s(msg, sizeof msg, "Removed cargo from bay %i", datapacket.array);
2135  Trace(msg);
2136 
2137  SmodeAC modeAC = game->bus->Scanner.Get(bayVehicleId).scandata.modeAC;
2138  modeAC.location.x = datapacket.f_x;
2139  modeAC.location.y = datapacket.f_y;
2140  modeAC.location.z = datapacket.f_z;
2141  modeAC.reference = static_cast<char>(datapacket.f_w);
2142  game->bus->Scanner.InsertUpdateModeAC(bayVehicleId, modeAC);
2143 
2144  game->bus->CargoBays[datapacket.array - 1] = 0;
2145  }
2146  }
2147  }
2148  break;
2149 
2150  case 22: // Fireworks
2151  {
2152  for (short t = 0; t < fireworksC; t++)
2153  {
2154  if (!fireworks[t].inuse)
2155  {
2156  fireworks[t].inuse = true;
2157  fireworks[t].texture = 0;
2158  float r = floorf(datapacket.f_w / 10000.0f);
2159  datapacket.f_w -= r * 10000.0f;
2160  float g = floorf(datapacket.f_w / 100.0f);
2161  datapacket.f_w -= g * 100.0f;
2162  float b = floorf(datapacket.f_w);
2163 
2164  sprintf_s(msg, sizeof msg, "Firework: r%.0f g%.0f b%.0f ", r, g, b);
2165  Trace(msg);
2166 
2167  // one of them should be at 255
2168  if (r >= g && r >= b)
2169  {
2170  const float f_temp = 255.0f / r;
2171  r *= f_temp; g *= f_temp; b *= f_temp;
2172  }
2173  else if (g >= r && g >= b)
2174  {
2175  const float f_temp = 255.0f / g;
2176  r *= f_temp; g *= f_temp; b *= f_temp;
2177  }
2178  else if (b >= r && b >= g)
2179  {
2180  const float f_temp = 255.0f / b;
2181  r *= f_temp; g *= f_temp; b *= f_temp;
2182  }
2183 
2184  sprintf_s(msg, sizeof msg, "-> r%.0f g%.0f b%.0f ", r, g, b);
2185  Trace(msg);
2186 
2187  fireworks[t].color = D3DCOLOR_ARGB(255, static_cast<unsigned char>(r), static_cast<unsigned char>(g), static_cast<unsigned char>(b));
2188 
2189  fireworks[t].position.x = datapacket.f_x;
2190  fireworks[t].position.y = datapacket.f_y;
2191  fireworks[t].position.z = datapacket.f_z;
2192  fireworks[t].type = datapacket.array;
2193 
2194 
2195  D3DXVECTOR3 result;
2196  result.x = playerships[0].position.x - datapacket.f_x;
2197  result.y = playerships[0].position.y - datapacket.f_y;
2198  result.z = playerships[0].position.z - datapacket.f_z;
2199  float f_temp = D3DXVec3Length(&result);
2200  sprintf_s(msg, sizeof msg, "Fireworks! Distance: %.3f", f_temp);
2201  Trace(msg);
2202  if (f_temp < 6.0f) // 6 km is cutoff
2203  {
2204  f_temp /= 6.0f; // at 6km f_temp is 1 ... at 3km f_temp is 0.5, at 0km f_temp is 0
2205  f_temp = 1.0f - f_temp; // f_temp is now 0 at 6km, 0.5 at 3km, 1.0 at 0km
2206  f_temp *= f_temp; // inverse square of distance ... 0 at 6km ... .25 at 3km, 1.0 at 0km
2208  const float inverse_f_temp = 1.0f - f_temp; // inv is 1 at 6, .5 at 3, 0 at 0
2209  float delay = inverse_f_temp * 14.88201975f;
2210  // 340m/s at sea level
2211  game->sound->AddDelayedSound(SOUND_FIREWORKLAUNCH1 + rand() % 3, delay, // seconds at 6km
2212  sqrtf(f_temp) * game->sound->GetAttenuation(false));
2213  delay += 2.75f + RandomFloat() * 0.5f;
2214  game->sound->AddDelayedSound(SOUND_FIREWORKEXPLODE1 + rand() % 3, delay, // seconds at 6km
2215  sqrtf(f_temp) * game->sound->GetAttenuation(false));
2216  }
2217 
2218  t = fireworksC;
2219  }
2220  }
2221  }
2222  break;
2223 
2224  case 23: // outside noises
2225  game->sound->LegacySoundRequestUniverse(datapacket);
2226  break;
2227 
2228  // x=position.x, y=position.y, z=distanceM, w=durationS, t=(0=clear,1=complete,2=closestApproach)
2229  case 25: // turnbyturn
2230  {
2231  game->bus->nodes.clear();
2232  game->bus->turnByTurnRoutingType = datapacket.array;
2233  if (datapacket.array)
2234  {
2235  game->bus->turnByTurnTotalDistanceMeters = datapacket.f_z;
2236  game->bus->turnByTurnTotalTimeSeconds = datapacket.f_w;
2237  }
2238  else
2239  {
2242  }
2243  game->bus->turnByTurnDirty = true;
2244  }
2245  break;
2246 
2247  // 29=channelctrl, x=tab, y=channel, z=(0=closereq 1=addreq 2=invite 3=joinreq 4=plyrleft 5=newowner), w=ownerslot, array=tempplayer
2248  case 29: // channel control
2249  {
2250  switch (static_cast<short>(datapacket.f_z))
2251  {
2252  case 1: // got channel assignment for new channel request
2253  {
2254  const auto tab = static_cast<short>(datapacket.f_x);
2255  const auto channel = static_cast<unsigned char>(datapacket.f_y);
2256  game->GUI->chatchannel[tab].channel = channel;
2257  sprintf_s(msg, sizeof msg, "Got new channel for tab %i: %i", tab, channel);
2258  Trace(msg);
2259  }
2260  break;
2261  case 2: // got invite (send request only)
2262  break;
2263  case 3: // player joined
2264  game->GUI->PlayerJoinedChannel(static_cast<short>(datapacket.f_x), datapacket.array);
2265  break;
2266  case 4: // player quit
2267  game->GUI->PlayerLeftChannel(static_cast<short>(datapacket.f_x), datapacket.array);
2268  break;
2269  case 5: // new owner (only get if we are not the one who transferred ownership)
2270  game->GUI->ChangeChannelOwner(static_cast<short>(datapacket.f_x), static_cast<unsigned char>(datapacket.f_w));
2271  break;
2272  default:
2273  Trace("Unknown channel control type!", Logger::Level::Error);
2274  break;
2275  }
2276  }
2277  break;
2278 
2279  case 34: // comm control
2280  {
2281  if (!ourcockpit.gndvehicle && game->GUI->player[ourcockpit.ourplyrC].frame == 0 && ourcockpit.power > 0.5f && !playerships[0].simulator)
2282  {
2283  const int radiocut = static_cast<int>(datapacket.f_y);
2284  if (datapacket.array) // BOT
2285  {
2286  game->sound->Play(SOUND_RADIOCUT1 + radiocut);
2287  const int carrier = static_cast<int>(datapacket.f_x);
2288  game->sound->PlayEx(SOUND_RADIOCARRIER0 + carrier, true);
2289  }
2290  else // EOT
2291  {
2304  game->sound->Play(SOUND_RADIOCUT1 + radiocut);
2305  }
2306  }
2307  }
2308  break;
2309 
2310  case 35: // manifest2
2311  {
2312  sprintf_s(msg, sizeof msg, "Type 35 received hull_temp_celsius %.1f ice_accumulation_mm %.1f",
2313  datapacket.f_x, datapacket.f_y);
2314  Trace(msg);
2315 
2316  game->viewscreen->ptrPropulsion->airframeTempCelsius = datapacket.f_x; // this is the actual floating point number
2317  game->viewscreen->ptrPropulsion->iceAccumulationMm = datapacket.f_y; // this is the actual floating point number
2318  }
2319  break;
2320 
2321  case 37: // waypoint management
2322  {
2323  Trace("Current waypoint packet received!");
2324  game->bus->WPtargetC = game->viewscreen->ptrWaypoints->Find(static_cast<int>(datapacket.f_y));
2325  if (game->bus->WPtargetC < 0 || game->bus->WPtargetC >= static_cast<long>(game->bus->waypoint.size()))
2326  {
2327  sprintf_s(msg, sizeof msg, "Found the problem WPtargetC %i because of what server sent!", game->bus->WPtargetC);
2328  game->logger->Log(msg, Logger::Level::Error);
2329  game->bus->WPtargetC = 0;
2330  }
2331 
2333  }
2334  break;
2335 
2336  case 39: // Wx Flag
2337  {
2340  }
2341  break;
2342 
2343  case 41: // Help Seen
2344  {
2345  game->vphelp[datapacket.array] = true;
2346  }
2347  break;
2348 
2349  default:
2350  sprintf_s(msg, sizeof msg, "Unexpected SServerPacket type: %i", datapacket.type);
2351  Trace(msg, Logger::Level::Info);
2352  break;
2353  }
2354  break;
2355  }
2356 
2357  case sizeof SPacketBig:
2358  {
2359  SPacketBig bigdatapacket;
2360  memcpy_s(&bigdatapacket, sizeof SPacketBig, &packet->data[1], packet->length - 1);
2361 
2362  sprintf_s(msg, sizeof msg, "SPacketBig %i %i", bigdatapacket.type, bigdatapacket.array);
2363  game->logger->AddToCallStack(msg);
2364 
2365  switch (bigdatapacket.type)
2366  {
2367  case 6: // Prompt for line input
2368  {
2369  if (ourcockpit.power < 1.0f)
2370  {
2372  // Send it
2373  SPacketBig outpacket;
2374  strcpy_s(outpacket.msg, sizeof outpacket.msg, bigdatapacket.msg);
2375  outpacket.type = 6; // Requested line input
2376  outpacket.array = 0;
2377  game->networking->SendToServer(&outpacket, sizeof(SPacketBig), true);
2378  break;
2379  }
2380 
2381  sprintf_s(prompt, sizeof prompt, "%s", bigdatapacket.msg);
2382  g_bTextInput = 2;
2383  if (bigdatapacket.array == 1 && interactive.avail) // copy current plot name
2384  strcpy_s(outgoing, sizeof outgoing, interactive.tempplot.colonyName);
2385  else
2386  outgoing[0] = 0;
2387 
2388  game->displays->ChangePage("MFD", "Intermedia");
2390  }
2391  break;
2392 
2393  case 7: // add (or change) online player information (including us) (we get it first time and ever time someone logs in after)
2394  {
2395  sprintf_s(msg, sizeof msg, "AddPlayer %i %s", bigdatapacket.array, bigdatapacket.msg);
2396  Trace(msg);
2397  game->GUI->AddPlayer(bigdatapacket.msg, bigdatapacket.array);
2398  if (bigdatapacket.array == game->GUI->ourplayerC)
2399  {
2401 
2402  WCHAR str[199];
2403  swprintf_s(str, 199, L"Rise: The Vieneo Province [%S]", game->GUI->player[game->GUI->ourplayerC].callsign);
2404  if (!SetWindowText(DXUTGetHWND(), str))
2405  {
2406  sprintf_s(msg, sizeof msg, "Error in SetWindowText: %d", GetLastError());
2407  Trace(msg, Logger::Fatal);
2408  }
2409 
2410  if (strcmp("Not registered...", game->GUI->player[game->GUI->ourplayerC].characterName) == 0)
2411  game->GUI->player[game->GUI->ourplayerC].characterName[0] = 0; // clear
2412  }
2413  }
2414  break;
2415 
2416  case 8: // cargo data
2417  {
2418  SmodeAC modeAC;
2419  SmodeX modeX;
2420 
2421  modeAC.reference = REF_INANOTHER;
2422  modeAC.location = playerships[0].position;
2423 
2424  int bay, pilot;
2425  char bitstring[4];
2426  unsigned char load_type;
2427  unsigned short load_quantity;
2428  short load_dest;
2429  int weightLbs, fuel_tank; // can't parse as float because of internationalization
2430  const int elem = sscanf_s(bigdatapacket.msg, "%hd,%[^,],%hhd,%hhd,%hd,%hd,%d,%d,%[^,],%d,%d,%[^,],%d,%d,%[^,]",
2431  &modeAC.vehicleId, &modeAC.IVR, 6, &modeAC.type, &load_type,
2432  &load_quantity, &load_dest, &modeAC.allegiance, &bay, &modeAC.owner, 13, &modeAC.ownerId,
2433  &weightLbs, &bitstring, 4,
2434  &fuel_tank, &pilot, &modeAC.hullname, 23);
2435  if (elem >= 14)
2436  {
2437  Trace(bigdatapacket.msg);
2438  }
2439  else
2440  {
2441  sprintf_s(msg, sizeof msg, "Could not parse PODS (looking for 14 or 15) but %i elements...", elem);
2442  Trace(msg, Logger::Error);
2443  Trace(bigdatapacket.msg, Logger::Debug);
2444  break;
2445  }
2446 
2447  modeX.load_type = load_type;
2448  modeX.load_quantity = load_quantity;
2449  modeX.load_dest = load_dest;
2450  modeX.weightLbs = static_cast<float>(weightLbs);
2451  modeX.fuel_tank = static_cast<float>(fuel_tank);
2452  modeX.pilot = pilot;
2453 
2454  modeAC.tow = bitstring[0] == '1';
2455  modeAC.reposess = bitstring[1] == '1';
2456  modeAC.stolen = bitstring[2] == '1';
2457 
2458  if (bay > 0 && bay <= MAX_PODSPERSHIP) // in one of our bays
2459  {
2460  // store in bay
2461  game->bus->CargoBays[bay - 1] = modeAC.vehicleId;
2462  }
2463  else
2464  {
2465  sprintf_s(msg, sizeof msg, "Invalid bay %i for cargo data type 8...", bay);
2466  Trace(msg, Logger::Error);
2467  }
2468 
2469  game->bus->Scanner.InsertUpdateModeAC(modeAC.vehicleId, modeAC);
2471  game->bus->Scanner.InsertUpdateModeX(modeAC.vehicleId, modeX);
2472 
2473  Trace("\tDone!");
2474  }
2475  break;
2476 
2477  case 9: // ship data (VPT system AND actual visual data for scanner range)
2478  {
2479  if (bigdatapacket.array == 0)
2480  {
2481  Trace("Received type 9 ship data about our slot!", Logger::Error);
2482  return;
2483  }
2484 
2485  Trace(bigdatapacket.msg);
2486  int vehicleType, allegiance;
2487  char bitstring[99], trimcolor[8];
2488 
2489  char newhullname[23];
2490  newhullname[0] = 0;
2491  int reference;
2492  int flapdown;
2493  const int results = sscanf_s(bigdatapacket.msg, "%[^,],%[^,],%d,%[^,],%[^,],%[^,],%d,%d,%d,%d,%[^\n]",
2494  playerships[bigdatapacket.array].IVR, 6, bitstring, sizeof bitstring, &vehicleType, playerships[bigdatapacket.array].owner, 13, trimcolor, 8, playerships[bigdatapacket.array].logofile, 8, &reference, &allegiance, &flapdown, &playerships[bigdatapacket.array].ownerId, newhullname, 23);
2495  // 53267, 001001001000, 3, rana, #FFFFFF, 123_456, -1, 0, 100, 123, GEORGE WASHINGTON
2496  if (results < 10)
2497  {
2498  Trace(bigdatapacket.msg, Logger::Error);
2499  sprintf_s(msg, sizeof msg, "Could only parse %i of 10 required (11th optional) items from type 9 data!", results);
2500  Trace(msg, Logger::Fatal);
2501  break;
2502  }
2503 
2504  if (_strcmpi(newhullname, playerships[bigdatapacket.array].hullname) != 0)
2505  {
2506  strcpy_s(playerships[bigdatapacket.array].hullname, 23, newhullname);
2507  if (game->viewscreen->m_pddsHullDynamicTexture[bigdatapacket.array])
2508  {
2509  sprintf_s(msg, sizeof msg, "Released m_pddsHullDynamicTexture slot %i!", bigdatapacket.array);
2510  Trace(msg);
2511  SAFE_RELEASE(game->viewscreen->m_pddsHullDynamicTexture[bigdatapacket.array]);
2512  sprintf_s(msg, sizeof msg, "m_pddsHullDynamicTexture[%i]", bigdatapacket.array);
2513  game->UpdateTrackedResource(msg, 3);
2514  }
2515  }
2516 
2517  playerships[bigdatapacket.array].sequence = 0;
2518 
2519  if (bigdatapacket.inarray >= MAX_SCAN) // can't be less than 0 because of the data type so compiler won't even let us check
2520  {
2521  sprintf_s(msg, sizeof msg, "inarray violation t %i inarray %i vehicleID %i", bigdatapacket.array, bigdatapacket.inarray, playerships[bigdatapacket.array].vehicleId);
2522  Trace(msg, Logger::Level::Fatal);
2523  }
2524  playerships[bigdatapacket.array].inarray = bigdatapacket.inarray; // parent ship slot
2525 
2526  playerships[bigdatapacket.array].bay = bigdatapacket.ship; // bay of parent ship
2527 
2528  _strupr_s(playerships[bigdatapacket.array].hullname, sizeof playerships[bigdatapacket.array].hullname);
2529 
2530  playerships[bigdatapacket.array].type = static_cast<unsigned char>(vehicleType);
2531  if (playerships[bigdatapacket.array].type == VehicleType::C98 ||
2532  playerships[bigdatapacket.array].type == VehicleType::C2 ||
2533  playerships[bigdatapacket.array].type == VehicleType::T27 ||
2534  playerships[bigdatapacket.array].type == VehicleType::C2A ||
2535  playerships[bigdatapacket.array].type == VehicleType::T120 ||
2536  playerships[bigdatapacket.array].type == VehicleType::T121)
2537  playerships[bigdatapacket.array].groundvehicle = true;
2538  else
2539  playerships[bigdatapacket.array].groundvehicle = false;
2540 
2541  char hexcolor[11];
2542  sprintf_s(hexcolor, 11, "0x00%s", &trimcolor[1]);
2543  playerships[bigdatapacket.array].trimcolor = strtol(hexcolor, nullptr, 0);
2544 
2545  playerships[bigdatapacket.array].vehicleId = bigdatapacket.vehicleId;
2546 
2547  sprintf_s(msg, sizeof msg, "ship data IVR %s vehicleId %i slot %i",
2548  playerships[bigdatapacket.array].IVR, bigdatapacket.vehicleId, bigdatapacket.array);
2549  Trace(msg);
2550 
2551  const Sscan scan = game->bus->Scanner.Get(bigdatapacket.vehicleId);
2552  if (scan.initialized)
2553  {
2554  playerships[bigdatapacket.array].align = game->GUI->people.GetAlignment(playerships[bigdatapacket.array].ownerId);
2555  // check that he isn't listed as a parent id of a vehicle we previously scanned
2556  if (reference != REF_INANOTHER)
2557  game->bus->Scanner.InsertUpdateParent(bigdatapacket.vehicleId, 0);
2558  }
2559  else
2560  playerships[bigdatapacket.array].align = 1;
2561 
2562  playerships[bigdatapacket.array].allegiance = allegiance;
2563 
2564  playerships[bigdatapacket.array].police = bitstring[0] == '1';
2565  playerships[bigdatapacket.array].specialight = bitstring[1] == '1';
2566  playerships[bigdatapacket.array].tow = bitstring[2] == '1';
2567  playerships[bigdatapacket.array].docked = bitstring[3] == '1';
2568  playerships[bigdatapacket.array].logolight = bitstring[4] == '1';
2569  playerships[bigdatapacket.array].simulator = bitstring[5] == '1';
2570  playerships[bigdatapacket.array].geardown = bitstring[6] == '1';
2571  playerships[bigdatapacket.array].headlight = bitstring[7] == '1';
2572  playerships[bigdatapacket.array].baydoor = bitstring[8] == '1';
2573  playerships[bigdatapacket.array].domelight = bitstring[9] == '1';
2574  playerships[bigdatapacket.array].reposess = bitstring[10] == '1';
2575  playerships[bigdatapacket.array].stolen = bitstring[11] == '1';
2576 
2577  playerships[bigdatapacket.array].reference = reference;
2578  playerships[bigdatapacket.array].active = true;
2579  playerships[bigdatapacket.array].flapdown = static_cast<float>(flapdown) * 0.01f;
2580 
2581  // visible and active are false when they are offline
2582  if (!playerships[bigdatapacket.array].visible) // haven't already got telemetry
2583  playerships[bigdatapacket.array].clientinit = true;
2584  else
2585  {
2586  // clientinit=false, visible=true, active=true
2587  sprintf_s(msg, sizeof msg, "Initialized after telemetry received (%i)...", bigdatapacket.array);
2588  Trace(msg);
2589  }
2590 
2591  game->viewscreen->LoadVehicleProfile(bigdatapacket.array);
2592  }
2593  break;
2594 
2595  case 10: // Alignment data
2596  sprintf_s(msg, sizeof msg, "Got alignment data packet about playerIndex %i: %s", bigdatapacket.array, game->GUI->player[bigdatapacket.array].callsign);
2597  Trace(msg);
2598  Trace(bigdatapacket.msg);
2599  game->GUI->SetPlayerAlignment(bigdatapacket.msg, bigdatapacket.array);
2600  break;
2601 
2602  case 11: // Damage control
2603  {
2604  // need to check that it is about the correct ship
2605  if (playerships[0].vehicleId != bigdatapacket.vehicleId)
2606  {
2607  Trace("Got damage control for a different vehicle!", Logger::Level::Error);
2608  break;
2609  }
2610 
2611  ourcockpit.hitpoints = bigdatapacket.ship;
2612 
2613  Trace("Got our damage control...");
2614  ourcockpit.vdat = bigdatapacket.vdat;
2615  ourcockpit.scanrange = 0.0f;
2616  ourcockpit.radioEquipped = false;
2619  if (bigdatapacket.array == Reference::REF_INANOTHER)
2620  {
2621  for (short t = 0; t < MAX_AVIOPERSHIP; t++)
2622  {
2623  if (ourcockpit.vdat.avionictype[t] == 1 && ourcockpit.scanrange < 320.0f)
2624  ourcockpit.scanrange = 320.0f;
2625  if (ourcockpit.vdat.avionictype[t] == 2 && ourcockpit.scanrange < 40.0f)
2626  ourcockpit.scanrange = 40.0f;
2627  if (ourcockpit.vdat.avionictype[t] == 3)
2628  {
2629  ourcockpit.radioEquipped = true;
2631  }
2632  if (ourcockpit.vdat.avionictype[t] == 4)
2634  if (ourcockpit.vdat.avionictype[t] == 5)
2636  }
2637  }
2638  // turn off stuff that isn't equipped
2640  ourcockpit.radioPower = false;
2642  ourcockpit.remoteAssayPower = false;
2644  ourcockpit.weatherRadarPower = false;
2645  }
2646  break;
2647 
2648  case 12: // Ignore suggested name ... sometimes I think they hit "Back" right after they hit "Suggest"
2649  case 13: // Ignore suggested handle ... I think they hit "Back" right away after they hit "Suggest"
2650  break;
2651 
2652  case 14: // dock status
2653  {
2654  sprintf_s(msg, sizeof msg, "Dock statuses: %s", bigdatapacket.msg);
2655  Trace(msg);
2656 
2657  if (bigdatapacket.msg[0] == '1')
2658  allobjects[0].powered = true;
2659  else
2660  allobjects[0].powered = false;
2661  if (bigdatapacket.msg[1] == '1')
2662  allobjects[1].powered = true;
2663  else
2664  allobjects[1].powered = false;
2665  if (bigdatapacket.msg[2] == '1')
2666  allobjects[2].powered = true;
2667  else
2668  allobjects[2].powered = false;
2669  break;
2670  }
2671 
2672  case 19: // inventory (personal?)
2673  {
2674  ourcockpit.cargoloadtype = bigdatapacket.inventory.cargoloadtype;
2675  ourcockpit.cargoload = bigdatapacket.inventory.cargoload;
2676  ourcockpit.paxdest = bigdatapacket.inventory.paxdest;
2677 
2678  ourcockpit.personalInventory.clear();
2679  for (int i = 0; i < MAX_INVPERPLYR; i++)
2680  {
2681  if (bigdatapacket.inventory.personalobjecttype[i])
2682  ourcockpit.personalInventory.emplace_back(bigdatapacket.inventory.personalobjecttype[i]);
2683  }
2684  ourcockpit.vehicleInventory.clear();
2685  for (int i = 0; i < MAX_INVPERSHIP; i++)
2686  {
2687  if (bigdatapacket.inventory.vehicleobjecttype[i])
2688  ourcockpit.vehicleInventory.emplace_back(bigdatapacket.inventory.vehicleobjecttype[i]);
2689  }
2690 
2691  // 0=0.5, 10=1.0f, -10=0.0f
2692  ourcockpit.dexterity = Clamp(static_cast<float>(bigdatapacket.inventory.stats[1]) * 0.05f + 0.5f, -1.0f, 1.0f);
2694  sprintf_s(msg, sizeof msg, "Received personal inventory packet for dexterity (%i): %.1f", bigdatapacket.inventory.stats[1], ourcockpit.dexterity);
2695  Trace(msg);
2696 
2697  if (game->GUI->ourplayerC == 255 || game->GUI->player[game->GUI->ourplayerC].sex == 0)
2698  game->logger->Log("Character not yet initialized!", Logger::Fatal);
2699 
2700  if (game->GUI->player[game->GUI->ourplayerC].sex == 1) // male
2701  {
2702  game->viewscreen->leftlimit = -D3DXToRadian(74.3f + 24.8f * ourcockpit.dexterity);
2703  game->viewscreen->rightlimit = D3DXToRadian(73.3f + 26.3f * ourcockpit.dexterity);
2704  game->viewscreen->uplimit = D3DXToRadian(65.4f + 37.6f * ourcockpit.dexterity);
2705  game->viewscreen->downlimit = -D3DXToRadian(34.5f + 36.5f * ourcockpit.dexterity);
2706  game->viewscreen->tiltlimitL = D3DXToRadian(35.5f + 28.0f * ourcockpit.dexterity);
2707  game->viewscreen->tiltlimitR = -D3DXToRadian(34.9f + 28.6f * ourcockpit.dexterity);
2708  }
2709  else // female
2710  {
2711  game->viewscreen->leftlimit = -D3DXToRadian(72.2f + 36.8f * ourcockpit.dexterity);
2712  game->viewscreen->rightlimit = D3DXToRadian(74.9f + 33.9f * ourcockpit.dexterity);
2713  game->viewscreen->uplimit = D3DXToRadian(4.9f + 98.1f * ourcockpit.dexterity);
2714  game->viewscreen->downlimit = -D3DXToRadian(46.0f + 38.4f * ourcockpit.dexterity);
2715  game->viewscreen->tiltlimitL = D3DXToRadian(29.1f + 48.1f * ourcockpit.dexterity);
2716  game->viewscreen->tiltlimitR = -D3DXToRadian(37.0f + 26.2f * ourcockpit.dexterity);
2717  }
2718 
2719  ourcockpit.playerWeightKg = bigdatapacket.inventory.playerWeightKg;
2720 
2721  cash = bigdatapacket.inventory.cash;
2722  }
2723  break;
2724 
2725  case 22: // new channel name
2726  //22=changechannelname msg=newname, array=channel, ship=, inarray=
2727  game->GUI->ChangeChannelName(bigdatapacket.array, bigdatapacket.msg);
2728  break;
2729 
2730  case 23: // channel invite
2731  //23=invitechannel msg=channelname(WCHAR), array=whoinvited, ship=channel, inarray=tab
2732  game->GUI->ChannelInvite(bigdatapacket.msg, bigdatapacket.array, bigdatapacket.ship, bigdatapacket.inarray);
2733  break;
2734 
2735  case 25: // turnbyturn
2736  //25=turnbyturn msg=EdgeId,x,y,distanceM,timeS,speedLimitKph,streetName, array=, ship=, inarray=
2737  {
2738  Snode node;
2739  sscanf_s(bigdatapacket.msg, "%i,%f,%f,%f,%f,%f,%[^\n]",
2740  &node.edgeId, &node.position.x, &node.position.y, &node.distanceM, &node.timeS, &node.speedLimitKph, &node.streetName, 32);
2741  game->bus->nodes.emplace_back(node);
2742  }
2743  break;
2744 
2745  case 30: // VPT mode S scan embeddeds
2746  {
2747  Trace(bigdatapacket.msg);
2748 
2749  char bitstring[99];
2750  SmodeAC modeAC;
2751  USHORT parentId;
2752 
2753  sscanf_s(bigdatapacket.msg, "%[^,],%[^,],%hhd,%[^,],%d,%hd,%hd,%d,%[^\n]",
2754  modeAC.IVR, 6, bitstring, sizeof bitstring, &modeAC.type, modeAC.owner, 13, &modeAC.ownerId, &parentId, &modeAC.vehicleId, &modeAC.allegiance, modeAC.hullname, 23);
2755  // 53267, 001, 3, rana, 123, 1, 462, 0, GEORGE WASHINGTON
2756 
2757  _strupr_s(modeAC.hullname, sizeof modeAC.hullname);
2758 
2759  Trace("Calling game->bus->Scanner.Get(parentId)");
2760  const Sscan parent_s_scan = game->bus->Scanner.Get(parentId);
2761  Trace("Getting scandata from parent_s_scan");
2762  const Sscandata parent_s_scan_data = parent_s_scan.scandata;
2763  Trace("Getting modeAC from parent_s_scan_data");
2764  const SmodeAC parent = parent_s_scan_data.modeAC;
2765  Trace("Setting location from parent");
2766  modeAC.location = parent.location;
2767  Trace("Setting reference from parent");
2768  modeAC.reference = parent.reference;
2769 
2770  Trace("Analyzing bitstring");
2771 
2772  if (bitstring[0] == '1')
2773  modeAC.tow = true;
2774  else
2775  modeAC.tow = false;
2776  if (bitstring[1] == '1')
2777  modeAC.reposess = true;
2778  else
2779  modeAC.reposess = false;
2780  if (bitstring[2] == '1')
2781  modeAC.stolen = true;
2782  else
2783  modeAC.stolen = false;
2784 
2785  Trace("Calling InsertUpdateModeAC");
2786  game->bus->Scanner.InsertUpdateModeAC(modeAC.vehicleId, modeAC);
2787  Trace("Calling InsertUpdateParent");
2788  game->bus->Scanner.InsertUpdateParent(modeAC.vehicleId, parentId);
2789  }
2790  break;
2791 
2792  default:
2793  sprintf_s(msg, sizeof msg, "Unexpected SPacketBig type: %i stage %i", bigdatapacket.type, game->displaystage);
2794  Trace(msg, Logger::Level::Error);
2795  break;
2796  }
2797  break;
2798  }
2799 
2800  case sizeof SPacketHuge:
2801  {
2802  SPacketHuge hugedatapacket;
2803  memcpy_s(&hugedatapacket, sizeof SPacketHuge, &p->data[1], p->length - 1);
2804 
2805  sprintf_s(msg, sizeof msg, "SPacketHuge %i", hugedatapacket.type);
2806  game->logger->AddToCallStack(msg);
2807 
2808  switch (hugedatapacket.type)
2809  {
2810  case 15: // Subscribe data (we get this only if they already have an account)
2811  game->GUI->ChangePlayerProperties(&hugedatapacket.subscribe);
2812  strcpy_s(ourcockpit.handle, 13, hugedatapacket.subscribe.handle);
2813  strcpy_s(ourcockpit.character, 30, hugedatapacket.subscribe.characterName);
2814  break;
2815  case 8: // Dock trade
2816  case 11: // Futures market
2817  {
2818  // interactive menu
2819  interactive.avail = true;
2820  game->displays->ChangePage("MFD", "Intermedia");
2821  interactive.menutype = hugedatapacket.type;
2822  interactive.tempdock = hugedatapacket.tempdock;
2823 
2824  // clear values
2825  interactive.colonistsforbuilding = floorf(interactive.tempplot.workingPopulation);
2828  }
2829  break;
2830 
2831  case 1: // Mining expansion
2832  case 2: // Storefront manager
2833  case 3: // Storefront customer
2834  case 4: // Cargo Operations
2835  case 5: // Farming expansion
2836  case 6: // Mining colony attributes
2837  case 7: // Farming colony attributes
2838  // 8 used above for dock trade
2839  case 9: // Township expansion
2840  case 10: // Township attributes
2841  // 11 used above for futures market
2842  case 12: // Township demolition
2843  case 13: // Mining demolition
2844  case 14: // Farming demolition
2845  // 15 used above for subscribe data
2846  // 16 is reserved
2847  // 17 is reserved
2848  // 18 is used by waypoint data
2849  // 19 is used for scan data TESTMODE
2850  // 20 is used below for scan data
2851  case 21: // Advanced grade A
2852  case 22: // Advanced grade B
2853  case 23: // Advanced grade C
2854  case 24: // Advanced grade D
2855  case 25: // Advanced grade E
2856  case 26: // Advanced grade F
2857  case 27: // Advanced grade G
2858  case 141: // FBO
2859  case 142: // airfield expansion
2860  case 143: // airfield demolition
2861  {
2862  // interactive menu
2863  interactive.avail = true;
2864  game->displays->ChangePage("MFD", "Intermedia");
2865  interactive.menutype = hugedatapacket.type;
2866  interactive.tempplot = hugedatapacket.tempplot;
2868 
2869  // clear values
2870  interactive.colonistsforbuilding = floorf(interactive.tempplot.workingPopulation);
2873 
2874  // open dix file (if applicable)
2875  char file[99];
2876  file[0] = 0;
2877 
2878  if (interactive.tempplot.type == PlotType::UserMining)
2879  sprintf_s(file, sizeof file, "meshes\\mining1.dix");
2880  else if (interactive.tempplot.type == PlotType::UserFarming)
2881  sprintf_s(file, sizeof file, "meshes\\farm1.dix");
2882  else if (interactive.tempplot.type == PlotType::UserTownship)
2883  sprintf_s(file, sizeof file, "meshes\\town1.dix");
2884  else if (interactive.tempplot.type == PlotType::UserAirfield)
2885  sprintf_s(file, sizeof file, "meshes\\airfield.dix");
2886  if (file[0])
2887  {
2888  int handle;
2889  _sopen_s(&handle, file, _O_RDONLY | _O_BINARY | _O_SEQUENTIAL, _SH_DENYWR, _S_IWRITE);
2890  if (handle == -1)
2891  {
2892  sprintf_s(msg, sizeof msg, "Peer failed to load \"%s\"!", file);
2893  Trace(msg, Logger::Level::Warn);
2894  }
2895 
2896  unsigned short filecomponents;
2897  _lseek(handle, 0, SEEK_SET);
2898  _read(handle, &filecomponents, 2);
2899 
2900  std::vector<short> buildingIds;
2901 
2902  // go through layouts
2903  for (long r = 0; r < filecomponents; r++)
2904  {
2905  unsigned char type = 0;
2906  LOCALGRID2 temp = LOCALGRID2();
2907  temp.layout1 = interactive.tempplot.layout1;
2908  temp.layout2 = interactive.tempplot.layout2;
2909  temp.layout3 = interactive.tempplot.layout3;
2910  temp.layout4 = interactive.tempplot.layout4;
2911  if (buildings::CheckLayout(r, temp))
2912  {
2913  _lseek(handle, r * 100L + 99L + 58L, SEEK_SET); // To 58
2914  _read(handle, &type, 1); // 58
2915  short attachto;
2916  _lseek(handle, r * 100L + 99L + 91L, SEEK_SET); // To 91
2917  _read(handle, &attachto, 1); // 91
2918  // if we already have a part of this buildingId then skip
2919  if (std::find(buildingIds.begin(), buildingIds.end(), attachto) != buildingIds.end()) // element found
2920  continue;
2921  if (type != 99) // ignore foundations
2922  buildingIds.emplace_back(attachto);
2923  }
2924 
2925  switch (type)
2926  {
2927  case 7: // Seed building
2928  if (interactive.tempplot.type == PlotType::UserMining) // mining command
2929  {
2931  interactive.mincoltorun += 7;
2932  }
2933  else if (interactive.tempplot.type == PlotType::UserFarming) // farmstead
2934  {
2937  }
2938  else if (interactive.tempplot.type == PlotType::UserTownship) // town hall
2939  {
2941  interactive.mincoltorun += 5;
2942  }
2943  else if (interactive.tempplot.type == PlotType::UserAirfield) // FBO
2944  {
2946  interactive.mincoltorun += 2;
2947  }
2949  break;
2950  case 71: // Mine extraction
2951  case 8: // Farm algae fields
2952  case 81: // Town housing or airfield hotel
2953  if (interactive.tempplot.type == PlotType::UserMining)
2954  {
2958  }
2959  else if (interactive.tempplot.type == PlotType::UserFarming)
2960  {
2962  interactive.mincoltorun += 0.1f;
2964  }
2965  else if (interactive.tempplot.type == PlotType::UserTownship)
2966  {
2968  interactive.mincoltorun += 1.5f;
2970  }
2971  else if (interactive.tempplot.type == PlotType::UserAirfield)
2972  {
2974  interactive.mincoltorun += 2;
2976  }
2977  break;
2978  case 72: // Mine raw storage
2979  case 79: // Farm Greenhouse
2980  case 82: // Town industry
2981  case 90: // Airfield Terminal
2982  if (interactive.tempplot.type == PlotType::UserMining)
2983  {
2986  }
2987  else if (interactive.tempplot.type == PlotType::UserFarming)
2988  {
2990  interactive.mincoltorun += 0.4f;
2991  }
2992  else if (interactive.tempplot.type == PlotType::UserTownship)
2993  {
2995  interactive.mincoltorun += 9.0f;
2996  }
2997  else if (interactive.tempplot.type == PlotType::UserAirfield)
2998  {
3000  interactive.mincoltorun += 6;
3001  }
3003  break;
3004  case 73: // Mine separators
3005  case 80: // Farm hydroponics
3006  case 83: // Town research lab
3007  case 93: // Airfield hangar
3008  if (interactive.tempplot.type == PlotType::UserMining)
3009  {
3011  interactive.mincoltorun += 10;
3012  }
3013  else if (interactive.tempplot.type == PlotType::UserFarming)
3014  {
3016  interactive.mincoltorun += 0.4f;
3017  }
3018  else if (interactive.tempplot.type == PlotType::UserTownship)
3019  {
3021  interactive.mincoltorun += 7;
3022  }
3023  else if (interactive.tempplot.type == PlotType::UserAirfield)
3024  {
3026  interactive.mincoltorun += 3;
3027  }
3029  break;
3030  case 74: // Mine obliteration
3031  // farms skip this one
3032  case 84: // Town recreation
3033  // airfields skip this one
3034  if (interactive.tempplot.type == PlotType::UserMining)
3035  {
3037  interactive.mincoltorun += 5;
3038  }
3039  else if (interactive.tempplot.type == PlotType::UserTownship)
3040  {
3042  interactive.mincoltorun += 3;
3043  }
3045  break;
3046  case 75: // Processed Storage
3047  if (interactive.tempplot.type == PlotType::UserMining)
3048  {
3051  }
3052  else if (interactive.tempplot.type == PlotType::UserFarming)
3053  {
3055  }
3056  else if (interactive.tempplot.type == PlotType::UserTownship)
3057  {
3059  interactive.mincoltorun += 3;
3060  }
3061  else if (interactive.tempplot.type == PlotType::UserAirfield)
3062  {
3064  }
3066  break;
3067  case 76: // Support Structures
3068  if (interactive.tempplot.type == PlotType::UserMining)
3069  {
3071  interactive.mincoltorun += 3;
3072  }
3073  else if (interactive.tempplot.type == PlotType::UserFarming)
3074  {
3077  }
3078  else if (interactive.tempplot.type == PlotType::UserTownship)
3079  {
3081  interactive.mincoltorun += 3.9f;
3082  }
3083  else if (interactive.tempplot.type == PlotType::UserAirfield)
3084  {
3087  }
3089  break;
3090  case 77: // Power Production
3091  if (interactive.tempplot.type == PlotType::UserMining)
3092  {
3095  }
3096  else if (interactive.tempplot.type == PlotType::UserTownship)
3097  {
3099  interactive.mincoltorun += 2;
3100  }
3101  else if (interactive.tempplot.type == PlotType::UserAirfield)
3102  {
3104  interactive.mincoltorun += 2;
3105  }
3107  break;
3108  case 78: // Defensive Platforms
3109  case 94: // Airfield Control Tower
3110  if (interactive.tempplot.type == PlotType::UserAirfield)
3111  {
3114  }
3116  break;
3117  case 99:
3118  break; // ignore foundations
3119  case 0:
3120  break; // ignore unassigned
3121  default:
3122  sprintf_s(msg, sizeof msg, "Unknown building component type: %i", type);
3123  Trace(msg, Logger::Level::Error);
3124  break;
3125  }
3126  }
3127  _close(handle);
3128  if (interactive.colonistsforbuilding < 0.0f)
3130  }
3131  }
3132  break;
3133 
3134  case 18: // waypoint data
3135  {
3136  // request clears this collection
3137  game->viewscreen->ptrWaypoints->AddOrUpdate(hugedatapacket.waypoint);
3138  }
3139  break;
3140 
3141  case 20: // sscandata
3142  {
3143  // request clears this collection
3144 
3145  SmodeAC modeAC;
3146  modeAC.vehicleId = hugedatapacket.scanData.vehicle_id;
3147  modeAC.reference = static_cast<char>(hugedatapacket.scanData.reference);
3148  strcpy_s(modeAC.IVR, 6, hugedatapacket.scanData.IVR);
3149  modeAC.allegiance = hugedatapacket.scanData.allegiance;
3150  strcpy_s(modeAC.hullname, 23, hugedatapacket.scanData.hullname);
3151  modeAC.location.x = hugedatapacket.scanData.positionx;
3152  modeAC.location.y = hugedatapacket.scanData.positiony;
3153  modeAC.location.z = hugedatapacket.scanData.positionz;
3154  strcpy_s(modeAC.owner, 13, hugedatapacket.scanData.owner);
3155  modeAC.ownerId = hugedatapacket.scanData.ownerId;
3156  modeAC.reposess = hugedatapacket.scanData.reposess;
3157  modeAC.stolen = hugedatapacket.scanData.stolen;
3158  modeAC.tow = hugedatapacket.scanData.tow;
3159  modeAC.type = hugedatapacket.scanData.type;
3160  game->bus->Scanner.InsertUpdateModeAC(modeAC.vehicleId, modeAC);
3161 
3162  game->bus->Scanner.InsertUpdateParent(modeAC.vehicleId, hugedatapacket.scanData.parent_vehicle_id);
3163 
3164  SmodeX modeX = SmodeX();
3165  if (hugedatapacket.scanData.loadQuantityHasValue)
3166  modeX.load_quantity = hugedatapacket.scanData.load_quantity;
3167  if (hugedatapacket.scanData.loadDestHasValue)
3168  modeX.load_dest = hugedatapacket.scanData.load_dest;
3169  if (hugedatapacket.scanData.loadTypeHasValue)
3170  modeX.load_type = hugedatapacket.scanData.load_type;
3171  if (hugedatapacket.scanData.weightLbsHasValue)
3172  modeX.weightLbs = hugedatapacket.scanData.weightLbs;
3173  if (hugedatapacket.scanData.pilotHasValue)
3174  modeX.pilot = hugedatapacket.scanData.pilot;
3175  game->bus->Scanner.InsertUpdateModeX(modeAC.vehicleId, modeX);
3176 
3177  for (short t = 0; t < MAX_SCAN; t++)
3178  {
3179  if (playerships[t].active && playerships[t].vehicleId == modeAC.vehicleId)
3180  {
3182  }
3183  }
3184  }
3185  break;
3186 
3187  default:
3188  sprintf_s(msg, sizeof msg, "Unknown HUGE packet type: %i", hugedatapacket.type);
3189  Trace(msg, Logger::Level::Warn);
3190  break;
3191  }
3192  }
3193  break;
3194 
3195  /* case sizeof SServerPacketChar:
3196  {
3197  SServerPacketChar datapacket;
3198  memcpy_s(&datapacket, sizeof SServerPacketChar, &packet->data[1], packet->length - 1);
3199 
3200 
3201 
3202  game->GUI->player[datapacket.array].frame=datapacket.frame;
3203  // game->GUI->player[datapacket.array].bldg=datapacket.bldg;
3204  //game->GUI->player[datapacket.array].request=datapacket.request; // what button they pushed
3205  //game->GUI->player[datapacket.array].x=datapacket.x;
3206  //game->GUI->player[datapacket.array].y=datapacket.y;
3207  //game->GUI->player[datapacket.array].hdg=datapacket.hdg;
3208  // game->GUI->player[datapacket.array].ani=datapacket.ani;
3209  game->GUI->player[datapacket.array].leftright=datapacket.leftright;
3210  game->GUI->player[datapacket.array].updown=datapacket.updown;
3211  game->GUI->player[datapacket.array].rolltilt=datapacket.rolltilt;
3212  }
3213  break;*/
3214 
3215  case sizeof SWeaponPacket:
3216  {
3217  SWeaponPacket datapacket;
3218  memcpy_s(&datapacket, sizeof SWeaponPacket, &packet->data[1], packet->length - 1);
3219 
3220  sprintf_s(msg, sizeof msg, "SWeaponPacket %i %i %i", datapacket.type, datapacket.status, datapacket.array);
3221  game->logger->AddToCallStack(msg);
3222 
3223  game->viewscreen->ptrWeapon->ProcessPacket(datapacket);
3224  }
3225  break;
3226 
3227  case sizeof SRenderPoint:
3228  {
3229  SRenderPoint datapacket;
3230  memcpy_s(&datapacket, sizeof SRenderPoint, &packet->data[1], packet->length - 1);
3231 
3232  sprintf_s(msg, sizeof msg, "Received dynamic change for %i,%i", datapacket.tcp.u, datapacket.tcp.v);
3233  Trace(msg);
3234 
3235  const short t = 31 + game->viewscreen->ptrGrid->tcp.u - datapacket.tcp.u;
3236  const short s = 31 + game->viewscreen->ptrGrid->tcp.v - datapacket.tcp.v;
3237  if (t > -1 && t < 64 && s > -1 && s < 64)
3238  {
3239  gridarray[t][s] = game->viewscreen->CalculateSRV(t, s, game->viewscreen->ptrGrid->tcp, game->viewscreen->ptrGrid->cube, datapacket.gridarray);
3240  if (gridarray[t][s].buildzoneOrdinal != -1)
3241  {
3242  SAFE_RELEASE(buildzone[gridarray[t][s].buildzoneOrdinal].VB);
3243  sprintf_s(msg, sizeof msg, "buildzone[%i].VB", gridarray[t][s].buildzoneOrdinal);
3244  game->UpdateTrackedResource(msg, 3);
3245 
3246  if (buildzone[gridarray[t][s].buildzoneOrdinal].RTSVB)
3247  {
3248  SAFE_RELEASE(buildzone[gridarray[t][s].buildzoneOrdinal].RTSVB);
3249  sprintf_s(msg, sizeof msg, "buildzone[%i].RTSVB", gridarray[t][s].buildzoneOrdinal);
3250  game->UpdateTrackedResource(msg, 3);
3251  }
3252 
3253  sprintf_s(msg, sizeof msg, "SRenderPoint released VB slot %i!", gridarray[t][s].buildzoneOrdinal);
3254  Trace(msg);
3255 
3256  gridarray[t][s].buildzoneOrdinal = -1; // re-create
3257  }
3258  game->viewscreen->ptrGrid->geometryReady = false;
3259  }
3260  }
3261  break;
3262 
3263  // This guy had some inherent problems with coordinating TCP and datapacket.TCP
3264  case sizeof SRenderRow:
3265  {
3266  SRenderRow datapacket;
3267  memcpy_s(&datapacket, sizeof SRenderRow, &packet->data[1], packet->length - 1);
3268 
3269  const short ewadjust = game->viewscreen->ptrGrid->tcp.u - datapacket.tcp.u;
3270  const short nsadjust = game->viewscreen->ptrGrid->tcp.v - datapacket.tcp.v;
3271  short newt, news;
3272 
3273 
3274  sprintf_s(msg, sizeof msg, "Received 1.3 data edge %i:%i,%i+(%+i,%+i)=(%i,%i)", datapacket.side - 1, datapacket.tcp.u, datapacket.tcp.v, ewadjust, nsadjust, game->viewscreen->ptrGrid->tcp.u, game->viewscreen->ptrGrid->tcp.v);
3275  Trace(msg);
3276 
3278  {
3279  Trace("We received 1.3 data edge but weren't waiting for any!", Logger::Level::Debug);
3280  break;
3281  }
3282 
3283  switch (datapacket.side)
3284  {
3285  case 1: // north (l to r)
3286  {
3287  news = 0 + nsadjust;
3288  if (news >= 0)
3289  {
3290  sprintf_s(msg, sizeof msg, "Proc SRV row %i: ", news);
3291  for (short t = 0; t < 64; t++)
3292  {
3293  newt = t - ewadjust;
3294  if (newt >= 0 && newt < 64)
3295  {
3296  char append[99];
3297  sprintf_s(append, sizeof append, "%2i ", newt);
3298  strcat_s(msg, sizeof msg, append);
3299  gridarray[newt][news] = game->viewscreen->CalculateSRV(newt, news, game->viewscreen->ptrGrid->tcp, game->viewscreen->ptrGrid->cube, datapacket.gridarray[t]);
3300  }
3301  else
3302  strcat_s(msg, sizeof msg, "XX ");
3303  }
3304  Trace(msg);
3305  }
3306  else
3307  Trace("Proc SRV row no longer applies!");
3308  }
3309  break;
3310 
3311  case 2: // south (l to r)
3312  {
3313  news = 63 + nsadjust;
3314  if (news < 64)
3315  {
3316  sprintf_s(msg, sizeof msg, "Proc SRV row %i: ", news);
3317  for (short t = 0; t < 64; t++)
3318  {
3319  newt = t - ewadjust;
3320  if (newt >= 0 && newt < 64)
3321  {
3322  char append[99];
3323  sprintf_s(append, sizeof append, "%2i ", newt);
3324  strcat_s(msg, sizeof msg, append);
3325  gridarray[newt][news] = game->viewscreen->CalculateSRV(newt, news, game->viewscreen->ptrGrid->tcp, game->viewscreen->ptrGrid->cube, datapacket.gridarray[t]);
3326  }
3327  else
3328  strcat_s(msg, sizeof msg, "XX ");
3329  }
3330  Trace(msg);
3331  }
3332  else
3333  Trace("Proc SRV row no longer applies!");
3334  }
3335  break;
3336 
3337  case 3: // east (u to d)
3338  {
3339  newt = 63 - ewadjust;
3340  if (newt < 64)
3341  {
3342  sprintf_s(msg, sizeof msg, "Proc SRV column %i: ", newt);
3343  for (short s = 0; s < 64; s++)
3344  {
3345  news = s + nsadjust;
3346  if (news >= 0 && news < 64)
3347  {
3348  char append[99];
3349  sprintf_s(append, sizeof append, "%2i ", news);
3350  strcat_s(msg, sizeof msg, append);
3351  gridarray[newt][news] = game->viewscreen->CalculateSRV(newt, news, game->viewscreen->ptrGrid->tcp, game->viewscreen->ptrGrid->cube, datapacket.gridarray[s]);
3352  }
3353  else
3354  strcat_s(msg, sizeof msg, "XX ");
3355  }
3356  Trace(msg);
3357  }
3358  else
3359  Trace("Proc SRV column no longer applies!");
3360  }
3361  break;
3362 
3363  case 4: // west (u to d) news verified 1/3
3364  {
3365  newt = 0 - ewadjust;
3366  if (newt >= 0)
3367  {
3368  sprintf_s(msg, sizeof msg, "Proc SRV column %i: ", newt);
3369  for (short s = 0; s < 64; s++)
3370  {
3371  news = s - nsadjust;
3372  if (news >= 0 && news < 64)
3373  {
3374  char append[99];
3375  sprintf_s(append, sizeof append, "%2i ", news);
3376  strcat_s(msg, sizeof msg, append);
3377  gridarray[newt][news] = game->viewscreen->CalculateSRV(newt, news, game->viewscreen->ptrGrid->tcp, game->viewscreen->ptrGrid->cube, datapacket.gridarray[s]);
3378  }
3379  else
3380  strcat_s(msg, sizeof msg, "XX ");
3381  }
3382  Trace(msg);
3383  }
3384  else
3385  Trace("Proc SRV column no longer applies!");
3386  }
3387  break;
3388  default:
3389  Trace("SRV row or column unrecognized!", Logger::Level::Error);
3390  break;
3391  }
3392 
3393 
3394  game->viewscreen->ptrGrid->geometryReady = false; // need to create new VB
3396  sprintf_s(msg, sizeof msg, "Ground grid is waiting for %i more", game->viewscreen->ptrGrid->dataPending);
3397  Trace(msg);
3398  }
3399  break;
3400 
3401  case sizeof SAssayGrid:
3402  {
3403  memcpy_s(&game->bus->assayGrid, sizeof SAssayGrid, &packet->data[1], packet->length - 1);
3404  game->bus->assayQuality = fabsf(game->bus->RadioAltitudeKm - 0.6f); // 0.5-0.6 = -0.1 and .7-.6=.1
3405  if (game->bus->assayQuality <= 0.1f)
3406  game->bus->assayQuality = 0.0f;
3407  else
3408  game->bus->assayQuality -= 0.1f; // .1-.6 is 0.5f which is now 0.4
3409  game->bus->assayQuality = 1.0f - game->bus->assayQuality * 2.0f;
3410  if (game->bus->assayQuality < 0.0f)
3411  game->bus->assayQuality = 0.0f;
3412  }
3413  break;
3414 
3415  // whole grid, should be clean slate before we get this call
3416  case sizeof SRenderGrid:
3417  {
3418  //Whole grid
3419  SRenderGrid datapacket;
3420  memcpy_s(&datapacket, sizeof SRenderGrid, &packet->data[1], packet->length - 1);
3421 
3422  // calculate and store results
3423  game->viewscreen->ptrGrid->ReceiveWholeGrid(datapacket);
3424  }
3425  break;
3426 
3427  //case sizeof SWeatherGrid:
3428  //{
3429  // memcpy_s(game->viewscreen->ptrWeather->weathergrid, sizeof SWeatherGrid, &packet->data[1], packet->length - 1);
3430  //
3431  // Trace("Received SWeatherGrid");
3432  //}
3433  //break;
3434 
3435  case sizeof SRenderBuilding:
3436  {
3437  SRenderBuilding datapacket;
3438  memcpy_s(&datapacket, sizeof SRenderBuilding, &packet->data[1], packet->length - 1);
3439 
3440  if (!g_bAboveClouds)
3441  {
3442  const short t = datapacket.tcp.u - game->viewscreen->ptrGrid->tcp.u + 31;
3443  const short s = datapacket.tcp.v - game->viewscreen->ptrGrid->tcp.v + 31;
3444 
3445  sprintf_s(msg, sizeof msg, "Received SRenderBuilding type %i @ u%i v%i (%i,%i) power %i", datapacket.type, datapacket.tcp.u, datapacket.tcp.v, t, s, datapacket.powered);
3446  Trace(msg);
3447  sprintf_s(msg, sizeof msg, " Zone %i (%08X %08X %08X %08X)", datapacket.zone, datapacket.layout.layout1, datapacket.layout.layout2, datapacket.layout.layout3, datapacket.layout.layout4);
3448  Trace(msg);
3449 
3450  int oldlayout4 = 0;
3451 
3452  // check to see if VB already exists in patch data
3453  if (t > 15 && t < 48 && s > 15 && s < 48)
3454  {
3455  if (gridarray[t][s].buildzoneOrdinal != -1)
3456  {
3457  SAFE_RELEASE(buildzone[gridarray[t][s].buildzoneOrdinal].VB);
3458  sprintf_s(msg, sizeof msg, "buildzone[%i].VB", gridarray[t][s].buildzoneOrdinal);
3459  game->UpdateTrackedResource(msg, 3);
3460 
3461  if (buildzone[gridarray[t][s].buildzoneOrdinal].RTSVB)
3462  {
3463  SAFE_RELEASE(buildzone[gridarray[t][s].buildzoneOrdinal].RTSVB);
3464  sprintf_s(msg, sizeof msg, "buildzone[%i].RTSVB", gridarray[t][s].buildzoneOrdinal);
3465  game->UpdateTrackedResource(msg, 3);
3466  }
3467 
3468  sprintf_s(msg, sizeof msg, " SRenderBuilding released VB slot %i!", gridarray[t][s].buildzoneOrdinal);
3469  Trace(msg);
3470 
3471  gridarray[t][s].buildzoneOrdinal = -1; // re-create
3472  }
3473  }
3474 
3475  if (t >= 0 && t < 64 && s >= 0 && s < 64)
3476  {
3477  gridarray[t][s].type = static_cast<PlotType>(datapacket.type);
3478  //if (gridarray[t][s].type != datapacket.type)
3479  //{
3480  // sprintf_s(msg, sizeof msg, "SRenderBuilding type %i (%i,%i) doesn't match the grid type %i (%i,%i)", datapacket.type, t, s, gridarray[t][s].type, gridarray[t][s].tcp.u, gridarray[t][s].tcp.v);
3481  // Trace(msg, Logger::Error);
3482  // gridarray[t][s].type = datapacket.type;
3483  //}
3484  gridarray[t][s].zone = datapacket.zone;
3485  gridarray[t][s].layout1 = datapacket.layout.layout1;
3486  gridarray[t][s].layout2 = datapacket.layout.layout2;
3487  gridarray[t][s].layout3 = datapacket.layout.layout3;
3488  oldlayout4 = gridarray[t][s].layout4;
3489  gridarray[t][s].layout4 = datapacket.layout.layout4;
3490  gridarray[t][s].powered = datapacket.powered;
3491  Trace(" SRenderBuilding is somewhere on grid, stored!");
3492  }
3493  else
3494  {
3495  Trace(" SRenderBuilding off grid reference, not stored!", Logger::Error);
3496  sprintf_s(msg, sizeof msg, " Received SRenderBuilding type %i @ u%i v%i (%i,%i) power %i", datapacket.type, datapacket.tcp.u, datapacket.tcp.v, t, s, datapacket.powered);
3497  Trace(msg, Logger::Debug);
3498  sprintf_s(msg, sizeof msg, " Zone %i (%08X %08X %08X %08X)", datapacket.zone, datapacket.layout.layout1, datapacket.layout.layout2, datapacket.layout.layout3, datapacket.layout.layout4);
3499  Trace(msg, Logger::Debug);
3500  }
3501 
3502  // rebuild if we have ground data already
3503  if (t > 15 && t < 48 && s > 15 && s < 48)
3504  {
3506  {
3507  Trace(" SRenderBuilding grid level is initialized, OK!");
3508  // if apn has construction whose VB hasn't been created
3509 
3510  if (gridarray[t][s].type > PlotType::NotZoned &&
3511  gridarray[t][s].type < PlotType::PlotTypeEnum &&
3512  gridarray[t][s].buildzoneOrdinal == -1)
3513  {
3514  Trace(" SRenderBuilding type in bounds, OK!");
3515  if (gridarray[t][s].IsUserColony())
3516  {
3517  Trace(" SRenderBuilding layout is user-generated and real, OK!");
3518  // if we got here the grid was ready when we got case 16
3519  if (gridarray[t][s].type != PlotType::UserAirfield || oldlayout4 == gridarray[t][s].layout4)
3520  game->viewscreen->ptrGrid->makeBuildings = true; // must be a building
3521  else
3522  {
3523  Trace(" SRenderBuilding is not an airfield or layout4 changed!");
3524  game->viewscreen->ptrGrid->makeBuildings = true; // must be a building
3525  game->viewscreen->ptrGrid->geometryReady = false; // reload the runway
3526  for (short tt = 16; tt < 48; tt++) // can't do outside edges
3527  {
3528  for (short ss = 16; ss < 48; ss++)
3529  {
3531  }
3532  }
3533  }
3534  }
3535  else
3536  {
3537  Trace(" SRenderBuilding must be gov, OK!");
3539  game->viewscreen->ptrGrid->geometryReady = false;
3540  for (short tt = 16; tt < 48; tt++) // can't do outside edges
3541  {
3542  for (short ss = 16; ss < 48; ss++)
3543  {
3545  }
3546  }
3547  }
3548  }
3549  else
3550  {
3551  sprintf_s(msg, sizeof msg, " SRenderBuilding type (%i) out-of-bounds (or %i), sorry!", gridarray[t][s].type, gridarray[t][s].buildzoneOrdinal);
3552  Trace(msg, Logger::Error);
3553  }
3554  }
3555  else
3556  {
3557  sprintf_s(msg, sizeof msg, " SRenderBuilding grid level NOT YET initiated, waiting for %i", game->viewscreen->ptrGrid->dataPending);
3558  Trace(msg, Logger::Error);
3559  }
3560  }
3561  else
3562  {
3563  Trace(" SRenderBuilding not in patch data, OK!");
3564  }
3565  } // !g_bAboveClouds
3566  else
3567  {
3568  Trace("SRenderBuilding received while ACMPL!", Logger::Warn);
3569  }
3570  }
3571  break;
3572 
3573  case sizeof SPacketMenu:
3574  {
3576  break;
3577 
3578  SPacketMenu datapacket;
3579  memcpy_s(&datapacket, sizeof SPacketMenu, &p->data[1], p->length - 1);
3580 
3582 
3583  wcscpy_s(ptr->menu[0], 44, datapacket.row0);
3584  wcscpy_s(ptr->menu[1], 44, datapacket.row1);
3585  wcscpy_s(ptr->menu[2], 44, datapacket.row2);
3586  wcscpy_s(ptr->menu[3], 44, datapacket.row3);
3587  wcscpy_s(ptr->menu[4], 44, datapacket.row4);
3588  wcscpy_s(ptr->menu[5], 44, datapacket.row5);
3589 
3590  ZeroMemory(ptr->menubool, 6);
3591  ptr->menuLevel = datapacket.menuLevel;
3592  ptr->UpdateMenu(-1);
3593 
3594  if (!datapacket.interactive && !g_bTextInput && interactive.avail)
3595  {
3596  interactive.avail = false;
3597  game->displays->RestorePage("MFD");
3598  }
3599  else if (datapacket.interactive)
3600  {
3601  interactive.avail = true;
3602  game->displays->ChangePage("MFD", "Intermedia");
3603  }
3604  }
3605  break;
3606 
3607  default:
3608  sprintf_s(msg, sizeof msg, "Unknown packet size: %d", p->length - 1);
3609  Trace(msg, Logger::Level::Debug);
3610  break;
3611  }
3612  break;
3613  }
3614 
3615  case ID_USER_PACKET_HELP:
3616  {
3617  SVerbiage chat = SVerbiage();
3618  memcpy_s(&chat, sizeof SVerbiage, &packet->data[1], packet->length - 1);
3619  sprintf_s(msg, sizeof msg, "Got verbiage: %i", chat.id);
3620  Trace(msg);
3621 
3622  if (chat.id > 0)
3623  game->GUI->informationDialog->SetHelpText(chat.text);
3624  else
3625  game->GUI->Toast(chat.text, static_cast<ActiveHelp>(chat.id));
3626  }
3627  break;
3628 
3629  case ID_USER_PACKET_CHAT:
3630  {
3631  WCHAR chat[TRANSMIT_CHAT_SIZE];
3632  const unsigned source_size = min(packet->length - 3, TRANSMIT_CHAT_SIZE * 2);
3633  memcpy_s(chat, sizeof chat, &packet->data[3], source_size);
3634 
3635  if (packet->data[2] == 255)
3636  game->GUI->AddSupportChatMessage(chat);
3637  else if (packet->data[2] == 254)
3638  game->GUI->AddDiscordChatMessage(chat);
3639  else
3640  game->GUI->AddChatMessage(chat, packet->data[2], packet->data[1]);
3641 
3642  // Wait until we are out of the apartment and only if we haven't already dismissed this help
3643  if (game->GUI->player[game->GUI->ourplayerC].frame == 0 &&
3646  DialogBase::dialogs[D_COMMUNICATIONS]->PopUpDialog();
3647 
3648  break;
3649  }
3650 
3651  case ID_DISCONNECTION_NOTIFICATION:
3652  Trace("ID_DISCONNECTION_NOTIFICATION", Logger::Level::Warn);
3653 #ifndef _DEBUG
3654  PostQuitMessage(0);
3655 #endif
3656  break;
3657 
3658  case ID_CONNECTION_LOST:
3659  Trace("ID_CONNECTION_LOST", Logger::Level::Warn);
3660  game->ToggleFullScreen(false);
3661  MessageBoxW(nullptr, L"Reliable packets cannot be delivered to the game server. Please check your connection and try again.", L"Disconnected from server!", MB_ICONERROR | MB_OK);
3662 #ifndef _DEBUG
3663  PostQuitMessage(0);
3664 #endif
3665  break;
3666 
3667  case ID_CONNECTION_ATTEMPT_FAILED:
3668  Trace("ID_CONNECTION_ATTEMPT_FAILED", Logger::Level::Warn);
3669 #ifndef _DEBUG
3670  PostQuitMessage(0);
3671 #endif
3672  break;
3673 
3674  case ID_NO_FREE_INCOMING_CONNECTIONS:
3675  Trace("ID_NO_FREE_INCOMING_CONNECTIONS", Logger::Level::Warn);
3676 #ifndef _DEBUG
3677  PostQuitMessage(0);
3678 #endif
3679  break;
3680 
3681  /*Trace("Lost connection!", Logger::Level::Warn);
3682  RakNet::ConnectionAttemptResult result = Connect();
3683  if (result != RakNet::ConnectionAttemptResult::CONNECTION_ATTEMPT_STARTED)
3684  DXUT_ERR_MSGBOX(L"NetFactory->Connect", 0);
3685  else
3686  {
3687  if (p->data[0] == ID_CONNECTION_ATTEMPT_FAILED)
3688  Trace("Retrying (ID_CONNECTION_ATTEMPT_FAILED)...", Logger::Level::Info);
3689  else if (p->data[0] == ID_NO_FREE_INCOMING_CONNECTIONS)
3690  Trace("Retrying (ID_NO_FREE_INCOMING_CONNECTIONS)...", Logger::Level::Info);
3691  else if (p->data[0] == ID_CONNECTION_LOST)
3692  Trace("Retrying (ID_CONNECTION_LOST)...", Logger::Level::Info);
3693  else if (p->data[0] == ID_DISCONNECTION_NOTIFICATION)
3694  Trace("Retrying (ID_DISCONNECTION_NOTIFICATION)...", Logger::Level::Info);
3695  }*/
3696 
3697  case ID_CONNECTION_REQUEST_ACCEPTED:
3698  Trace("ID_CONNECTION_REQUEST_ACCEPTED");
3699  break;
3700 
3701  default:
3702  {
3703  sprintf_s(msg, sizeof msg, "Unknown packet ID %i", p->data[0]);
3704  game->logger->Log(msg, Logger::Error);
3705  }
3706  break;
3707  }
3708 
3709  game->logger->AddToCallStack("Networking::RakNetMessageHandler DONE");
3710 }
void SetCloudCeilingTargetKm(float prmCloudCeilingTargetKm)
Definition: weather.cpp:887
InputConfig inputConfigLeftToeBrake
Definition: config.h:35
float LeadingEdgeFlapsPosition
Definition: Bus.h:326
D3DXVECTOR3 chaireye
Definition: globals.h:618
D3DXCOLOR color
Definition: globals.h:752
void SavePatchDate() const
Definition: config.cpp:39
Scockpit ourcockpit
Definition: globals.cpp:176
short type1built
Definition: globals.h:772
D3DXVECTOR3 position
Definition: globals.h:753
float PitchTrimScalar
Definition: Bus.h:316
bool powered
Definition: globals.h:297
VECTOR2SHORT tcp
Definition: grid.h:34
bool AntiIce
Definition: Bus.h:296
int inventoryItemInUseType
Definition: globals.h:687
char referralValid
Definition: gui.h:773
void SendScreenShot(const char *fileContents, int length) const
Definition: Networking.cpp:140
void SetHelpText(WCHAR *str)
WCHAR loginstr[99]
Definition: gui.h:747
#define MAX_ENGINES
Definition: Bus.h:14
float staticDensity
Definition: propulsion.h:84
D3DXVECTOR3 dockingvel
Definition: globals.h:540
bool g_bAugment
Definition: globals.cpp:63
int intentoryItemInUseVehicleId
Definition: globals.h:688
Nullable< float > fuel_tank
Definition: scanDb.h:35
UINT flapSettingTE
Definition: Bus.h:56
char IVR[6]
Definition: scanDb.h:16
float tach
Definition: globals.h:651
D3DXVECTOR3 acc
Definition: globals.h:542
SPlotData tempplot
Definition: globals.h:767
void ReceiveWholeGrid(SRenderGrid datapacket)
Definition: grid.cpp:109
D3DXVECTOR3 acciter
Definition: globals.h:542
std::vector< DIDEVICEINSTANCE > deviceList
Definition: joystick.h:27
float power
Definition: globals.h:608
float yawdeflect
Definition: globals.h:562
void AddSupportChatMessage(const WCHAR *wmsg)
Definition: gui.cpp:3463
bool stolen
Definition: scanDb.h:26
unsigned char type
Definition: scanDb.h:17
float fuel
Definition: globals.cpp:143
float turnByTurnTotalDistanceMeters
Definition: Bus.h:400
short dihvanimate
Definition: globals.cpp:71
GameClass * game
Definition: Networking.h:62
Config config
Definition: GameClass.h:102
RakNet::Packet * p
Definition: Networking.h:66
short type8built
Definition: globals.h:772
bool g_bAboveClouds
Definition: globals.cpp:22
int ivalues[2]
Definition: Command.h:21
void Close()
Definition: Networking.cpp:48
unsigned char language
Definition: config.h:12
std::vector< Command > commandStream
Definition: Bus.h:342
D3DXVECTOR3 position
Definition: globals.h:549
void CalculateInsideArray(short t, short s) const
Definition: grid.cpp:1181
float payload
Definition: globals.cpp:145
GameClass * gameclass
Definition: Viewscreen.h:292
float airframeTempCelsius
Definition: propulsion.h:76
GameState displaystage
Definition: GameClass.h:121
Nullable< float > weightLbs
Definition: scanDb.h:34
bool radioPower
Definition: globals.h:606
unsigned long rcvdbytes
Definition: Networking.h:93
std::vector< int > flapSettings
Definition: globals.h:656
unsigned char zone
Definition: globals.h:291
int allegiance
Definition: scanDb.h:23
char type
Definition: globals.h:751
D3DXQUATERNION orientation
Definition: globals.h:558
float tirespeedKph
Definition: globals.h:651
std::vector< std::wstring > motd
Definition: gui.h:746
float turnByTurnTotalTimeSeconds
Definition: Bus.h:401
Definition: gui.h:415
D3DXVECTOR3 location
Definition: scanDb.h:20
long layout2
Definition: globals.h:293
void SendToServer(void *pData, DWORD dwSize, bool bGuaranteed, PacketOrdering order=ORDERING_NONE) const
Definition: Networking.cpp:59
char startcycle
Definition: globals.h:608
int flapMaxDegrees
Definition: globals.h:692
bool wheeled
Definition: globals.h:605
ID3DXFont * g_pFont
Definition: gui.h:727
short oldRoomIndex
Definition: Viewscreen.h:245
bool weatherRadarPower
Definition: globals.h:606
void ChannelInvite(char *title, unsigned char whoinvited, unsigned char channel, unsigned char players) const
Definition: gui.cpp:3703
scanDb Scanner
Definition: Bus.h:379
Sinteractive interactive
Definition: globals.cpp:183
bool radioEquipped
Definition: globals.h:644
float f_Uphours
Definition: globals.cpp:25
InformationDialog * informationDialog
Definition: gui.h:789
void SexChangeOperation(char newsex)
Definition: gui.cpp:27
void PlayerOffline(unsigned char arrayindex)
Definition: gui.cpp:3373
bool geometryReady
Definition: grid.h:30
void Reset()
unsigned short vehicleId
Definition: globals.h:570
char owner[13]
Definition: scanDb.h:21
double precisiony
Definition: globals.h:550
unsigned char cargoload
Definition: globals.h:673
FIREWORKS fireworks[fireworksC]
Definition: globals.cpp:181
RakNet::RakPeerInterface * rakPeer
Definition: Networking.h:64
float colonistsforbuilding
Definition: globals.h:771
unsigned char paxdest
Definition: globals.h:673
s_network_objects playerships[MAX_SCAN]
Definition: globals.cpp:174
float cash
Definition: globals.cpp:146
waypoints * ptrWaypoints
Definition: Viewscreen.h:290
unsigned char cargoloadtype
Definition: globals.h:673
unsigned char playerWeightKg
Definition: globals.h:665
float dihvelapsed
Definition: globals.cpp:74
float RadioAltitudeKm
Definition: Bus.h:134
D3DXVECTOR3 velocity
Definition: globals.h:500
void UpdateMenu(short tab) override
char handle[13]
Definition: globals.h:667
void ProcessPacket(SWeaponPacket datapacket)
Definition: weapon.cpp:984
float displayHeight
Definition: GameClass.h:129
void SetTurbidity(float prmTurbidity)
Definition: weather.cpp:867
weapon * ptrWeapon
Definition: Viewscreen.h:280
long dihvtimeseq
Definition: globals.cpp:73
bool g_bGotConclusion
Definition: globals.cpp:150
std::vector< unsigned char > personalInventory
Definition: globals.h:675
InputConfig inputConfigGas
Definition: config.h:33
float extended
Definition: globals.h:427
short type6built
Definition: globals.h:772
float deathfuel
Definition: globals.cpp:144
InputConfig inputConfigRoll
Definition: config.h:27
InputConfig inputConfigLookVertical
Definition: config.h:38
float PayloadWeightLbs
Definition: Bus.h:364
void SetTurbulenceScalar(float prmTurbulence)
Definition: weather.cpp:845
static float GetCpuSpeedMhz()
Definition: GameClass.cpp:2692
float leftlimit
Definition: Viewscreen.h:314
void AddOrUpdate(Swaypoint tempwaypoint) const
Definition: waypoints.cpp:132
D3DXQUATERNION orientleft
Definition: globals.h:558
void ToggleFullScreen(bool goFullScreen)
Definition: GameClass.cpp:269
short scanslot[MAX_SCAN]
Definition: Viewscreen.h:276
weather * ptrWeather
Definition: Viewscreen.h:287
unsigned char axis
Definition: InputConfig.h:14
void SendEvent(EventType eventType, float extent=0.0f) const
Definition: Networking.cpp:111
void ChangePage(std::string screenName, std::string pageName)
Definition: Displays.cpp:491
float displayWidth
Definition: GameClass.h:129
void ResetLoginFields()
Definition: gui.cpp:3406
unsigned char channel
Definition: chat.h:57
float uplimit
Definition: Viewscreen.h:314
char g_bTextInput
Definition: globals.cpp:108
Nullable< unsigned short > load_quantity
Definition: scanDb.h:32
Logger * logger
Definition: GameClass.h:113
RakNet::RakNetStatistics * GetStatistics() const
Definition: Networking.cpp:148
char cube
Definition: grid.h:35
std::vector< RECT > rooms
Definition: Viewscreen.h:42
void InsertUpdateParent(USHORT vehicleId, USHORT parentId)
Definition: scanDb.cpp:69
joystick * ptrJoystick
Definition: Viewscreen.h:283
PlotType type
Definition: globals.h:282
void FrameMove(GameState displaystage)
Definition: Networking.cpp:191
InputConfig inputConfigThrustLeft
Definition: config.h:29
char reference
Definition: scanDb.h:19
unsigned short vehicleId
Definition: scanDb.h:15
D3DXVECTOR3 veliter
Definition: globals.h:541
std::string name
Definition: Command.h:11
bool vphelp[vphelpC]
Definition: GameClass.h:103
InputConfig inputConfigThrustRight
Definition: config.h:30
void AddChatMessage(WCHAR *msg, unsigned char playerindex, unsigned char channel)
Definition: gui.cpp:3511
bool ThrustReverserCommand[MAX_ENGINES]
Definition: Bus.h:61
void PlayerLeftChannel(short tab, unsigned char playerindex)
Definition: gui.cpp:3432
s_mesh_component * componentarray
Definition: globals.h:578
bool g_bEnabled
Definition: globals.cpp:149
static DialogBase * dialogs[D_ENUMERATION]
Definition: DialogBase.h:39
CDXUTDialog g_HUD
Definition: gui.h:710
void PlayAudioData(unsigned char *data, size_t length)
Definition: Sound.cpp:402
bool reposess
Definition: scanDb.h:25
unsigned char bay
Definition: globals.h:548
#define fireworksC
Definition: globals.h:746
void LostScannerTarget(const char *msg) const
Definition: GameClass.cpp:2191
propulsion * ptrPropulsion
Definition: Viewscreen.h:285
float tiltlimitL
Definition: Viewscreen.h:314
short type5built
Definition: globals.h:772
float mincoltorun
Definition: globals.h:771
void LegacySoundRequestUniverse(SServerPacket datapacket)
Definition: Sound.cpp:1133
char defaultuser[13]
Definition: config.h:15
void InsertUpdateModeAC(USHORT vehicleId, SmodeAC modeAC)
Definition: scanDb.cpp:23
WCHAR menu[maxmenuC][44]
float flapExtent
Definition: globals.h:655
s_universe_object allobjects[maxstarC]
Definition: globals.cpp:170
bool loopintro
Definition: Sound.h:332
float scanrange
Definition: globals.h:645
bool isInjected
Definition: gui.h:777
InputConfig inputConfigPitchTrim
Definition: config.h:39
Nullable< short > load_dest
Definition: scanDb.h:33
bool IsAdmin
Definition: gui.h:777
void UseOrDisuseInventoryItemType(int itemtype, int itemId, int vehicleId) const
Definition: GameClass.cpp:729
Viewscreen * viewscreen
Definition: GameClass.h:111
D3DXVECTOR3 posleft
Definition: globals.h:541
float rolldeflect
Definition: globals.h:562
short type2built
Definition: globals.h:772
long layout4
Definition: globals.h:293
unsigned char ourplayerC
Definition: gui.h:766
Networking * networking
Definition: GameClass.h:107
bool PopUpHelp(short helpId, bool allowDismiss=true, bool isLearnMore=false)
int GetPingTime() const
Definition: Networking.cpp:106
double precisionx
Definition: globals.h:550
SPlayerData player[MAX_ONLINEPLAYERS]
Definition: gui.h:765
void SetWindDirectionRadians(float prmWinddir)
Definition: weather.cpp:835
float Clamp(float val, float min, float max)
Definition: MathUtilities.h:3
short texture
Definition: globals.h:750
char outgoing[80]
Definition: globals.cpp:107
void RepairVehicle() const
Definition: GameClass.cpp:168
float assayQuality
Definition: Bus.h:386
void LoadPeopleSounds() const
Definition: gui.cpp:1128
float MapScaleInnerRingKm
Definition: Bus.h:381
int lineact
Definition: DialogBase.h:73
bool g_bRunning
Definition: globals.cpp:151
InputConfig inputConfigPitch
Definition: config.h:26
bool FlightFreeze
Definition: Bus.h:374
unsigned char turnByTurnRoutingType
Definition: Bus.h:399
long layout1
Definition: globals.h:293
bool isSteam
Definition: gui.h:783
short txbuffer
Definition: gui.h:772
RakNet::SystemAddress serverC
Definition: Networking.h:65
void InsertUpdateModeX(USHORT vehicleId, SmodeX modeX)
Definition: scanDb.cpp:59
bool initFromDeflect
Definition: propulsion.h:72
void AddPlayer(char *msg, unsigned char playerindex)
Definition: gui.cpp:3586
BUILDZONE buildzone[buildingVBC]
Definition: globals.cpp:165
float EngineThrustOutput[MAX_ENGINES]
Definition: Bus.h:43
char charnameValid
Definition: gui.h:773
void AddDelayedSound(int soundEnum, float delay, float volume=1.0f)
Definition: Sound.cpp:1927
Definition: Command.h:5
InputConfig inputConfigBrake
Definition: config.h:34
short targetC
Definition: Bus.h:378
float rightlimit
Definition: Viewscreen.h:314
Definition: scanDb.h:29
char handleValid
Definition: gui.h:773
void Toast(const WCHAR *message, ActiveHelp activeHelp)
Definition: gui.cpp:1202
void Trace(const char *msg, Logger::Level severity=Logger::Level::Info) const
Definition: Networking.cpp:41
Networking(GameClass *g)
Definition: Networking.cpp:15
float pitchdeflect
Definition: globals.h:562
char hullname[23]
Definition: globals.h:535
bool remoteAssayEquipped
Definition: globals.h:644
bool menubool[maxmenuC]
D3DXVECTOR3 velocity
Definition: globals.cpp:9
const D3DXVECTOR3 centerC
LOCALGRID2 CalculateSRV(short t, short s, VECTOR2SHORT tcp, char cube, SRenderVertex sourcedata)
float TrailingEdgeFlapsPosition
Definition: Bus.h:324
bool remoteAssayPower
Definition: globals.h:606
D3DXVECTOR3 velocity
Definition: globals.h:540
Sound * sound
Definition: GameClass.h:108
void RakNetMessageHandler(RakNet::Packet *packet) const
Definition: Networking.cpp:827
D3DXMATRIX matrixWorld
Definition: globals.h:555
short buildzoneOrdinal
Definition: globals.h:292
float dexterity
Definition: globals.h:664
float GetAttenuation(bool applyDensity) const
Definition: Sound.cpp:1062
void LoadVehicleProfile(short t, bool forceCockpitTextures=false)
char emailValid
Definition: gui.h:773
unsigned long patchbytes
Definition: Networking.h:92
static D3DXVECTOR3 CalculateBarycentric(D3DXVECTOR3 *position, D3DXVECTOR3 *gthrust, float *radius)
CHATCHANNEL chatchannel[MAX_TAB]
Definition: gui.h:768
bool active
Definition: DialogBase.h:71
D3DXVECTOR3 velleft
Definition: globals.h:541
void Log(const char *msg, Level level=Info, int errorCode=0)
Definition: Logger.cpp:11
grid * ptrGrid
Definition: Viewscreen.h:279
Definition: scanDb.h:13
void PlayerJoinedChannel(short tab, unsigned char playerindex)
Definition: gui.cpp:3413
Nullable< int > pilot
Definition: scanDb.h:36
char hullname[23]
Definition: scanDb.h:18
const GUID MYGUID_NULL
Definition: Guids.h:3
unsigned char hitpoints
Definition: globals.h:663
unsigned short CargoBays[MAX_PODSPERSHIP]
Definition: Bus.h:365
bool turnByTurnDirty
Definition: Bus.h:398
InputConfig inputConfigRightToeBrake
Definition: config.h:36
bool immigrationPassed
Definition: gui.h:776
short type3built
Definition: globals.h:772
bool groundvehicle
Definition: globals.h:581
unsigned short sequence
Definition: globals.h:589
short rxbuffer
Definition: gui.h:772
EventType
Definition: Networking.h:31
RakNet::ConnectionAttemptResult Connect() const
Definition: Networking.cpp:153
PEOPLE people
Definition: gui.h:769
Sscandata scandata
Definition: scanDb.h:49
bool avail
Definition: globals.h:760
char character[30]
Definition: globals.h:666
#define MaxAcceleration
Definition: globals.h:34
float deathinhibit
Definition: globals.cpp:51
void ChangeChannelName(unsigned char channelId, char *title)
Definition: gui.cpp:3683
float dpiscale
Definition: GameClass.h:128
char logofile[8]
Definition: globals.h:538
float Play(int soundEnum)
Definition: Sound.cpp:577
#define INTERIOR_SCALE
Definition: globals.h:28
unsigned char type
Definition: globals.h:532
ID3DXSprite * g_pTextSprite
Definition: gui.h:726
bool YawDamperStatus
Definition: Bus.h:333
int ownerId
Definition: scanDb.h:22
LPD3DXBUFFER pBuffer
Definition: gui.h:761
void AddDiscordChatMessage(const WCHAR *msg)
Definition: gui.cpp:3481
void SetTemperatureCelsius(float prmTemperature)
Definition: weather.cpp:851
void SetProjectionMatrices()
void RestorePage(std::string screenName)
Definition: Displays.cpp:602
bool inuse
Definition: globals.h:749
void SetPlayerAlignment(char *msg, unsigned char playerindex)
Definition: gui.cpp:3639
float downlimit
Definition: Viewscreen.h:314
float g_UniverseTime
Definition: globals.cpp:24
float tiltlimitR
Definition: Viewscreen.h:314
#define hostC
Definition: Networking.h:15
float scale
Definition: config.h:24
bool weatherRadarEquipped
Definition: globals.h:644
char GetAlignment(int ownerId) const
Definition: people.h:196
std::vector< Snode > nodes
Definition: Bus.h:397
void SendChatMessage(unsigned char channel, unsigned char player, const WCHAR *message) const
Definition: Networking.cpp:179
SmodeAC modeAC
Definition: scanDb.h:41
void Flush() const
Definition: Networking.cpp:158
HMI * GUI
Definition: GameClass.h:110
D3DXVECTOR3 positer
Definition: globals.h:541
short ourplyrC
Definition: globals.h:659
void SendTelemetry(SClientPacketNew *pData) const
Definition: Networking.cpp:83
long layout3
Definition: globals.h:293
float dockprogress
Definition: globals.cpp:44
Definition: scanDb.h:46
InputConfig inputConfigWalkVertical
Definition: config.h:41
char dead
Definition: globals.cpp:49
char prompt[80]
Definition: globals.cpp:109
short type9built
Definition: globals.h:772
SDockingPorts tempdock
Definition: globals.h:768
VECTOR2SHORT tcp
Definition: globals.h:763
LOCALGRID2 gridarray[64][64]
Definition: globals.cpp:153
D3DXVECTOR3 accleft
Definition: globals.h:542
short type7built
Definition: globals.h:772
void SendErrorReport(SErrorPacket *pData) const
Definition: Networking.cpp:93
Sscan Get(USHORT vehicleId) const
Definition: scanDb.cpp:87
std::vector< Swaypoint > waypoint
Definition: Bus.h:391
InputConfig inputConfigWalkLateral
Definition: config.h:40
void SendTraceFile(const char *fileContents) const
Definition: Networking.cpp:125
float usage
Definition: globals.h:645
void ChangePlayerProperties(SSubscribeData *prop)
Definition: gui.cpp:3715
void Stop(int soundEnum)
Definition: Sound.cpp:1946
D3DXVECTOR3 barycentric
Definition: globals.h:540
Nullable< unsigned char > load_type
Definition: scanDb.h:31
Level
Definition: Logger.h:19
static bool CheckLayout(unsigned i, LOCALGRID2 localgrid2)
Definition: buildings.cpp:16
std::wstring strings[L_ENUMERATION]
Definition: gui.h:749
bool tow
Definition: scanDb.h:24
void PlayEx(int soundEnum, bool loop, float volume=1.0f, float frequencyMod=1.0f, float pan=0.0f, bool restart=true)
Definition: Sound.cpp:606
bool parkingBrake
Definition: globals.h:685
void SetWindspeedKms(float prmWindspeed)
Definition: weather.cpp:861
char owner[13]
Definition: globals.h:585
bool gndvehicle
Definition: globals.h:604
InputConfig inputConfigYaw
Definition: config.h:28
void ChangeChannelOwner(short tab, unsigned char playerindex)
Definition: gui.cpp:3451
int WPtargetC
Definition: Bus.h:390
void UpdateTrackedResource(const char *name, int status)
Definition: GameClass.cpp:2725
D3DXQUATERNION orientiter
Definition: globals.h:558
void AddToCallStack(const char *msg)
Definition: Logger.cpp:86
void SetCloudSurfaceTargetKm(float prmCloudSurfaceTargetKm)
Definition: weather.cpp:877
Bus * bus
Definition: GameClass.h:112
bool dihvcoming
Definition: globals.cpp:75
bool makeBuildings
Definition: grid.h:32
void RequestVerbiage(int helpId) const
Definition: Networking.cpp:168
D3DXVECTOR3 position
Definition: globals.h:493
char gearshift
Definition: globals.h:652
bool initialized
Definition: scanDb.h:48
float RandomFloat()
Definition: MathUtilities.h:98
std::vector< unsigned char > vehicleInventory
Definition: globals.h:676
short retryconnect
Definition: Networking.h:94
InputConfig inputConfigSteer
Definition: config.h:32
double precisionz
Definition: globals.h:550
Displays * displays
Definition: GameClass.h:114
bool inhibitvisibility
Definition: globals.h:565
unsigned char menutype
Definition: globals.h:761
char dataPending
Definition: grid.h:31
SAssayGrid assayGrid
Definition: Bus.h:385
SPlayerData player[MAX_ONLINEPLAYERS]
Definition: globals.cpp:185
InputConfig inputConfigLookLateral
Definition: config.h:37
LPDIRECT3DTEXTURE9 m_pddsHullDynamicTexture[MAX_SCAN]
Definition: Viewscreen.h:209
#define portC
Definition: Networking.h:16
short type4built
Definition: globals.h:772
GameState
Definition: GameState.h:3
D3DXVECTOR3 dockoffset
Definition: globals.h:549
unsigned short components
Definition: globals.h:577
short Find(int uniqueid) const
Definition: waypoints.cpp:152
char patchdate[24]
Definition: config.h:17
float EngineThrustLever[MAX_ENGINES]
Definition: Bus.h:264
SVesselDC vdat
Definition: globals.h:669
float iceAccumulationMm
Definition: propulsion.h:77
char connectstatus
Definition: Networking.h:91