00001
00002 #include <winsock.h>
00003 #include "revolt.h"
00004 #include "dx.h"
00005 #include "dxerrors.h"
00006 #include "main.h"
00007 #include "text.h"
00008 #include "model.h"
00009 #include "particle.h"
00010 #include "aerial.h"
00011 #include "NewColl.h"
00012 #include "Body.h"
00013 #include "car.h"
00014 #include "ctrlread.h"
00015 #include "object.h"
00016 #include "control.h"
00017 #include "player.h"
00018 #include "play.h"
00019 #include "input.h"
00020 #include "draw.h"
00021 #include "registry.h"
00022 #include "geom.h"
00023 #include "move.h"
00024 #include "timing.h"
00025
00026
00027
00028
00029 IDirectPlay4A *DP = NULL;
00030 IDirectPlayLobby3 *Lobby = NULL;
00031 DPID FromID, ToID, LocalPlayerID, ServerID;
00032 DP_PLAYER PlayerList[MAX_NUM_PLAYERS];
00033 long PlayerCount;
00034 char ReceiveBuff[1024], TransmitBuff[1024];
00035 START_DATA StartData;
00036
00037 static char SessionName[MAX_SESSION_NAME];
00038 static unsigned char IP[4];
00039 static char ConnectionCount, SessionCount;
00040 static DP_PLAYER_DATA LocalPlayerData;
00041 static DPSESSIONDESC2 Session, SessionEnum, SessionJoin;
00042 static DP_SESSION SessionList[SESSION_MAX];
00043 static DP_CONNECTION Connection[CONNECTION_MAX];
00044 static char HostName[MAX_HOST_NAME];
00045 static HANDLE PlayerEvent = NULL;
00046 static long GameStarted, ReadyFlag;
00047 static float PingRequestTime, SessionRequestTime;
00048
00049
00050
00051 LEGAL_IP LegalIP[] = {
00052 {255, 255, 255, 0, 100, 103, 0, 0},
00053
00054 {255, 255, 255, 0, 100, 105, 0, 0},
00055 {255, 255, 255, 0, 100, 106, 0, 0},
00056
00057
00058
00059
00060
00061
00062 {255, 255, 255, 0, 38, 240, 105, 0},
00063 {255, 255, 255, 0, 100, 0, 7, 0},
00064 {255, 255, 255, 0, 100, 0, 5, 0},
00065 {255, 255, 255, 0, 194, 129, 18, 0},
00066
00067 {255, 255, 255, 255, 100, 0, 5, 70},
00068
00069 {0, 0, 0, 0}
00070 };
00071
00072
00073
00074 GUID DP_GUID = {0x6bb78285, 0x71df, 0x11d2, 0xb4, 0x6c, 0xc, 0x78, 0xc, 0xc1, 0x8, 0x40};
00075
00077
00079
00080 void LobbyRegister(void)
00081 {
00082 HRESULT r;
00083 DPAPPLICATIONDESC app;
00084 char dir[256];
00085
00086
00087
00088 r = CoCreateInstance(CLSID_DirectPlayLobby, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlayLobby3A, (void**)&Lobby);
00089 if (r != DP_OK)
00090 {
00091 ErrorDX(r, "Can't create DirectPlay Lobby object");
00092 QuitGame = TRUE;
00093 return;
00094 }
00095
00096
00097
00098 GetCurrentDirectory(256, dir);
00099
00100 app.dwSize = sizeof(app);
00101 app.dwFlags = 0;
00102 app.lpszApplicationNameA = "Revolt";
00103 app.guidApplication = DP_GUID;
00104 app.lpszFilenameA = "revolt.exe";
00105 app.lpszCommandLineA = "";
00106 app.lpszPathA = dir;
00107 app.lpszCurrentDirectoryA = dir;
00108 app.lpszDescriptionA = NULL;
00109 app.lpszDescriptionW = NULL;
00110
00111 r = Lobby->RegisterApplication(0, &app);
00112 if (r != DP_OK)
00113 {
00114 ErrorDX(r, "Can't register for lobby support");
00115 QuitGame = TRUE;
00116 return;
00117 }
00118
00119
00120
00121 RELEASE(Lobby);
00122 }
00123
00125
00127
00128 bool InitPlay(void)
00129 {
00130 HRESULT r;
00131 char i;
00132
00133
00134
00135 r = CoCreateInstance(CLSID_DirectPlay, NULL, CLSCTX_INPROC_SERVER, IID_IDirectPlay4A, (void**)&DP);
00136 if (r != DP_OK)
00137 {
00138 ErrorDX(r, "Can't create DirectPlay object");
00139 QuitGame = TRUE;
00140 return FALSE;
00141 }
00142
00143
00144
00145 ConnectionCount = 0;
00146 for (i = 0 ; i < CONNECTION_MAX ; i++) Connection[i].Ptr = NULL;
00147
00148 r = DP->EnumConnections(&DP_GUID, EnumConnectionsCallback, NULL, DPCONNECTION_DIRECTPLAY);
00149 if (r != DP_OK)
00150 {
00151 ErrorDX(r, "Can't enumerate DirectPlay connections");
00152 QuitGame = TRUE;
00153 return FALSE;
00154 }
00155
00156
00157
00158 PlayerEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
00159 if (!PlayerEvent)
00160 {
00161 ErrorDX(0, "Can't create player event!");
00162 QuitGame = TRUE;
00163 return FALSE;
00164 }
00165
00166
00167
00168 return TRUE;
00169 }
00170
00172
00174
00175 void KillPlay(void)
00176 {
00177 char i;
00178
00179
00180
00181 CloseHandle(PlayerEvent);
00182
00183
00184
00185 for (i = 0 ; i < CONNECTION_MAX ; i++) if (Connection[i].Ptr)
00186 {
00187 free(Connection[i].Ptr);
00188 Connection[i].Ptr = NULL;
00189 }
00190
00191
00192
00193 RELEASE(DP);
00194 }
00195
00197
00199
00200 BOOL FAR PASCAL EnumConnectionsCallback(LPCGUID lpguidSP, LPVOID lpConnection, DWORD dwConnectionSize, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext)
00201 {
00202
00203
00204
00205 if (ConnectionCount >= CONNECTION_MAX) return FALSE;
00206
00207
00208
00209 memcpy(Connection[ConnectionCount].Name, lpName->lpszShortNameA, 128);
00210 Connection[ConnectionCount].Ptr = malloc(dwConnectionSize);
00211 memcpy(Connection[ConnectionCount].Ptr, lpConnection, dwConnectionSize);
00212
00213
00214
00215 ConnectionCount++;
00216 return TRUE;
00217 }
00218
00220
00222
00223 bool InitConnection(char num)
00224 {
00225 HRESULT r;
00226
00227
00228
00229 r = DP->InitializeConnection(Connection[num].Ptr, 0);
00230 if (r != DP_OK)
00231 {
00232 ErrorDX(r, "Can't init DirectPlay connection");
00233 QuitGame = TRUE;
00234 return FALSE;
00235 }
00236
00237
00238
00239 return TRUE;
00240 }
00241
00243
00245
00246 bool CreateSession(char *name)
00247 {
00248 HRESULT r;
00249
00250
00251
00252 ZeroMemory(&Session, sizeof(Session));
00253 Session.dwSize = sizeof(Session);
00254
00255 Session.dwFlags = DPSESSION_DIRECTPLAYPROTOCOL | DPSESSION_MULTICASTSERVER | DPSESSION_KEEPALIVE;
00256 Session.guidApplication = DP_GUID;
00257 Session.dwMaxPlayers = MAX_NUM_PLAYERS;
00258 Session.lpszSessionNameA = name;
00259
00260
00261
00262 r = DP->Open(&Session, DPOPEN_CREATE);
00263 if (r != DP_OK)
00264 {
00265 ErrorDX(r, "Can't create DirectPlay session");
00266 QuitGame = TRUE;
00267 return FALSE;
00268 }
00269
00270
00271
00272 return TRUE;
00273 }
00274
00276
00278
00279 bool JoinSession(char num)
00280 {
00281 HRESULT r;
00282
00283
00284
00285 ZeroMemory(&SessionJoin, sizeof(SessionJoin));
00286 SessionJoin.dwSize = sizeof(SessionJoin);
00287 SessionJoin.guidInstance = SessionList[num].Guid;
00288
00289
00290
00291 r = DP->Open(&SessionJoin, DPOPEN_JOIN);
00292 if (r != DP_OK)
00293 {
00294 ErrorDX(r, "Can't join DirectPlay session");
00295 QuitGame = TRUE;
00296 return FALSE;
00297 }
00298
00299
00300
00301 return TRUE;
00302 }
00303
00305
00307
00308 void ListSessions(void)
00309 {
00310 SessionCount = 0;
00311
00312 ZeroMemory(&SessionEnum, sizeof(SessionEnum));
00313 SessionEnum.dwSize = sizeof(SessionEnum);
00314 SessionEnum.guidApplication = DP_GUID;
00315
00316 DP->EnumSessions(&SessionEnum, 0, EnumSessionsCallback, NULL, DPENUMSESSIONS_ASYNC | DPENUMSESSIONS_ALL);
00317 }
00318
00320
00322
00323 void StopSessionEnum(void)
00324 {
00325 ZeroMemory(&SessionEnum, sizeof(SessionEnum));
00326 SessionEnum.dwSize = sizeof(SessionEnum);
00327 SessionEnum.guidApplication = DP_GUID;
00328
00329 DP->EnumSessions(&SessionEnum, 0, EnumSessionsCallback, NULL, DPENUMSESSIONS_STOPASYNC);
00330 }
00331
00333
00335
00336 BOOL FAR PASCAL EnumSessionsCallback(LPCDPSESSIONDESC2 lpSessionDesc, LPDWORD lpdwTimeOut, DWORD dwFlags, LPVOID lpContext)
00337 {
00338
00339
00340
00341 if (SessionCount >= SESSION_MAX) return FALSE;
00342
00343
00344
00345 if (dwFlags & DPESC_TIMEDOUT) return FALSE;
00346
00347
00348
00349 memcpy(SessionList[SessionCount].Name, lpSessionDesc->lpszSessionNameA, MAX_SESSION_NAME);
00350 SessionList[SessionCount].Guid = lpSessionDesc->guidInstance;
00351 SessionList[SessionCount].Flags = lpSessionDesc->dwFlags;
00352
00353
00354
00355 SessionCount++;
00356 return TRUE;
00357 }
00358
00360
00362
00363 bool CreatePlayer(char *name, long server)
00364 {
00365 DPNAME dpname;
00366 HRESULT r;
00367
00368
00369
00370 ZeroMemory(&dpname, sizeof(dpname));
00371 dpname.dwSize = sizeof(dpname);
00372 dpname.lpszShortNameA = name;
00373 dpname.lpszLongNameA = NULL;
00374
00375
00376
00377 LocalPlayerData.CarID = GameSettings.CarID;
00378
00379
00380
00381 r = DP->CreatePlayer(&LocalPlayerID, &dpname, PlayerEvent, &LocalPlayerData, sizeof(LocalPlayerData), 0);
00382 if (r != DP_OK)
00383 {
00384 ErrorDX(r, "Can't create a player");
00385 QuitGame = TRUE;
00386 return FALSE;
00387 }
00388
00389
00390
00391 return TRUE;
00392 }
00393
00395
00397
00398 void DisplayPlayers(void)
00399 {
00400 short j;
00401 PLAYER *player;
00402
00403 j = 128;
00404 for (player = PLR_PlayerHead ; player ; player = player->next)
00405 {
00406 DumpText(0, j, 8, 16, 0x000080, player->PlayerName);
00407 j += 16;
00408 }
00409 }
00410
00412
00414
00415 void TransmitMessage(char *buff, short size, DPID to, long pri)
00416 {
00417 HRESULT r;
00418
00419 r = DP->SendEx(LocalPlayerID, to, DPSEND_ASYNC | DPSEND_NOSENDCOMPLETEMSG, buff, size, pri, 0, NULL, NULL);
00420
00421 }
00422
00424
00426
00427 void TransmitMessageGuaranteed(char *buff, short size, DPID to, long pri)
00428 {
00429 HRESULT r;
00430
00431 r = DP->SendEx(LocalPlayerID, to, DPSEND_GUARANTEED, buff, size, pri, 0, NULL, NULL);
00432 }
00433
00435
00437
00438 void CancelPriority(long pri)
00439 {
00440 HRESULT r;
00441
00442 r = DP->CancelPriority(pri, pri, 0);
00443 if (r != DP_OK)
00444 ErrorDX(r, "can't cancel priority!");
00445 }
00446
00448
00450
00451 char GetRemoteMessages(void)
00452 {
00453 HRESULT r;
00454 DWORD size;
00455 char flag = FALSE;
00456
00457
00458
00459 do
00460 {
00461
00462
00463
00464 size = 1024;
00465 r = DP->Receive(&FromID, &ToID, DPRECEIVE_ALL, ReceiveBuff, &size);
00466
00467
00468
00469 if (r == DP_OK)
00470 {
00471
00472
00473
00474 flag = TRUE;
00475
00476
00477
00478 if (FromID == DPID_SYSMSG)
00479 {
00480 ProcessSystemMessage();
00481 }
00482
00483
00484
00485 else
00486 {
00487 ProcessPersonalMessage();
00488 }
00489 }
00490
00491
00492
00493 } while (r != DPERR_NOMESSAGES);
00494
00495
00496
00497 return flag;
00498 }
00499
00501
00503
00504 void ProcessPersonalMessage(void)
00505 {
00506 long i, flag;
00507 char buf[128];
00508 MESSAGE_HEADER *header = (MESSAGE_HEADER*)ReceiveBuff;
00509
00510
00511
00512 switch (header->Type)
00513 {
00514
00515
00516
00517 case MESSAGE_GAME_STARTED:
00518
00519 GameStarted = TRUE;
00520 ServerID = FromID;
00521
00522 StartData = *(START_DATA*)(header + 1);
00523
00524 flag = FALSE;
00525 for (i = 0 ; i < GameSettings.LevelNum ; i++)
00526 {
00527 if (!strcmp(StartData.LevelDir, LevelInf[i].Dir))
00528 {
00529 GameSettings.Level = i;
00530 flag = TRUE;
00531 break;
00532 }
00533 }
00534
00535 if (!flag)
00536 {
00537 wsprintf(buf, "Can't find Level directory '%s'", StartData.LevelDir);
00538 Box(NULL, buf, MB_OK);
00539 QuitGame = TRUE;
00540 }
00541
00542 break;
00543
00544
00545
00546 case MESSAGE_CAR_DATA:
00547 ProcessCarMessage();
00548 break;
00549
00550
00551
00552 case MESSAGE_PING_REQUEST:
00553 ProcessPingRequest();
00554 break;
00555
00556
00557
00558 case MESSAGE_PING_RETURN:
00559 ProcessPingReturn();
00560 break;
00561
00562
00563
00564 case MESSAGE_PLAYER_READY:
00565 ProcessPlayerReady();
00566 break;
00567
00568
00569
00570 case MESSAGE_SYNC_TIMERS1:
00571 ProcessSyncTimers1();
00572 break;
00573
00574
00575
00576 case MESSAGE_SYNC_TIMERS2:
00577 ProcessSyncTimers2();
00578 break;
00579
00580
00581
00582 case MESSAGE_SYNC_TIMERS3:
00583 ProcessSyncTimers3();
00584 break;
00585 }
00586 }
00587
00589
00591
00592 void ProcessCarMessage()
00593 {
00594 REMOTE_DATA *rem;
00595 CAR *car;
00596 PLAYER *player;
00597 MESSAGE_HEADER *header = (MESSAGE_HEADER*)ReceiveBuff;
00598 short *sh;
00599 char *ptr = (char*)(header + 1);
00600
00601
00602
00603 for (player = PLR_PlayerHead ; player ; player = player->next) if ((player->type == PLAYER_REMOTE) && (FromID == player->PlayerID))
00604 {
00605 car = &player->car;
00606 break;
00607 }
00608
00609
00610
00611 rem = NextRemoteData(car);
00612
00613 rem->PacketInfo = 0;
00614
00615
00616
00617 rem->PacketInfo |= REMOTE_TIME;
00618
00619
00620
00621 if (header->Contents & MESSAGE_CONTENTS_CAR_POS)
00622 {
00623 CopyVec((VEC*)ptr, &rem->Pos);
00624 rem->PacketInfo |= REMOTE_POS;
00625 ptr += sizeof(VEC);
00626 }
00627
00628
00629
00630 if (header->Contents & MESSAGE_CONTENTS_CAR_QUAT)
00631 {
00632 rem->Quat.v[VX] = ((REAL)*ptr++ / CAR_REMOTE_QUAT_SCALE);
00633 rem->Quat.v[VY] = ((REAL)*ptr++ / CAR_REMOTE_QUAT_SCALE);
00634 rem->Quat.v[VZ] = ((REAL)*ptr++ / CAR_REMOTE_QUAT_SCALE);
00635 rem->Quat.v[S] = ((REAL)*ptr++ / CAR_REMOTE_QUAT_SCALE);
00636 NormalizeQuat(&rem->Quat);
00637 rem->PacketInfo |= REMOTE_QUAT;
00638 }
00639
00640
00641
00642 if (header->Contents & MESSAGE_CONTENTS_CAR_VEL)
00643 {
00644 sh = (short*)ptr;
00645 rem->Vel.v[X] = ((REAL)*sh++ / CAR_REMOTE_VEL_SCALE);
00646 rem->Vel.v[Y] = ((REAL)*sh++ / CAR_REMOTE_VEL_SCALE);
00647 rem->Vel.v[Z] = ((REAL)*sh++ / CAR_REMOTE_VEL_SCALE);
00648 rem->PacketInfo |= REMOTE_VEL;
00649 ptr = (char*)sh;
00650 }
00651
00652
00653
00654 if (header->Contents & MESSAGE_CONTENTS_CAR_ANGVEL)
00655 {
00656 sh = (short*)ptr;
00657 rem->AngVel.v[X] = ((REAL)*sh++ / CAR_REMOTE_ANGVEL_SCALE);
00658 rem->AngVel.v[Y] = ((REAL)*sh++ / CAR_REMOTE_ANGVEL_SCALE);
00659 rem->AngVel.v[Z] = ((REAL)*sh++ / CAR_REMOTE_ANGVEL_SCALE);
00660 rem->PacketInfo |= REMOTE_ANGVEL;
00661 ptr = (char*)sh;
00662
00663 }
00664
00665
00666
00667 if (header->Contents & MESSAGE_CONTENTS_CAR_CONTROL)
00668 {
00669 rem->dx = *ptr++;
00670 rem->dy = *ptr++;
00671 rem->PacketInfo |= REMOTE_CONTROL;
00672 }
00673
00674 rem->NewData = TRUE;
00675
00676 }
00677
00679
00681
00682 void RequestPings(void)
00683 {
00684 long i;
00685 MESSAGE_HEADER *header = (MESSAGE_HEADER*)TransmitBuff;
00686 unsigned long *ptr = (unsigned long*)(header + 1);
00687
00688
00689
00690 for (i = 0 ; i < PlayerCount ; i++)
00691 {
00692 if (PlayerList[i].PlayerID == LocalPlayerID)
00693 PlayerList[i].Ping = 0;
00694 }
00695
00696
00697
00698 header->Type = MESSAGE_PING_REQUEST;
00699 ptr[0] = CurrentTimer();
00700
00701
00702
00703 TransmitMessage(TransmitBuff, sizeof(MESSAGE_HEADER) + sizeof(long), DPID_ALLPLAYERS, MESSAGE_PRIORITY_NORMAL);
00704 }
00705
00707
00709
00710 void ProcessPingRequest(void)
00711 {
00712 MESSAGE_HEADER *rheader = (MESSAGE_HEADER*)ReceiveBuff;
00713 MESSAGE_HEADER *theader = (MESSAGE_HEADER*)TransmitBuff;
00714 long *rptr = (long*)(rheader + 1);
00715 long *tptr = (long*)(theader + 1);
00716
00717
00718
00719 theader->Type = MESSAGE_PING_RETURN;
00720 tptr[0] = rptr[0];
00721
00722
00723
00724 TransmitMessage(TransmitBuff, sizeof(MESSAGE_HEADER) + sizeof(long) * 2, FromID, MESSAGE_PRIORITY_NORMAL);
00725 }
00726
00728
00730
00731 void ProcessPingReturn(void)
00732 {
00733 MESSAGE_HEADER *header = (MESSAGE_HEADER*)ReceiveBuff;
00734 long i;
00735 unsigned long ping, *ptr = (unsigned long*)(header + 1);
00736
00737
00738
00739 ping = TIME2MS(CurrentTimer() - ptr[0]);
00740
00741
00742
00743 for (i = 0 ; i < PlayerCount ; i++) if (PlayerList[i].PlayerID == FromID)
00744 {
00745 PlayerList[i].Ping = ping;
00746 }
00747 }
00748
00750
00752
00753 void ProcessPlayerReady(void)
00754 {
00755 PLAYER *player;
00756
00757
00758
00759 if (!ReadyFlag)
00760 return;
00761
00762 for (player = PLR_PlayerHead ; player ; player = player->next) if ((player->type == PLAYER_REMOTE) && (FromID == player->PlayerID))
00763 {
00764 player->Ready = TRUE;
00765 }
00766 }
00767
00769
00771
00772 void ProcessSyncTimers1(void)
00773 {
00774 MESSAGE_HEADER *rh = (MESSAGE_HEADER*)ReceiveBuff;
00775 MESSAGE_HEADER *th = (MESSAGE_HEADER*)TransmitBuff;
00776 unsigned long *rptr = (unsigned long*)(rh + 1);
00777 unsigned long *tptr = (unsigned long*)(th + 1);
00778
00779
00780
00781 ReadyFlag = TRUE;
00782
00783
00784
00785 th->Type = MESSAGE_SYNC_TIMERS2;
00786 tptr[0] = rptr[0];
00787 tptr[1] = CurrentTimer();
00788
00789 TransmitMessage(TransmitBuff, sizeof(MESSAGE_HEADER) + sizeof(unsigned long) * 2, FromID, MESSAGE_PRIORITY_NORMAL);
00790 }
00791
00793
00795
00796 void ProcessSyncTimers2(void)
00797 {
00798 MESSAGE_HEADER *rh = (MESSAGE_HEADER*)ReceiveBuff;
00799 MESSAGE_HEADER *th = (MESSAGE_HEADER*)TransmitBuff;
00800 unsigned long *rptr = (unsigned long*)(rh + 1);
00801 unsigned long *tptr = (unsigned long*)(th + 1);
00802
00803
00804
00805 th->Type = MESSAGE_SYNC_TIMERS3;
00806 tptr[0] = TIME2MS(CurrentTimer() - rptr[0]);
00807 tptr[1] = rptr[1];
00808
00809 TransmitMessage(TransmitBuff, sizeof(MESSAGE_HEADER) + sizeof(unsigned long) * 2, FromID, MESSAGE_PRIORITY_NORMAL);
00810 }
00811
00813
00815
00816 void ProcessSyncTimers3(void)
00817 {
00818 MESSAGE_HEADER *header = (MESSAGE_HEADER*)ReceiveBuff;
00819 unsigned long *ptr = (unsigned long*)(header + 1), ping;
00820
00821
00822
00823 ping = TIME2MS(CurrentTimer() - ptr[1]) + (ptr[0] / 2);
00824
00825
00826
00827 CountdownEndTime = CurrentTimer() + MS2TIME(COUNTDOWN_START - ping);
00828 CountdownTime = TRUE;
00829
00830
00831
00832 ReadyFlag = TRUE;
00833 }
00834
00836
00838
00839 void ProcessSystemMessage(void)
00840 {
00841 DPMSG_GENERIC *Message = (DPMSG_GENERIC*)ReceiveBuff;
00842 DPMSG_CREATEPLAYERORGROUP *Player;
00843 PLAYER *player, *next;
00844
00845 switch (Message->dwType)
00846 {
00847
00848
00849
00850 case DPSYS_CREATEPLAYERORGROUP:
00851 break;
00852
00853
00854
00855 case DPSYS_DESTROYPLAYERORGROUP:
00856 Player = (DPMSG_CREATEPLAYERORGROUP*)ReceiveBuff;
00857 if (Player->dwPlayerType == DPPLAYERTYPE_PLAYER)
00858 {
00859 for (player = PLR_PlayerHead ; player ; )
00860 {
00861 next = player->next;
00862 if ((player->type == PLAYER_REMOTE) && player->PlayerID == Player->dpId)
00863 {
00864 PLR_KillPlayer(player);
00865 }
00866 player = next;
00867 }
00868 }
00869 break;
00870
00871
00872
00873 case DPSYS_SESSIONLOST:
00874 Box(NULL, "Session lost!", MB_OK);
00875 GameSettings.GameType = GAMETYPE_SESSIONLOST;
00876 break;
00877
00878
00879
00880 case DPSYS_HOST:
00881 GameSettings.GameType = GAMETYPE_SERVER;
00882 ServerID = LocalPlayerID;
00883 break;
00884 }
00885 }
00886
00888
00890
00891 void ListPlayers(GUID *guid)
00892 {
00893 PlayerCount = 0;
00894 if (!guid) DP->EnumPlayers(NULL, EnumPlayersCallback, NULL, DPENUMPLAYERS_ALL);
00895 else DP->EnumPlayers(guid, EnumPlayersCallback, NULL, DPENUMPLAYERS_SESSION);
00896 }
00897
00899
00901
00902 BOOL FAR PASCAL EnumPlayersCallback(DPID dpId, DWORD dwPlayerType, LPCDPNAME lpName, DWORD dwFlags, LPVOID lpContext)
00903 {
00904 DWORD size;
00905
00906
00907
00908 if (PlayerCount >= MAX_NUM_PLAYERS) return FALSE;
00909
00910
00911
00912 PlayerList[PlayerCount].PlayerID = dpId;
00913 strncpy(PlayerList[PlayerCount].Name, lpName->lpszShortNameA, MAX_PLAYER_NAME);
00914 DP->GetPlayerCaps(PlayerList[PlayerCount].PlayerID, &PlayerList[PlayerCount].Caps, NULL);
00915
00916
00917
00918 size = sizeof(DP_PLAYER_DATA);
00919 DP->GetPlayerData(PlayerList[PlayerCount].PlayerID, &PlayerList[PlayerCount].Data, &size, DPGET_REMOTE);
00920
00921
00922
00923 PlayerCount++;
00924 return TRUE;
00925 }
00926
00928
00930
00931 void ConnectionMenu(void)
00932 {
00933 short i;
00934 long col;
00935
00936
00937
00938 CheckSurfaces();
00939 FlipBuffers();
00940 ClearBuffers();
00941
00942
00943
00944 ReadMouse();
00945 ReadKeyboard();
00946
00947 if (Keys[DIK_UP] && !LastKeys[DIK_UP] && MenuCount) MenuCount--;
00948 if (Keys[DIK_DOWN] && !LastKeys[DIK_DOWN] && MenuCount < ConnectionCount - 1) MenuCount++;
00949
00950
00951
00952 D3Ddevice->BeginScene();
00953
00954 BlitBitmap(TitleHbm, &BackBuffer);
00955
00956 BeginTextState();
00957
00958 DumpText(128, 112, 12, 24, 0x808000, "Select Connection:");
00959
00960 for (i = 0 ; i < ConnectionCount ; i++)
00961 {
00962 if (MenuCount == i) col = 0xff0000;
00963 else col = 0x808080;
00964 DumpText(128, i * 48 + 176, 12, 24, col, Connection[i].Name);
00965 }
00966
00967 D3Ddevice->EndScene();
00968
00969
00970
00971 if (Keys[DIK_ESCAPE] && !LastKeys[DIK_ESCAPE])
00972 {
00973 KillPlay();
00974 MenuCount = 0;
00975 Event = MainMenu;
00976 }
00977
00978 if (Keys[DIK_RETURN] && !LastKeys[DIK_RETURN])
00979 {
00980 InitConnection((char)MenuCount);
00981
00982 if (GameSettings.GameType == GAMETYPE_SERVER)
00983 {
00984 MenuCount = 0;
00985 Event = GetSessionName;
00986 }
00987
00988 else
00989 {
00990 MenuCount = 0;
00991 SessionCount = 0;
00992 SessionRequestTime = 0.0f;
00993 Event = LookForSessions;
00994 }
00995 }
00996 }
00997
00999
01001
01002 void GetSessionName(void)
01003 {
01004 unsigned char c;
01005
01006
01007
01008 CheckSurfaces();
01009 FlipBuffers();
01010 ClearBuffers();
01011
01012
01013
01014 ReadMouse();
01015 ReadKeyboard();
01016
01017 if ((c = GetKeyPress()))
01018 {
01019
01020
01021
01022 if (c == 8)
01023 {
01024 if (MenuCount) MenuCount--;
01025 }
01026
01027
01028
01029 else if (c == 9)
01030 {
01031 MenuCount = 0;
01032 }
01033
01034
01035
01036 else if (c == 13)
01037 {
01038 SessionName[MenuCount] = 0;
01039 CreateSession(SessionName);
01040 CreatePlayer(RegistrySettings.PlayerName, TRUE);
01041 PingRequestTime = 0.0f;
01042 Event = HostWait;
01043 }
01044
01045
01046
01047 else if (c == 27)
01048 {
01049 MenuCount = 0;
01050 KillPlay();
01051 InitPlay();
01052 Event = ConnectionMenu;
01053 }
01054
01055
01056
01057 else if (MenuCount < MAX_SESSION_NAME - 2)
01058 {
01059 SessionName[MenuCount++] = c;
01060 }
01061 }
01062
01063
01064
01065 D3Ddevice->BeginScene();
01066
01067 BlitBitmap(TitleHbm, &BackBuffer);
01068
01069 BeginTextState();
01070
01071 DumpText(208, 224, 12, 24, 0x808000, "Enter Game Name:");
01072 SessionName[MenuCount] = '_';
01073 SessionName[MenuCount + 1] = 0;
01074 DumpText(128, 276, 12, 24, 0x808080, SessionName);
01075
01076 D3Ddevice->EndScene();
01077 }
01078
01080
01082
01083 void LookForSessions(void)
01084 {
01085 short i;
01086 long col;
01087 char state[7];
01088
01089
01090
01091 CheckSurfaces();
01092 FlipBuffers();
01093 ClearBuffers();
01094
01095
01096
01097 UpdateTimeFactor();
01098 ReadMouse();
01099 ReadKeyboard();
01100
01101
01102
01103 BlitBitmap(TitleHbm, &BackBuffer);
01104
01105
01106
01107 D3Ddevice->BeginScene();
01108
01109
01110
01111 SessionRequestTime -= TimeStep;
01112 if (SessionRequestTime < 0.0f)
01113 {
01114 ListSessions();
01115 SessionRequestTime = 2.0f;
01116
01117 if (SessionCount)
01118 {
01119 if (MenuCount > SessionCount - 1) MenuCount = SessionCount - 1;
01120 ListPlayers(&SessionList[MenuCount].Guid);
01121 }
01122 }
01123
01124
01125
01126 BeginTextState();
01127
01128 DumpText(264, 16, 8, 16, 0x808000, "Choose a Game:");
01129
01130 for (i = 0 ; i < SessionCount ; i++)
01131 {
01132 if (MenuCount == i) col = 0xff0000;
01133 else col = 0x808080;
01134 DumpText(168, i * 16 + 48, 8, 16, col, SessionList[i].Name);
01135 if (SessionList[i].Flags & DPSESSION_JOINDISABLED) memcpy(state, "CLOSED", sizeof(state));
01136 else memcpy(state, "OPEN", sizeof(state));
01137 DumpText(432, i * 16 + 48, 8, 16, 0x808000, state);
01138 }
01139
01140
01141
01142 if (!SessionCount) PlayerCount = 0;
01143
01144 if (PlayerCount)
01145 {
01146 DumpText(288, 192, 8, 16, 0x808000, "Players:");
01147 for (i = 0 ; i < PlayerCount ; i++)
01148 {
01149 DumpText(168, i * 16 + 224, 8, 16, 0xff0000, PlayerList[i].Name);
01150 }
01151 }
01152
01153
01154
01155 D3Ddevice->EndScene();
01156
01157
01158
01159 if (Keys[DIK_UP] && !LastKeys[DIK_UP] && MenuCount) MenuCount--;
01160 if (Keys[DIK_DOWN] && !LastKeys[DIK_DOWN]) MenuCount++;
01161 if (SessionCount && MenuCount >= SessionCount) MenuCount = SessionCount - 1;
01162
01163
01164
01165 if (Keys[DIK_ESCAPE] && !LastKeys[DIK_ESCAPE])
01166 {
01167 StopSessionEnum();
01168 KillPlay();
01169 InitPlay();
01170 MenuCount = 0;
01171 Event = ConnectionMenu;
01172 }
01173
01174
01175
01176 if (Keys[DIK_RETURN] && !LastKeys[DIK_RETURN] && SessionCount && !(SessionList[MenuCount].Flags & DPSESSION_JOINDISABLED))
01177 {
01178 JoinSession((char)MenuCount);
01179 CreatePlayer(RegistrySettings.PlayerName, FALSE);
01180 GameStarted = FALSE;
01181 PingRequestTime = 0.0f;
01182 Event = ClientWait;
01183 }
01184 }
01185
01187
01189
01190 void HostWait(void)
01191 {
01192 long i, j, k, gridused[MAX_NUM_PLAYERS];
01193 MESSAGE_HEADER *header;
01194 char buf[128];
01195
01196
01197
01198 CheckSurfaces();
01199 FlipBuffers();
01200 ClearBuffers();
01201
01202
01203
01204 UpdateTimeFactor();
01205 ReadMouse();
01206 ReadKeyboard();
01207
01208
01209
01210 D3Ddevice->BeginScene();
01211
01212 BlitBitmap(TitleHbm, &BackBuffer);
01213
01214 BeginTextState();
01215
01216 DumpText(288, 64, 8, 16, 0x808000, "Players:");
01217 DumpText(216, 400, 8, 16, 0x808000, "Hit Enter To Start Game...");
01218
01219 ListPlayers(NULL);
01220
01221 PingRequestTime -= TimeStep;
01222 if (PingRequestTime < 0.0f)
01223 {
01224 RequestPings();
01225 PingRequestTime = 2.0f;
01226 }
01227
01228 GetRemoteMessages();
01229
01230 for (i = 0 ; i < PlayerCount ; i++)
01231 {
01232 DumpText(192, i * 16 + 96, 8, 16, 0xff0000, PlayerList[i].Name);
01233 wsprintf(buf, "%ld", PlayerList[i].Ping);
01234 DumpText(448, i * 16 + 96, 8, 16, 0xff0000, buf);
01235 }
01236
01237 D3Ddevice->EndScene();
01238
01239
01240
01241 if (Keys[DIK_ESCAPE] && !LastKeys[DIK_ESCAPE])
01242 {
01243 DP->Close();
01244 Event = GetSessionName;
01245 }
01246
01247
01248
01249 if (Keys[DIK_RETURN] && !LastKeys[DIK_RETURN])
01250 {
01251
01252
01253
01254 Session.dwFlags |= DPSESSION_JOINDISABLED;
01255 DP->SetSessionDesc(&Session, NULL);
01256
01257
01258
01259 StartData.PlayerNum = PlayerCount;
01260 strncpy(StartData.LevelDir, LevelInf[GameSettings.Level].Dir, MAX_LEVEL_DIR_NAME);
01261
01262 for (i = 0 ; i < StartData.PlayerNum ; i++)
01263 gridused[i] = FALSE;
01264
01265 for (i = 0 ; i < StartData.PlayerNum ; i++)
01266 {
01267 StartData.PlayerData[i].PlayerID = PlayerList[i].PlayerID;
01268 StartData.PlayerData[i].CarID = PlayerList[i].Data.CarID;
01269 strncpy(StartData.PlayerData[i].Name, PlayerList[i].Name, MAX_PLAYER_NAME);
01270
01271 k = (rand() % (StartData.PlayerNum - i)) + 1;
01272 for (j = 0 ; j < StartData.PlayerNum ; j++)
01273 {
01274 if (!gridused[j])
01275 k--;
01276
01277 if (!k)
01278 {
01279 StartData.PlayerData[i].GridNum = j;
01280 gridused[j] = TRUE;
01281 break;
01282 }
01283 }
01284 }
01285
01286
01287
01288 header = (MESSAGE_HEADER*)TransmitBuff;
01289 header->Type = MESSAGE_GAME_STARTED;
01290
01291 memcpy(header + 1, &StartData, sizeof(START_DATA));
01292
01293 TransmitMessageGuaranteed(TransmitBuff, sizeof(MESSAGE_HEADER) + sizeof(START_DATA), DPID_ALLPLAYERS, MESSAGE_PRIORITY_NORMAL);
01294 ReadyFlag = FALSE;
01295
01296 Event = SetupGame;
01297 }
01298 }
01299
01301
01303
01304 void ClientWait(void)
01305 {
01306 short i;
01307 char buf[128];
01308
01309
01310
01311 CheckSurfaces();
01312 FlipBuffers();
01313 ClearBuffers();
01314
01315
01316
01317 UpdateTimeFactor();
01318 ReadMouse();
01319 ReadKeyboard();
01320
01321
01322
01323 D3Ddevice->BeginScene();
01324
01325 BlitBitmap(TitleHbm, &BackBuffer);
01326
01327 BeginTextState();
01328
01329 DumpText(288, 64, 8, 16, 0x808000, "Players:");
01330 DumpText(240, 400, 8, 16, 0x808000, "Waiting For Host...");
01331
01332 ListPlayers(NULL);
01333
01334 PingRequestTime -= TimeStep;
01335 if (PingRequestTime < 0.0f)
01336 {
01337 RequestPings();
01338 PingRequestTime = 2.0f;
01339 }
01340
01341 GetRemoteMessages();
01342
01343 for (i = 0 ; i < PlayerCount ; i++)
01344 {
01345 DumpText(192, i * 16 + 96, 8, 16, 0xff0000, PlayerList[i].Name);
01346 wsprintf(buf, "%ld", PlayerList[i].Ping);
01347 DumpText(448, i * 16 + 96, 8, 16, 0xff0000, buf);
01348 }
01349
01350 D3Ddevice->EndScene();
01351
01352
01353
01354 if ((Keys[DIK_ESCAPE] && !LastKeys[DIK_ESCAPE]) || GameSettings.GameType != GAMETYPE_CLIENT)
01355 {
01356 DP->Close();
01357 MenuCount = 0;
01358 GameSettings.GameType = GAMETYPE_CLIENT;
01359 Event = LookForSessions;
01360 }
01361
01362
01363
01364 if (GameStarted)
01365 {
01366 Event = SetupGame;
01367 }
01368 }
01369
01371
01373
01374 char GetHostDetails(void)
01375 {
01376 int r;
01377 static char hostname[1024];
01378 HOSTENT *he;
01379
01380
01381
01382 r = gethostname(hostname, sizeof(hostname));
01383 if (r == SOCKET_ERROR)
01384 return FALSE;
01385
01386
01387
01388 he = gethostbyname(hostname);
01389 if (!he)
01390 return FALSE;
01391
01392
01393
01394 memcpy(HostName, he->h_name, MAX_HOST_NAME);
01395
01396 IP[0] = (*he->h_addr_list)[0];
01397 IP[1] = (*he->h_addr_list)[1];
01398 IP[2] = (*he->h_addr_list)[2];
01399 IP[3] = (*he->h_addr_list)[3];
01400
01401
01402
01403 return TRUE;
01404 }
01405
01407
01409
01410 char CheckLegalIP(void)
01411 {
01412 LEGAL_IP *lip;
01413
01414
01415
01416 if (!InitPlay())
01417 return FALSE;
01418
01419 if (!InitConnection(0))
01420 {
01421 KillPlay();
01422 return FALSE;
01423 }
01424
01425
01426
01427 if (!GetHostDetails())
01428 {
01429 KillPlay();
01430 return FALSE;
01431 }
01432
01433
01434
01435 KillPlay();
01436
01437
01438
01439 for (lip = LegalIP ; *(long*)lip->Mask ; lip++)
01440 {
01441 if ((IP[0] & lip->Mask[0]) == lip->IP[0] &&
01442 (IP[1] & lip->Mask[1]) == lip->IP[1] &&
01443 (IP[2] & lip->Mask[2]) == lip->IP[2] &&
01444 (IP[3] & lip->Mask[3]) == lip->IP[3])
01445 return TRUE;
01446 }
01447
01448
01449
01450 return FALSE;
01451 }
01452
01454
01456
01457 void RemoteSync(void)
01458 {
01459 unsigned long flag, quit, time, starttime, sendtime;
01460 PLAYER *player;
01461 MESSAGE_HEADER *header = (MESSAGE_HEADER*)TransmitBuff;
01462
01463
01464
01465 if (GameSettings.GameType == GAMETYPE_SERVER)
01466 {
01467
01468
01469
01470 for (player = PLR_PlayerHead ; player ; player = player->next)
01471 player->Ready = FALSE;
01472
01473 ReadyFlag = TRUE;
01474
01475
01476
01477 quit = FALSE;
01478 starttime = CurrentTimer();
01479
01480 while (!quit)
01481 {
01482 GetRemoteMessages();
01483
01484 time = TIME2MS(CurrentTimer() - starttime);
01485 if (time > (1000 * 60))
01486 {
01487 Box(NULL, "Timed out waiting for players to load!", MB_OK);
01488 quit = TRUE;
01489 }
01490
01491 flag = 0;
01492 for (player = PLR_PlayerHead ; player ; player = player->next)
01493 if (player->type == PLAYER_REMOTE && !player->Ready)
01494 flag++;
01495
01496 if (!flag)
01497 quit = TRUE;
01498
01499 if (GameSettings.GameType == GAMETYPE_SESSIONLOST)
01500 {
01501 QuitGame = TRUE;
01502 return;
01503 }
01504 }
01505
01506
01507
01508 CountdownEndTime = CurrentTimer() + MS2TIME(COUNTDOWN_START);
01509 CountdownTime = TRUE;
01510
01511 header->Type = MESSAGE_SYNC_TIMERS1;
01512 *(unsigned long*)(header + 1) = CurrentTimer();
01513 TransmitMessage(TransmitBuff, sizeof(MESSAGE_HEADER) + sizeof(unsigned long), DPID_ALLPLAYERS, MESSAGE_PRIORITY_NORMAL);
01514 }
01515
01516
01517
01518 else
01519 {
01520
01521
01522
01523 ReadyFlag = FALSE;
01524 starttime = CurrentTimer();
01525 sendtime = 0;
01526
01527 while (!ReadyFlag)
01528 {
01529 GetRemoteMessages();
01530
01531 time = TIME2MS(CurrentTimer() - starttime);
01532 if (time > sendtime)
01533 {
01534 header->Type = MESSAGE_PLAYER_READY;
01535 TransmitMessage(TransmitBuff, sizeof(MESSAGE_HEADER), ServerID, MESSAGE_PRIORITY_NORMAL);
01536 sendtime += 1000;
01537 }
01538
01539 if (time > (1000 * 60))
01540 {
01541 Box(NULL, "Timed out waiting for server to start!", MB_OK);
01542 ReadyFlag = TRUE;
01543 }
01544
01545 if (GameSettings.GameType == GAMETYPE_SESSIONLOST)
01546 {
01547 QuitGame = TRUE;
01548 return;
01549 }
01550 }
01551
01552
01553
01554 ReadyFlag = FALSE;
01555
01556 while (!ReadyFlag)
01557 {
01558 GetRemoteMessages();
01559 }
01560 }
01561 }