Advertisement
Guest User

Untitled

a guest
Aug 14th, 2013
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 68.81 KB | None | 0 0
  1. #include "r3dPCH.h"
  2. #include "r3d.h"
  3. #include "GameLevel.h"
  4.  
  5. #include "ServerGameLogic.h"
  6. #include "MasterServerLogic.h"
  7. #include "GameObjects/ObjManag.h"
  8.  
  9. #include "ObjectsCode/obj_ServerPlayer.h"
  10. #include "ObjectsCode/obj_ServerLightMesh.h"
  11. #include "ObjectsCode/sobj_SpawnedItem.h"
  12. #include "ObjectsCode/sobj_DroppedItem.h"
  13. #include "ObjectsCode/sobj_Note.h"
  14. #include "ObjectsCode/Zombies/sobj_Zombie.h"
  15. #include "ObjectsCode/obj_ServerPlayerSpawnPoint.h"
  16. #include "ObjectsCode/obj_ServerBarricade.h"
  17. #include "ObjectsCode/obj_ServerFarmBlock.h"
  18.  
  19. #include "../EclipseStudio/Sources/GameCode/UserProfile.h"
  20. #include "../EclipseStudio/Sources/ObjectsCode/weapons/WeaponArmory.h"
  21.  
  22. #include "ServerWeapons/ServerWeapon.h"
  23.  
  24. #include "AsyncFuncs.h"
  25. #include "Async_Notes.h"
  26. #include "NetworkHelper.h"
  27.  
  28. ServerGameLogic gServerLogic;
  29.  
  30. CVAR_FLOAT( _glm_SpawnRadius,    1.0f, "");
  31.  
  32. extern  __int64 cfg_sessionId;
  33.  
  34. #include "../EclipseStudio/Sources/Gameplay_Params.h"
  35.     CGamePlayParams     GPP_Data;
  36.     DWORD           GPP_Seed = GetTickCount();  // seed used to xor CRC of gpp_data
  37.  
  38.  
  39.  
  40. static bool IsNullTerminated(const char* data, int size)
  41. {
  42.   for(int i=0; i<size; i++) {
  43.     if(data[i] == 0)
  44.       return true;
  45.   }
  46.  
  47.   return false;
  48. }
  49.  
  50. //
  51. //
  52. //
  53. //
  54. static void preparePacket(const GameObject* from, DefaultPacket* packetData)
  55. {
  56.     r3d_assert(packetData);
  57.     r3d_assert(packetData->EventID >= 0);
  58.  
  59.     if(from) {
  60.         r3d_assert(from->GetNetworkID());
  61.         //r3d_assert(from->NetworkLocal);
  62.  
  63.         packetData->FromID = toP2pNetId(from->GetNetworkID());
  64.     } else {
  65.         packetData->FromID = 0; // world event
  66.     }
  67.  
  68.     return;
  69. }
  70.  
  71. ServerGameLogic::ServerGameLogic()
  72. {
  73.     maxPlayers_ = 0;
  74.     curPlayers_ = 0;
  75.     curPeersConnected = 0;
  76.  
  77.     // init index to players table
  78.     for(int i=0; i<MAX_NUM_PLAYERS; i++) {
  79.         plrToPeer_[i] = NULL;
  80.     }
  81.  
  82.     // init peer to player table
  83.     for(int i=0; i<MAX_PEERS_COUNT; i++) {
  84.         peers_[i].Clear();
  85.     }
  86.    
  87.     memset(&netRecvPktSize, 0, sizeof(netRecvPktSize));
  88.     memset(&netSentPktSize, 0, sizeof(netSentPktSize));
  89.  
  90.     net_lastFreeId    = NETID_OBJECTS_START;
  91.     net_mapLoaded_LastNetID = 0;
  92.    
  93.     weaponStats_.reserve(128);
  94. }
  95.  
  96. ServerGameLogic::~ServerGameLogic()
  97. {
  98.     SAFE_DELETE(g_AsyncApiMgr);
  99. }
  100.  
  101. void ServerGameLogic::Init(const GBGameInfo& ginfo, uint32_t creatorID)
  102. {
  103.     r3dOutToLog("Game: Initializing with %d players\n", ginfo.maxPlayers); CLOG_INDENT;
  104.     r3d_assert(curPlayers_ == 0);
  105.     r3d_assert(curPeersConnected == 0);
  106.  
  107.     creatorID_  = creatorID;
  108.     ginfo_      = ginfo;
  109.     maxPlayers_ = ginfo.maxPlayers;
  110.     curPlayers_ = 0;
  111.     curPeersConnected = 0;
  112.  
  113.     // init game time
  114.     gameStartTime_     = r3dGetTime();
  115.    
  116.     __int64 utcTime = GetUtcGameTime();
  117.     struct tm* tm = _gmtime64(&utcTime);
  118.     r3d_assert(tm);
  119.  
  120.     char buf[128];
  121.     asctime_s(buf, sizeof(buf), tm);
  122.     r3dOutToLog("Server time is %s", buf);
  123.    
  124.     weaponDataUpdates_ = 0;
  125.  
  126.     g_AsyncApiMgr = new CAsyncApiMgr();
  127.  
  128.     return;
  129. }
  130.  
  131. void ServerGameLogic::CreateHost(int port)
  132. {
  133.     r3dOutToLog("Starting server on port %d\n", port);
  134.  
  135.     g_net.Initialize(this, "p2pNet");
  136.     g_net.CreateHost(port, MAX_PEERS_COUNT);
  137.     //g_net.dumpStats_ = 2;
  138.  
  139.     return;
  140. }
  141.  
  142. void ServerGameLogic::Disconnect()
  143. {
  144.     r3dOutToLog("Disconnect server\n");
  145.     g_net.Deinitialize();
  146.  
  147.     return;
  148. }
  149.  
  150. void ServerGameLogic::OnGameStart()
  151. {
  152.     /*
  153.     if(1)
  154.     {
  155.         r3dOutToLog("Main World objects\n"); CLOG_INDENT;
  156.         for(GameObject* obj=GameWorld().GetFirstObject(); obj; obj=GameWorld().GetNextObject(obj))
  157.         {
  158.             if(obj->isActive()) r3dOutToLog("obj: %s %s\n", obj->Class->Name.c_str(), obj->Name.c_str());
  159.         }
  160.     }
  161.  
  162.     if(1)
  163.     {
  164.         extern ObjectManager ServerDummyWorld;
  165.         r3dOutToLog("Temporary World objects\n"); CLOG_INDENT;
  166.         for(GameObject* obj=ServerDummyWorld.GetFirstObject(); obj; obj=ServerDummyWorld.GetNextObject(obj))
  167.         {
  168.             if(obj->isActive()) r3dOutToLog("obj: %s %s\n", obj->Class->Name.c_str(), obj->Name.c_str());
  169.         }
  170.     }*/
  171.  
  172.  
  173.     // record last net id
  174.     net_mapLoaded_LastNetID = gServerLogic.net_lastFreeId;
  175.     r3dOutToLog("net_mapLoaded_LastNetID: %d\n", net_mapLoaded_LastNetID);
  176.    
  177.     // start getting server notes
  178.     CJobGetServerNotes* job = new CJobGetServerNotes();
  179.     job->GameServerId = ginfo_.gameServerId;
  180.     g_AsyncApiMgr->AddJob(job);
  181. }
  182.  
  183. void ServerGameLogic::CheckClientsSecurity()
  184. {
  185.   const float PEER_CHECK_DELAY = 0.2f;  // do checks every N seconds
  186.   const float IDLE_PEERS_DELAY = 5.0f;  // peer have this N seconds to validate itself
  187.   const float SECREP1_DELAY    = PKT_C2S_SecurityRep_s::REPORT_PERIOD*4; // x4 time of client reporting time (15sec) to receive security report
  188.  
  189.   static float nextCheck = -1;
  190.   const float curTime = r3dGetTime();
  191.   if(curTime < nextCheck)
  192.     return;
  193.   nextCheck = curTime + PEER_CHECK_DELAY;
  194.  
  195.   for(int peerId=0; peerId<MAX_PEERS_COUNT; peerId++)
  196.   {
  197.     const peerInfo_s& peer = peers_[peerId];
  198.     if(peer.status_ == PEER_FREE)
  199.       continue;
  200.      
  201.     // check againts not validated peers
  202.     if(peer.status_ == PEER_CONNECTED)
  203.     {
  204.       if(curTime < peer.startTime + IDLE_PEERS_DELAY)
  205.         continue;
  206.      
  207.       DisconnectPeer(peerId, false, "no validation, last:%f/%d", peer.lastPacketTime, peer.lastPacketId);
  208.       continue;
  209.     }
  210.    
  211.     // check for receiveing security report
  212.     if(peer.player != NULL)
  213.     {
  214.       if(curTime > peer.secRepRecvTime + SECREP1_DELAY) {
  215.         DisconnectPeer(peerId, false, "no SecRep, last:%f/%d", peer.lastPacketTime, peer.lastPacketId);
  216.         continue;
  217.       }
  218.     }
  219.   }
  220.  
  221.   return;
  222. }
  223.  
  224. void ServerGameLogic::ApiPlayerUpdateChar(obj_ServerPlayer* plr, bool disconnectAfter)
  225. {
  226.     // force current GameFlags update
  227.     plr->UpdateGameWorldFlags();
  228.  
  229.     CJobUpdateChar* job = new CJobUpdateChar(plr);
  230.     job->CharData   = *plr->loadout_;
  231.     job->OldData    = plr->savedLoadout_;
  232.     job->Disconnect = disconnectAfter;
  233.     job->GameDollars = plr->profile_.ProfileData.GameDollars;
  234.     // add character play time to update data
  235.     job->CharData.Stats.TimePlayed += (int)(r3dGetTime() - plr->startPlayTime_);
  236.     g_AsyncApiMgr->AddJob(job);
  237.  
  238.     // replace character saved loadout. if update will fail, we'll disconnect player and keep everything at sync
  239.     plr->savedLoadout_ = job->CharData;
  240. }
  241.  
  242. void ServerGameLogic::ApiPlayerLeftGame(const obj_ServerPlayer* plr)
  243. {
  244.     CJobUserLeftGame* job = new CJobUserLeftGame(plr);
  245.     job->GameMapId    = ginfo_.mapId;
  246.     job->GameServerId = ginfo_.gameServerId;
  247.     job->TimePlayed   = (int)(r3dGetTime() - plr->startPlayTime_);
  248.     g_AsyncApiMgr->AddJob(job);
  249. }
  250.  
  251. void ServerGameLogic::LogInfo(DWORD peerId, const char* msg, const char* fmt, ...)
  252. {
  253.     char buf[4096];
  254.     va_list ap;
  255.     va_start(ap, fmt);
  256.     StringCbVPrintfA(buf, sizeof(buf), fmt, ap);
  257.     va_end(ap);
  258.    
  259.     LogCheat(peerId, 0, false, msg, buf);
  260. }
  261.  
  262. void ServerGameLogic::LogCheat(DWORD peerId, int LogID, int disconnect, const char* msg, const char* fmt, ...)
  263. {
  264.     char buf[4096];
  265.     va_list ap;
  266.     va_start(ap, fmt);
  267.     StringCbVPrintfA(buf, sizeof(buf), fmt, ap);
  268.     va_end(ap);
  269.  
  270.     const peerInfo_s& peer = GetPeer(peerId);
  271.     DWORD IP = net_->GetPeerIp(peerId);
  272.  
  273.     extern int cfg_uploadLogs;
  274.     if(/*cfg_uploadLogs ||*/ (LogID > 0)) // always upload cheats
  275.     {
  276.         CJobAddLogInfo* job = new CJobAddLogInfo();
  277.         job->CheatID    = LogID;
  278.         job->CustomerID = peer.CustomerID;
  279.         job->CharID     = peer.CharID;
  280.         job->IP         = IP;
  281.         job->GameServerId = ginfo_.gameServerId;
  282.         r3dscpy(job->Gamertag, peer.temp_profile.ProfileData.ArmorySlots[0].Gamertag);
  283.         r3dscpy(job->Msg, msg);
  284.         r3dscpy(job->Data, buf);
  285.         g_AsyncApiMgr->AddJob(job);
  286.     }
  287.    
  288.     const char* screenname = "<NOT_CONNECTED>";
  289.     if(peer.status_ == PEER_PLAYING)
  290.         screenname = peer.temp_profile.ProfileData.ArmorySlots[0].Gamertag;
  291.  
  292.     r3dOutToLog("%s: peer%02d, r:%s %s, CID:%d [%s], ip:%s\n",
  293.         LogID > 0 ? "!!! cheat" : "LogInfo",
  294.         peerId,
  295.         msg, buf,
  296.         peer.CustomerID, screenname,
  297.         inet_ntoa(*(in_addr*)&IP));
  298.  
  299.     if(disconnect && peer.player && !peer.player->profile_.ProfileData.isDevAccount)
  300.     {
  301.         // tell client he's cheating.
  302.         // ptumik: no need to make it easier to hack
  303.         //PKT_S2C_CheatWarning_s n2;
  304.         //n2.cheatId = (BYTE)cheatId;
  305.         //p2pSendRawToPeer(peerId, NULL, &n2, sizeof(n2));
  306.  
  307.         net_->DisconnectPeer(peerId);
  308.         // fire up disconnect event manually, enet might skip if if other peer disconnect as well
  309.         OnNetPeerDisconnected(peerId);
  310.     }
  311.  
  312.     return;
  313. }
  314.  
  315. void ServerGameLogic::DisconnectPeer(DWORD peerId, bool cheat, const char* fmt, ...)
  316. {
  317.   char buf[1024];
  318.   va_list ap;
  319.   va_start(ap, fmt);
  320.   StringCbVPrintfA(buf, sizeof(buf), fmt, ap);
  321.   va_end(ap);
  322.  
  323.   LogCheat(peerId, cheat ? 99 : 0, false, "DisconnectPeer", buf);
  324.  
  325.   net_->DisconnectPeer(peerId);
  326.  
  327.   // fire up disconnect event manually, enet might skip if if other peer disconnect as well
  328.   OnNetPeerDisconnected(peerId);
  329. }
  330.  
  331. void ServerGameLogic::OnNetPeerConnected(DWORD peerId)
  332. {
  333.     // too many connections, do not allow more connects
  334.     if(peerId >= MAX_PEERS_COUNT)
  335.     {
  336.         r3dOutToLog("!!! peer%02d over MAX_PEERS_COUNT connected\n", peerId);
  337.         net_->DisconnectPeer(peerId);
  338.         return;
  339.     }
  340.  
  341.     if(gameFinished_)
  342.     {
  343.         r3dOutToLog("peer connected while game is finished\n");
  344.         return;
  345.     }
  346.        
  347.     r3d_assert(maxPlayers_ > 0);
  348.  
  349.     //r3dOutToLog("peer%02d connected\n", peerId); CLOG_INDENT;
  350.  
  351.     peerInfo_s& peer = GetPeer(peerId);
  352.     peer.SetStatus(PEER_CONNECTED);
  353.  
  354.     curPeersConnected++;
  355.     return;
  356. }
  357.  
  358. void ServerGameLogic::OnNetPeerDisconnected(DWORD peerId)
  359. {
  360.     // too many connections, do not do anything
  361.     if(peerId >= MAX_PEERS_COUNT)
  362.         return;
  363.  
  364.     //r3dOutToLog("peer%02d disconnected\n", peerId); CLOG_INDENT;
  365.  
  366.     peerInfo_s& peer = GetPeer(peerId);
  367.  
  368.     // debug validation
  369.     switch(peer.status_)
  370.     {
  371.     default:
  372.         r3dError("!!! Invalid status %d in disconnect !!!", peer.status_);
  373.         break;
  374.     case PEER_FREE:
  375.         break;
  376.  
  377.     case PEER_CONNECTED:
  378.     case PEER_VALIDATED1:
  379.         r3d_assert(peer.player == NULL);
  380.         r3d_assert(peer.playerIdx == -1);
  381.         break;
  382.  
  383.     case PEER_LOADING:
  384.         r3d_assert(peer.playerIdx != -1);
  385.         r3d_assert(plrToPeer_[peer.playerIdx] != NULL);
  386.         r3d_assert(peer.player == NULL);
  387.        
  388.         plrToPeer_[peer.playerIdx] = NULL;
  389.         break;
  390.  
  391.     case PEER_PLAYING:
  392.         r3d_assert(peer.playerIdx != -1);
  393.         r3d_assert(plrToPeer_[peer.playerIdx] != NULL);
  394.         r3d_assert(plrToPeer_[peer.playerIdx] == &peer);
  395.         if(peer.player)
  396.         {
  397.             gMasterServerLogic.RemovePlayer(peer.CustomerID);
  398.  
  399.             if(peer.player->loadout_->Alive && !peer.player->wasDisconnected_)
  400.             {
  401.                 r3dOutToLog("peer%02d player %s is updating his data\n", peerId, peer.player->userName);
  402.                 ApiPlayerUpdateChar(peer.player);
  403.             }
  404.  
  405.             ApiPlayerLeftGame(peer.player);
  406.        
  407.             // report to users
  408.             {
  409.                 PKT_S2C_PlayerNameLeft_s n;
  410.                 n.peerId = (BYTE)peerId;
  411.  
  412.                 // send to all, regardless visibility
  413.                 for(int i=0; i<MAX_PEERS_COUNT; i++) {
  414.                     if(peers_[i].status_ >= PEER_PLAYING && peers_[i].player && i != peerId) {
  415.                         net_->SendToPeer(&n, sizeof(n), i, true);
  416.                     }
  417.                 }
  418.             }
  419.  
  420.             DeletePlayer(peer.playerIdx, peer.player);
  421.         }
  422.  
  423.         plrToPeer_[peer.playerIdx] = NULL;
  424.         break;
  425.     }
  426.  
  427.     if(peer.status_ != PEER_FREE)
  428.     {
  429.         // OnNetPeerDisconnected can fire multiple times, because of forced disconnect
  430.         curPeersConnected--;
  431.     }
  432.  
  433.     // clear peer status
  434.     peer.Clear();
  435.  
  436.     return;
  437. }
  438.  
  439. void ServerGameLogic::OnNetData(DWORD peerId, const r3dNetPacketHeader* packetData, int packetSize)
  440. {
  441.     // too many connections, do not do anything
  442.     if(peerId >= MAX_PEERS_COUNT)
  443.         return;
  444.  
  445.     // we can receive late packets from logically disconnected peer.
  446.     peerInfo_s& peer = GetPeer(peerId);
  447.     if(peer.status_ == PEER_FREE)
  448.         return;
  449.        
  450.     if(packetSize < sizeof(DefaultPacket))
  451.     {
  452.         DisconnectPeer(peerId, true, "small packetSize %d", packetSize);
  453.         return;
  454.     }
  455.     const DefaultPacket* evt = static_cast<const DefaultPacket*>(packetData);
  456.  
  457.     // store last packet data for debug
  458.     peer.lastPacketTime = r3dGetTime();
  459.     peer.lastPacketId   = evt->EventID;
  460.    
  461.     // store received sizes by packets
  462.     if(evt->EventID < 256)
  463.         netRecvPktSize[evt->EventID] += packetSize;
  464.  
  465.     if(gameFinished_)
  466.     {
  467.         r3dOutToLog("!!! peer%02d got packet %d while game is finished\n", peerId, evt->EventID);
  468.         return;
  469.     }
  470.  
  471.     GameObject* fromObj = GameWorld().GetNetworkObject(evt->FromID);
  472.  
  473.     // pass to world even processor first.
  474.     if(ProcessWorldEvent(fromObj, evt->EventID, peerId, packetData, packetSize)) {
  475.         return;
  476.     }
  477.  
  478.     if(evt->FromID && fromObj == NULL) {
  479.         DisconnectPeer(peerId, true, "bad event %d from not registered object %d", evt->EventID, evt->FromID);
  480.         return;
  481.     }
  482.  
  483.     if(fromObj)
  484.     {
  485.         if(IsServerPlayer(fromObj))
  486.         {
  487.             // make sure that sender of that packet is same player on server
  488.             if(((obj_ServerPlayer*)fromObj)->peerId_ != peerId)
  489.             {
  490.                 LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Network, false, "PlayerPeer",
  491.                     "peerID: %d, player: %d, packetID: %d",
  492.                     peerId, ((obj_ServerPlayer*)fromObj)->peerId_, evt->EventID);
  493.                 return;
  494.             }
  495.         }
  496.  
  497.         if(!fromObj->OnNetReceive(evt->EventID, packetData, packetSize))
  498.         {
  499.             LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Network, true, "BadObjectEvent",
  500.                 "%d for %s %d",
  501.                 evt->EventID, fromObj->Name.c_str(), fromObj->GetNetworkID());
  502.         }
  503.         return;
  504.     }
  505.  
  506.     LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Network, true, "BadWorldEvent",
  507.         "event %d from %d, obj:%s",
  508.         evt->EventID, evt->FromID, fromObj ? fromObj->Name.c_str() : "NONE");
  509.     return;
  510. }
  511.  
  512. void ServerGameLogic::DoKillPlayer(GameObject* sourceObj, obj_ServerPlayer* targetPlr, STORE_CATEGORIES weaponCat, bool forced_by_server, bool fromPlayerInAir, bool targetPlayerInAir )
  513. {
  514.     r3dOutToLog("%s killed by %s, forced: %d\n", targetPlr->userName, sourceObj->Name.c_str(), (int)forced_by_server);
  515.  
  516.     // sent kill packet
  517.     {            
  518.         PKT_S2C_KillPlayer_s n;
  519.         n.targetId = toP2pNetId(targetPlr->GetNetworkID());
  520.         n.killerWeaponCat = (BYTE)weaponCat;
  521.         n.forced_by_server = forced_by_server;
  522.         p2pBroadcastToActive(sourceObj, &n, sizeof(n));
  523.     }
  524.  
  525.     /*
  526.     if(!forced_by_server && sourceObj != targetPlr) // do not reward suicides
  527.     {
  528.         DropLootBox(targetPlr);
  529.     }*/
  530.  
  531.     targetPlr->DoDeath();
  532.  
  533.     if(forced_by_server)
  534.         return;
  535.    
  536.     targetPlr->loadout_->Stats.Deaths++;
  537.     //AddPlayerReward(targetPlr, RWD_Death, "RWD_Death");
  538.  
  539.     // do not count suicide kills
  540.     if(sourceObj == targetPlr)
  541.         return;
  542.  
  543.     if(IsServerPlayer(sourceObj))
  544.     {
  545.         obj_ServerPlayer * fromPlr = ((obj_ServerPlayer*)sourceObj);
  546.         fromPlr->loadout_->Stats.Kills++;
  547.  
  548.         const int fromPlrOldReputation = fromPlr->loadout_->Stats.Reputation;
  549.  
  550.         if (fromPlr->loadout_->Stats.Reputation >= ReputationPoints::Constable &&
  551.             targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Civilian)
  552.         {
  553.             if (fromPlr->loadout_->Stats.Reputation >= ReputationPoints::Paragon)
  554.             {
  555.                 fromPlr->loadout_->Stats.Reputation -= 125;
  556.             }
  557.             else if (fromPlr->loadout_->Stats.Reputation >= ReputationPoints::Vigilante)
  558.             {
  559.                 fromPlr->loadout_->Stats.Reputation -= 60;
  560.             }
  561.             else if (fromPlr->loadout_->Stats.Reputation >= ReputationPoints::Guardian)
  562.             {
  563.                 fromPlr->loadout_->Stats.Reputation -= 40;
  564.             }
  565.             else if (fromPlr->loadout_->Stats.Reputation >= ReputationPoints::Lawman)
  566.             {
  567.                 fromPlr->loadout_->Stats.Reputation -= 15;
  568.             }
  569.             else if (fromPlr->loadout_->Stats.Reputation >= ReputationPoints::Deputy)
  570.             {
  571.                 fromPlr->loadout_->Stats.Reputation -= 2;
  572.             }
  573.             else if (fromPlr->loadout_->Stats.Reputation >= ReputationPoints::Constable)
  574.             {
  575.                 fromPlr->loadout_->Stats.Reputation -= 1;
  576.             }
  577.         }
  578.         else
  579.         {
  580.             if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Paragon)
  581.             {
  582.                 fromPlr->loadout_->Stats.Reputation -= 20;
  583.             }
  584.             else if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Vigilante)
  585.             {
  586.                 fromPlr->loadout_->Stats.Reputation -= 15;
  587.             }
  588.             else if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Guardian)
  589.             {
  590.                 fromPlr->loadout_->Stats.Reputation -= 10;
  591.             }
  592.             else if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Lawman)
  593.             {
  594.                 fromPlr->loadout_->Stats.Reputation -= 4;
  595.             }
  596.             else if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Deputy)
  597.             {
  598.                 fromPlr->loadout_->Stats.Reputation -= 3;
  599.             }
  600.             else if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Constable)
  601.             {
  602.                 fromPlr->loadout_->Stats.Reputation -= 2;
  603.             }
  604.             else if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Civilian)
  605.             {
  606.                 fromPlr->loadout_->Stats.Reputation -= 1;
  607.             }
  608.             else if (targetPlr->loadout_->Stats.Reputation <= ReputationPoints::Villain)
  609.             {
  610.                 fromPlr->loadout_->Stats.Reputation +=
  611.                     fromPlr->loadout_->Stats.Reputation <= ReputationPoints::Thug ? -20 : 20;
  612.             }
  613.             else if (targetPlr->loadout_->Stats.Reputation <= ReputationPoints::Assassin)
  614.             {
  615.                 fromPlr->loadout_->Stats.Reputation +=
  616.                     fromPlr->loadout_->Stats.Reputation <= ReputationPoints::Thug ? -15 : 15;
  617.             }
  618.             else if (targetPlr->loadout_->Stats.Reputation <= ReputationPoints::Hitman)
  619.             {
  620.                 fromPlr->loadout_->Stats.Reputation +=
  621.                     fromPlr->loadout_->Stats.Reputation <= ReputationPoints::Thug ? -10 : 10;
  622.             }
  623.             else if (targetPlr->loadout_->Stats.Reputation <= ReputationPoints::Bandit)
  624.             {
  625.                 fromPlr->loadout_->Stats.Reputation +=
  626.                     fromPlr->loadout_->Stats.Reputation <= ReputationPoints::Thug ? -4 : 4;
  627.             }
  628.             else if (targetPlr->loadout_->Stats.Reputation <= -ReputationPoints::Outlaw)
  629.             {
  630.                 fromPlr->loadout_->Stats.Reputation +=
  631.                     fromPlr->loadout_->Stats.Reputation <= ReputationPoints::Thug ? -3 : 3;
  632.             }
  633.             else if (targetPlr->loadout_->Stats.Reputation <= ReputationPoints::Thug)
  634.             {
  635.                 fromPlr->loadout_->Stats.Reputation +=
  636.                     fromPlr->loadout_->Stats.Reputation <= ReputationPoints::Thug ? -2 : 2;
  637.             }
  638.         }
  639.  
  640.         if (targetPlr->loadout_->Stats.Reputation >= ReputationPoints::Civilian)
  641.         {
  642.             fromPlr->loadout_->Stats.KilledSurvivors++;
  643.         }
  644.         else
  645.         {
  646.             fromPlr->loadout_->Stats.KilledBandits++;
  647.         }
  648.  
  649.     }
  650.     else if(sourceObj->isObjType(OBJTYPE_GameplayItem) && sourceObj->Class->Name == "obj_ServerAutoTurret")
  651.     {
  652.         // award kill to owner of the turretx
  653.         obj_ServerPlayer* turretOwner = IsServerPlayer(GameWorld().GetObject(sourceObj->ownerID));
  654.         if(turretOwner)
  655.         {
  656.             turretOwner->loadout_->Stats.Kills++;
  657.         }
  658.     }
  659.  
  660.     return;
  661. }
  662.  
  663. // make sure this function is the same on client: AI_Player.cpp bool canDamageTarget(const GameObject* obj)
  664. bool ServerGameLogic::CanDamageThisObject(const GameObject* targetObj)
  665. {
  666.     if(IsServerPlayer(targetObj))
  667.     {
  668.         return true;
  669.     }
  670.     else if(targetObj->isObjType(OBJTYPE_Zombie))
  671.     {
  672.         return true;
  673.     }
  674.     else if(targetObj->Class->Name == "obj_LightMesh")
  675.     {
  676.         return true;
  677.     }
  678.     else if(targetObj->Class->Name == "obj_ServerBarricade")
  679.     {
  680.         return true;
  681.     }
  682.  
  683.     return false;
  684. }
  685.  
  686. void ServerGameLogic::ApplyDamage(GameObject* fromObj, GameObject* targetObj, const r3dPoint3D& dmgPos, float damage, bool force_damage, STORE_CATEGORIES damageSource)
  687. {
  688.     r3d_assert(fromObj);
  689.     r3d_assert(targetObj);
  690.    
  691.     if(IsServerPlayer(targetObj))
  692.     {
  693.         ApplyDamageToPlayer(fromObj, (obj_ServerPlayer*)targetObj, dmgPos, damage, -1, 0, force_damage, damageSource);
  694.         return;
  695.     }
  696.     else if(targetObj->isObjType(OBJTYPE_Zombie))
  697.     {
  698.         ApplyDamageToZombie(fromObj, targetObj, dmgPos, damage, -1, 0, force_damage, damageSource);
  699.         return;
  700.     }
  701.     else if(targetObj->Class->Name == "obj_LightMesh")
  702.     {
  703.         obj_ServerLightMesh* lightM = (obj_ServerLightMesh*)targetObj;
  704.         if(lightM->bLightOn)
  705.         {
  706.             lightM->bLightOn = false;
  707.             lightM->SyncLightStatus(-1);
  708.         }
  709.        
  710.         return;
  711.     }
  712.     else if(targetObj->Class->Name == "obj_ServerBarricade")
  713.     {
  714.         obj_ServerBarricade* shield = (obj_ServerBarricade*)targetObj;
  715.         shield->DoDamage(damage);
  716.         return;
  717.     }
  718.     else if(targetObj->Class->Name == "obj_ServerFarmBlock")
  719.     {
  720.         obj_ServerFarmBlock* shield = (obj_ServerFarmBlock*)targetObj;
  721.         shield->DoDamage(damage, damageSource);
  722.         return;
  723.     }
  724.  
  725.     r3dOutToLog("!!! error !!! was trying to damage object %s [%s]\n", targetObj->Name.c_str(), targetObj->Class->Name.c_str());
  726. }
  727.  
  728. // return true if hit was registered, false otherwise
  729. // state is grabbed from the dynamics.  [0] is from player in the air, [1] is target player in the air
  730. bool ServerGameLogic::ApplyDamageToPlayer(GameObject* fromObj, obj_ServerPlayer* targetPlr, const r3dPoint3D& dmgPos, float damage, int bodyBone, int bodyPart, bool force_damage, STORE_CATEGORIES damageSource, int airState )
  731. {
  732.     r3d_assert(fromObj);
  733.     r3d_assert(targetPlr);
  734.     return false;
  735.     if(targetPlr->loadout_->Alive == 0)
  736.         return false;
  737.        
  738.     // can't damage players in safe zones (postbox now act like that)
  739.     if((targetPlr->loadout_->GameFlags & wiCharDataFull::GAMEFLAG_NearPostBox) && !force_damage)
  740.         return false;
  741.  
  742.    
  743.  
  744.     // if we are NOT! on VIP Map then doesn't allow PVP
  745.     if(targetPlr->loadout_->GameMapId != GBGameInfo::MAPID_WZ_Colorado_Old)
  746.         return false;
  747.  
  748.     // SkillSystem
  749.    
  750.     damage = targetPlr->ApplyDamage(damage, fromObj, bodyPart, damageSource);
  751.     if(targetPlr->loadout_->Stats.skillid29 == 1){
  752.         damage *= 0.25f;
  753.     }
  754.  
  755.    
  756.  
  757.     // send damage packet, originating from the firing dude
  758.     PKT_S2C_Damage_s a;
  759.     a.dmgPos = dmgPos;
  760.     a.targetId = toP2pNetId(targetPlr->GetNetworkID());
  761.     a.damage   = R3D_MIN((BYTE)damage, (BYTE)255);
  762.     a.dmgType = damageSource;
  763.     a.bodyBone = bodyBone;
  764.     p2pBroadcastToActive(fromObj, &a, sizeof(a));
  765.  
  766.     // check if we killed player
  767.     if(targetPlr->loadout_->Health <= 0)
  768.     {
  769.         bool fromPlayerInAir = ((airState & 0x1) != 0);
  770.         bool targetPlayerInAir = ((airState & 0x2) != 0);
  771.  
  772.         DoKillPlayer(fromObj, targetPlr, damageSource, false, fromPlayerInAir, targetPlayerInAir);
  773.     }
  774.  
  775.     return true;
  776. }
  777.  
  778. bool ServerGameLogic::ApplyDamageToZombie(GameObject* fromObj, GameObject* targetZombie, const r3dPoint3D& dmgPos, float damage, int bodyBone, int bodyPart, bool force_damage, STORE_CATEGORIES damageSource)
  779. {
  780.     r3d_assert(fromObj);
  781.     r3d_assert(targetZombie && targetZombie->isObjType(OBJTYPE_Zombie));
  782.    
  783.     // relay to zombie logic
  784.     obj_Zombie* z = (obj_Zombie*)targetZombie;
  785.     bool killed = z->ApplyDamage(fromObj, damage, bodyPart, damageSource);
  786.     if(IsServerPlayer(fromObj) && killed)
  787.     {
  788.         IsServerPlayer(fromObj)->loadout_->Stats.KilledZombies++;
  789.     }
  790.    
  791.     return true;
  792. }
  793.  
  794. void ServerGameLogic::RelayPacket(DWORD peerId, const GameObject* from, const DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  795. {
  796.     if(!from)
  797.     {
  798.         r3dError("RelayPacket !from, event: %d", packetData->EventID);
  799.     }
  800.     const INetworkHelper* nh = const_cast<GameObject*>(from)->GetNetworkHelper();
  801.  
  802.     for(int i=0; i<MAX_PEERS_COUNT; i++)
  803.     {
  804.         if(peers_[i].status_ >= PEER_PLAYING && i != peerId)
  805.         {
  806.             if(!nh->GetVisibility(i))
  807.             {
  808.                 continue;
  809.             }
  810.  
  811.             net_->SendToPeer(packetData, packetSize, i, guaranteedAndOrdered);
  812.             netSentPktSize[packetData->EventID] += packetSize;
  813.         }
  814.     }
  815.  
  816.     return;
  817. }
  818.  
  819. void ServerGameLogic::p2pBroadcastToActive(const GameObject* from, DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  820. {
  821.     if(!from)
  822.     {
  823.         r3dError("p2pBroadcastToActive !from, event: %d", packetData->EventID);
  824.     }
  825.     const INetworkHelper* nh = const_cast<GameObject*>(from)->GetNetworkHelper();
  826.  
  827.     preparePacket(from, packetData);
  828.  
  829.     for(int i=0; i<MAX_PEERS_COUNT; i++)
  830.     {
  831.         if(peers_[i].status_ >= PEER_PLAYING)
  832.         {
  833.             if(!nh->GetVisibility(i))
  834.             {
  835.                 continue;
  836.             }
  837.             net_->SendToPeer(packetData, packetSize, i, guaranteedAndOrdered);
  838.             netSentPktSize[packetData->EventID] += packetSize;
  839.         }
  840.     }
  841.  
  842.     return;
  843. }
  844.  
  845. void ServerGameLogic::p2pBroadcastToAll(const GameObject* from, DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  846. {
  847.     preparePacket(from, packetData);
  848.  
  849.     for(int i=0; i<MAX_PEERS_COUNT; i++)
  850.     {
  851.         if(peers_[i].status_ >= PEER_VALIDATED1)
  852.         {
  853.             net_->SendToPeer(packetData, packetSize, i, guaranteedAndOrdered);
  854.             netSentPktSize[packetData->EventID] += packetSize;
  855.         }
  856.     }
  857.  
  858.     return;
  859. }
  860.  
  861. void ServerGameLogic::p2pSendToPeer(DWORD peerId, const GameObject* from, DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  862. {
  863.     if(!from)
  864.     {
  865.         r3dError("p2pSendToPeer !from, event: %d", packetData->EventID);
  866.     }
  867.  
  868.     const peerInfo_s& peer = GetPeer(peerId);
  869.     if(peer.status_ >= PEER_PLAYING)
  870.     {
  871.         const INetworkHelper* nh = const_cast<GameObject*>(from)->GetNetworkHelper();
  872.         if(!nh->GetVisibility(peerId))
  873.         {
  874.             return;
  875.         }
  876.  
  877.         preparePacket(from, packetData);
  878.         net_->SendToPeer(packetData, packetSize, peerId, guaranteedAndOrdered);
  879.         netSentPktSize[packetData->EventID] += packetSize;
  880.     }
  881. }
  882.  
  883. void ServerGameLogic::p2pSendRawToPeer(DWORD peerId, DefaultPacket* packetData, int packetSize, bool guaranteedAndOrdered)
  884. {
  885.     const peerInfo_s& peer = GetPeer(peerId);
  886.     r3d_assert(peer.status_ != PEER_FREE);
  887.  
  888.     preparePacket(NULL, packetData);
  889.     net_->SendToPeer(packetData, packetSize, peerId, guaranteedAndOrdered);
  890.     netSentPktSize[packetData->EventID] += packetSize;
  891. }
  892.  
  893. void ServerGameLogic::InformZombiesAboutSound(const obj_ServerPlayer* plr, const ServerWeapon* wpn)
  894. {
  895.     for(GameObject* obj = GameWorld().GetFirstObject(); obj; obj = GameWorld().GetNextObject(obj))
  896.     {
  897.         if(obj->isObjType(OBJTYPE_Zombie))
  898.             ((obj_Zombie*)obj)->SenseWeaponFire(plr, wpn);
  899.     }
  900. }
  901.  
  902. wiStatsTracking ServerGameLogic::GetRewardData(obj_ServerPlayer* plr, EPlayerRewardID rewardID)
  903. {
  904.     r3d_assert(g_GameRewards);
  905.     const CGameRewards::rwd_s& rwd = g_GameRewards->GetRewardData(rewardID);
  906.     if(!rwd.IsSet)
  907.     {
  908.         LogInfo(plr->peerId_, "GetReward", "%d not set", rewardID);
  909.         return wiStatsTracking();
  910.     }
  911.    
  912.     wiStatsTracking stat;
  913.     stat.RewardID = (int)rewardID;
  914.     stat.GP       = 0;
  915.    
  916.     if(plr->loadout_->Hardcore)
  917.     {
  918.         stat.GD = rwd.GD_HARD;
  919.         stat.XP = rwd.XP_HARD;
  920.     }
  921.     else
  922.     {
  923.         stat.GD = rwd.GD_SOFT;
  924.         stat.XP = rwd.XP_SOFT;
  925.     }
  926.    
  927.     return stat;
  928. }  
  929.    
  930. void ServerGameLogic::AddPlayerReward(obj_ServerPlayer* plr, EPlayerRewardID rewardID)
  931. {
  932.     wiStatsTracking stat = GetRewardData(plr, rewardID);
  933.     if(stat.RewardID == 0)
  934.         return;
  935.  
  936.     const CGameRewards::rwd_s& rwd = g_GameRewards->GetRewardData(rewardID);
  937.     AddDirectPlayerReward(plr, stat, rwd.Name.c_str());
  938. }
  939.  
  940. void ServerGameLogic::AddDirectPlayerReward(obj_ServerPlayer* plr, const wiStatsTracking& in_rwd, const char* rewardName)
  941. {
  942.     // add reward to player
  943.     wiStatsTracking rwd2 = plr->AddReward(in_rwd);
  944.     int xp = rwd2.XP;
  945.     int gp = rwd2.GP;
  946.     int gd = rwd2.GD;
  947.     if(xp == 0 && gp == 0 && gd == 0)
  948.         return;
  949.        
  950.     r3dOutToLog("reward: %s got %dxp %dgp %dgd RWD_%s\n", plr->userName, xp, gp, gd, rewardName ? rewardName : "");
  951.  
  952.     // send it to him
  953.     PKT_S2C_AddScore_s n;
  954.     n.ID = (WORD)in_rwd.RewardID;
  955.     n.XP = R3D_CLAMP(xp, -30000, 30000);
  956.     n.GD = (WORD)gd;
  957.     p2pSendToPeer(plr->peerId_, plr, &n, sizeof(n));
  958.  
  959.     return;
  960. }
  961.  
  962. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_ValidateConnectingPeer)
  963. {
  964.     // reply back with our version
  965.     PKT_C2S_ValidateConnectingPeer_s n1;
  966.     n1.protocolVersion = P2PNET_VERSION;
  967.     n1.sessionId       = 0;
  968.     p2pSendRawToPeer(peerId, &n1, sizeof(n1));
  969.  
  970.     if(n.protocolVersion != P2PNET_VERSION)
  971.     {
  972.         DisconnectPeer(peerId, false, "Version mismatch");
  973.         return;
  974.     }
  975.     extern __int64 cfg_sessionId;
  976.     if(n.sessionId != cfg_sessionId)
  977.     {
  978.         DisconnectPeer(peerId, true, "Wrong sessionId");
  979.         return;
  980.     }
  981.  
  982.     // switch to Validated state
  983.     peerInfo_s& peer = GetPeer(peerId);
  984.     peer.SetStatus(PEER_VALIDATED1);
  985.  
  986.     return;
  987. }
  988.  
  989. obj_ServerPlayer* ServerGameLogic::CreateNewPlayer(DWORD peerId, const r3dPoint3D& spawnPos, float spawnDir)
  990. {
  991.     peerInfo_s& peer = GetPeer(peerId);
  992.     const int playerIdx = peer.playerIdx;
  993.  
  994.     r3d_assert(playerIdx >= 0 && playerIdx < maxPlayers_);
  995.     r3d_assert(peer.startGameAns == PKT_S2C_StartGameAns_s::RES_Ok);
  996.    
  997.     // store game session id
  998.     peer.temp_profile.ProfileData.ArmorySlots[0].GameServerId = ginfo_.gameServerId;
  999.     peer.temp_profile.ProfileData.ArmorySlots[0].GameMapId    = ginfo_.mapId;
  1000.  
  1001.     // create player
  1002.     char name[128];
  1003.     //sprintf(name, "player%02d", playerIdx);
  1004.     sprintf(name, "%s", peer.temp_profile.ProfileData.ArmorySlots[0].Gamertag);
  1005.     obj_ServerPlayer* plr = (obj_ServerPlayer*)srv_CreateGameObject("obj_ServerPlayer", name, spawnPos);
  1006.    
  1007.     // add to peer-to-player table (need to do before player creation, because of network objects visibility check)
  1008.     r3d_assert(plrToPeer_[playerIdx] != NULL);
  1009.     r3d_assert(plrToPeer_[playerIdx]->player == NULL);
  1010.     plrToPeer_[playerIdx]->player = plr;
  1011.     // mark that we're active
  1012.     peer.player = plr;
  1013.  
  1014.     // fill player info
  1015.     plr->m_PlayerRotation = spawnDir;
  1016.     plr->peerId_      = peerId;
  1017.     plr->SetNetworkID(playerIdx + NETID_PLAYERS_START);
  1018.     plr->NetworkLocal = false;
  1019.     plr->SetProfile(peer.temp_profile);
  1020.     plr->OnCreate();
  1021.  
  1022.     // from this point we do expect security report packets
  1023.     peer.secRepRecvTime = r3dGetTime();
  1024.     peer.secRepGameTime = -1;
  1025.     peer.secRepRecvAccum = 0;
  1026.  
  1027.     r3d_assert(curPlayers_ < maxPlayers_);
  1028.     curPlayers_++;
  1029.    
  1030.     // report in masterserver
  1031.     gMasterServerLogic.AddPlayer(peer.CustomerID);
  1032.    
  1033.     // report joined player name to all users
  1034.     {
  1035.         PKT_S2C_PlayerNameJoined_s n;
  1036.         n.peerId = (BYTE)peerId;
  1037.         r3dscpy(n.gamertag, plr->userName);
  1038.         n.flags = 0;
  1039.         if(plr->profile_.ProfileData.AccountType == 0) // legend
  1040.             n.flags |= 1;
  1041.         if(plr->profile_.ProfileData.isDevAccount)
  1042.             n.flags |= 2;
  1043.         n.Reputation = plr->loadout_->Stats.Reputation;
  1044.  
  1045.         // send to all, regardless visibility, excluding us
  1046.         for(int i=0; i<MAX_PEERS_COUNT; i++) {
  1047.             if(peers_[i].status_ >= PEER_PLAYING && peers_[i].player && i != peerId) {
  1048.                 net_->SendToPeer(&n, sizeof(n), i, true);
  1049.             }
  1050.         }
  1051.     }
  1052.    
  1053.     // report list of current players to user, including us
  1054.     {
  1055.         for(int i=0; i<MAX_PEERS_COUNT; i++) {
  1056.             if(peers_[i].status_ >= PEER_PLAYING && peers_[i].player) {
  1057.                 PKT_S2C_PlayerNameJoined_s n;
  1058.                 n.peerId = i;
  1059.                 r3dscpy(n.gamertag, peers_[i].player->userName);
  1060.                 n.flags = 0;
  1061.                 if(peers_[i].player->profile_.ProfileData.AccountType == 0) // legend
  1062.                     n.flags |= 1;
  1063.                 if(peers_[i].player->profile_.ProfileData.isDevAccount)
  1064.                     n.flags |= 2;
  1065.                 n.Reputation = plr->loadout_->Stats.Reputation;
  1066.  
  1067.                 net_->SendToPeer(&n, sizeof(n), peerId, true);
  1068.             }
  1069.         }
  1070.     }
  1071.    
  1072.     return plr;
  1073. }
  1074.  
  1075. void ServerGameLogic::DeletePlayer(int playerIdx, obj_ServerPlayer* plr)
  1076. {
  1077.     r3d_assert(plr);
  1078.  
  1079.     r3d_assert(playerIdx == (plr->GetNetworkID() - NETID_PLAYERS_START));
  1080.     r3dOutToLog("DeletePlayer: %s, playerIdx: %d\n", plr->userName, playerIdx);
  1081.  
  1082.     ResetNetObjVisData(plr);
  1083.    
  1084.     // send player destroy
  1085.     {
  1086.         PKT_S2C_DestroyNetObject_s n;
  1087.         n.spawnID = gp2pnetid_t(plr->GetNetworkID());
  1088.         p2pBroadcastToActive(plr, &n, sizeof(n));
  1089.     }
  1090.  
  1091.     // mark for deletion
  1092.     plr->setActiveFlag(0);
  1093.     //plr->NetworkID = 0;
  1094.  
  1095.     r3d_assert(curPlayers_ > 0);
  1096.     curPlayers_--;
  1097.  
  1098.     return;
  1099. }
  1100.  
  1101. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_JoinGameReq)
  1102. {
  1103.     DWORD ip = net_->GetPeerIp(peerId);
  1104.     r3dOutToLog("peer%02d PKT_C2S_JoinGameReq: CID:%d, ip:%s\n",
  1105.         peerId, n.CustomerID, inet_ntoa(*(in_addr*)&ip));
  1106.     CLOG_INDENT;
  1107.  
  1108.     if(n.CustomerID == 0 || n.SessionID == 0 || n.CharID == 0)
  1109.     {
  1110.         gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "JoinGame",
  1111.             "%d %d %d", n.CustomerID, n.SessionID, n.CharID);
  1112.         return;
  1113.     }
  1114.    
  1115.     // GetFreePlayerSlot
  1116.     int playerIdx = -1;
  1117.     for(int i=0; i<maxPlayers_; i++)
  1118.     {
  1119.         if(plrToPeer_[i] == NULL)
  1120.         {
  1121.             playerIdx = i;
  1122.             break;
  1123.         }
  1124.     }
  1125.  
  1126.     if(playerIdx == -1)
  1127.     {
  1128.         PKT_S2C_JoinGameAns_s n;
  1129.         n.success   = 0;
  1130.         n.playerIdx = 0;
  1131.         p2pSendRawToPeer(peerId, &n, sizeof(n));
  1132.  
  1133.         DisconnectPeer(peerId, false, "game is full"); //@ investigate why it's happening
  1134.         return;
  1135.     }
  1136.  
  1137.     { // send answer to peer
  1138.         PKT_S2C_JoinGameAns_s n;
  1139.         n.success      = 1;
  1140.         n.playerIdx    = playerIdx;
  1141.         n.gameInfo     = ginfo_;
  1142.         n.gameTime     = GetUtcGameTime();
  1143.  
  1144.         p2pSendRawToPeer(peerId, &n, sizeof(n));
  1145.     }
  1146.    
  1147.     {  // send game parameters to peer
  1148.         PKT_S2C_SetGamePlayParams_s n;
  1149.         n.GPP_Data = GPP_Data;
  1150.         n.GPP_Seed = GPP_Seed;
  1151.         p2pSendRawToPeer(peerId, &n, sizeof(n));
  1152.     }
  1153.  
  1154.     peerInfo_s& peer = GetPeer(peerId);
  1155.     r3d_assert(peer.player == NULL);
  1156.     peer.SetStatus(PEER_LOADING);
  1157.     peer.playerIdx    = playerIdx;
  1158.     peer.CustomerID   = n.CustomerID;
  1159.     peer.SessionID    = n.SessionID;
  1160.     peer.CharID       = n.CharID;
  1161.  
  1162.     // add to players table
  1163.     r3d_assert(plrToPeer_[playerIdx] == NULL);
  1164.     plrToPeer_[playerIdx] = &peer;
  1165.    
  1166.     // start thread for profile loading
  1167.     g_AsyncApiMgr->AddJob(new CJobProcessUserJoin(peerId));
  1168.  
  1169.     return;
  1170. }
  1171.  
  1172. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_StartGameReq)
  1173. {
  1174.     peerInfo_s& peer = GetPeer(peerId);
  1175.     r3d_assert(peer.playerIdx != -1);
  1176.     r3d_assert(peer.player == NULL);
  1177.     r3d_assert(peer.status_ == PEER_LOADING);
  1178.    
  1179.     r3dOutToLog("peer%02d PKT_C2S_StartGameReq, startGameAns: %d, lastNetID: %d\n", peerId, peer.startGameAns, n.lastNetID); CLOG_INDENT;
  1180.    
  1181.     if(n.lastNetID != net_mapLoaded_LastNetID)
  1182.     {
  1183.         PKT_S2C_StartGameAns_s n2;
  1184.         n2.result = PKT_S2C_StartGameAns_s::RES_UNSYNC;
  1185.         p2pSendRawToPeer(peerId, &n2, sizeof(n2));
  1186.         DisconnectPeer(peerId, true, "netID doesn't match %d vs %d", n.lastNetID, net_mapLoaded_LastNetID);
  1187.         return;
  1188.     }
  1189.    
  1190.     // check for default values, just in case
  1191.     r3d_assert(0 == PKT_S2C_StartGameAns_s::RES_Unactive);
  1192.     r3d_assert(1 == PKT_S2C_StartGameAns_s::RES_Ok);
  1193.     switch(peer.startGameAns)
  1194.     {
  1195.         // we have profile, process
  1196.         case PKT_S2C_StartGameAns_s::RES_Ok:
  1197.             break;
  1198.            
  1199.         // no profile loaded yet
  1200.         case PKT_S2C_StartGameAns_s::RES_Unactive:
  1201.         {
  1202.             // we give 60sec to finish getting profile per user
  1203.             if(r3dGetTime() > (peer.startTime + 120.0f))
  1204.             {
  1205.                 PKT_S2C_StartGameAns_s n;
  1206.                 n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  1207.                 p2pSendRawToPeer(peerId, &n, sizeof(n));
  1208.                 DisconnectPeer(peerId, true, "timeout getting profile data");
  1209.             }
  1210.             else
  1211.             {
  1212.                 // still pending
  1213.                 PKT_S2C_StartGameAns_s n;
  1214.                 n.result = PKT_S2C_StartGameAns_s::RES_Pending;
  1215.                 p2pSendRawToPeer(peerId, &n, sizeof(n));
  1216.             }
  1217.             return;
  1218.         }
  1219.        
  1220.         default:
  1221.         {
  1222.             PKT_S2C_StartGameAns_s n;
  1223.             n.result = (BYTE)peer.startGameAns;
  1224.             p2pSendRawToPeer(peerId, &n, sizeof(n));
  1225.             DisconnectPeer(peerId, true, "StarGameReq: %d", peer.startGameAns);
  1226.             return;
  1227.         }
  1228.     }
  1229.    
  1230.     // we have player profile, put it in game
  1231.     r3d_assert(peer.startGameAns == PKT_S2C_StartGameAns_s::RES_Ok);
  1232.  
  1233.     // we must have only one profile with correct charid
  1234.     if(peer.temp_profile.ProfileData.NumSlots != 1 ||
  1235.        peer.temp_profile.ProfileData.ArmorySlots[0].LoadoutID != peer.CharID)
  1236.     {
  1237.         PKT_S2C_StartGameAns_s n;
  1238.         n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  1239.         p2pSendRawToPeer(peerId, &n, sizeof(n));
  1240.  
  1241.         DisconnectPeer(peerId, true, "CharID mismatch %d vs %d", peer.CharID, peer.temp_profile.ProfileData.ArmorySlots[0].LoadoutID);
  1242.         return;
  1243.     }
  1244.  
  1245.     // and it should be alive.
  1246.     wiCharDataFull& loadout = peer.temp_profile.ProfileData.ArmorySlots[0];
  1247.     if(loadout.Alive == 0)
  1248.     {
  1249.         PKT_S2C_StartGameAns_s n;
  1250.         n.result = PKT_S2C_StartGameAns_s::RES_Failed;
  1251.         p2pSendRawToPeer(peerId, &n, sizeof(n));
  1252.            
  1253.         DisconnectPeer(peerId, true, "CharID %d is DEAD", peer.CharID);
  1254.         return;
  1255.     }
  1256.  
  1257.     peer.SetStatus(PEER_PLAYING);
  1258.  
  1259.     // if by some fucking unknown method you appeared at 0,0,0 - pretend he was dead, so it'll spawn at point
  1260.     if(loadout.Alive == 1 && loadout.GameMapId != GBGameInfo::MAPID_ServerTest && loadout.GamePos.Length() < 10)
  1261.     {
  1262.         LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Data, false, "ZeroSpawn", "%f %f %f", loadout.GamePos.x, loadout.GamePos.y, loadout.GamePos.z);
  1263.         loadout.Alive = 2;
  1264.     }
  1265.  
  1266.     // get spawn position
  1267.     r3dPoint3D spawnPos;
  1268.     float      spawnDir;
  1269.     GetStartSpawnPosition(loadout, &spawnPos, &spawnDir);
  1270.    
  1271.     // adjust for positions that is under ground because of geometry change
  1272.     if(Terrain)
  1273.     {
  1274.         float y1 = Terrain->GetHeight(spawnPos);
  1275.         if(spawnPos.y <= y1)
  1276.             spawnPos.y = y1 + 0.1f;
  1277.     }
  1278.  
  1279.     // create that player
  1280.     CreateNewPlayer(peerId, spawnPos, spawnDir);
  1281.  
  1282.     // send current weapon info to player
  1283.     SendWeaponsInfoToPlayer(peerId);
  1284.  
  1285.     // send answer to start game
  1286.     {
  1287.         PKT_S2C_StartGameAns_s n;
  1288.         n.result = PKT_S2C_StartGameAns_s::RES_Ok;
  1289.         p2pSendRawToPeer(peerId, &n, sizeof(n));
  1290.     }
  1291.  
  1292.     return;
  1293. }
  1294.  
  1295. bool ServerGameLogic::CheckForPlayersAround(const r3dPoint3D& pos, float dist)
  1296. {
  1297.     float distSq = dist * dist;
  1298.     for(int i=0; i<ServerGameLogic::MAX_NUM_PLAYERS; i++)
  1299.     {
  1300.         const obj_ServerPlayer* plr = gServerLogic.GetPlayer(i);
  1301.         if(!plr) continue;
  1302.        
  1303.         if((plr->GetPosition() - pos).LengthSq() < distSq)
  1304.             return true;
  1305.     }
  1306.    
  1307.     return false;
  1308. }
  1309.  
  1310. void ServerGameLogic::GetStartSpawnPosition(const wiCharDataFull& loadout, r3dPoint3D* pos, float* dir)
  1311. {
  1312.     // if no map assigned yet, or new map, or newly created character (alive == 3)
  1313.     if(loadout.GameMapId == 0 || loadout.GameMapId != ginfo_.mapId || loadout.Alive == 3)
  1314.     {
  1315.         GetSpawnPositionNewPlayer(loadout.GamePos, pos, dir);
  1316.         // move spawn pos at radius
  1317.         pos->x += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  1318.         pos->z += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  1319.         //r3dOutToLog("new spawn at position %f %f %f\n", pos->x, pos->y, pos->z);
  1320.         return;
  1321.     }
  1322.    
  1323.     // alive at current map
  1324.     if(loadout.GameMapId && (loadout.GameMapId == ginfo_.mapId) && loadout.Alive == 1)
  1325.     {
  1326.         *pos = loadout.GamePos;
  1327.         *dir = loadout.GameDir;
  1328.         //r3dOutToLog("alive at position %f %f %f\n", pos->x, pos->y, pos->z);
  1329.         return;
  1330.     }
  1331.    
  1332.     // revived (alive == 2) - spawn to closest spawn point
  1333.     if(loadout.GameMapId && loadout.Alive == 2)
  1334.     {
  1335.         GetSpawnPositionAfterDeath(loadout.GamePos, pos, dir);
  1336.         // move spawn pos at radius
  1337.         pos->x += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  1338.         pos->z += u_GetRandom(-_glm_SpawnRadius, _glm_SpawnRadius);
  1339.         //r3dOutToLog("revived at position %f %f %f\n", pos->x, pos->y, pos->z);
  1340.         return;
  1341.     }
  1342.  
  1343.     r3dOutToLog("%d %d %d\n", loadout.GameMapId, loadout.Alive, ginfo_.mapId);
  1344.     r3d_assert(false && "GetStartSpawnPosition");
  1345. }
  1346.  
  1347. void ServerGameLogic::GetSpawnPositionNewPlayer(const r3dPoint3D& GamePos, r3dPoint3D* pos, float* dir)
  1348. {
  1349.     if(gCPMgr.numBaseControlPoints == 0)
  1350.     {
  1351.         r3dOutToLog("!!!!!!!!!!!! THERE IS NO BASE CONTROL POINTS !!!!!!!\n");
  1352.         *pos = r3dPoint3D(0, 0, 0);
  1353.         *dir = 0;
  1354.         return;
  1355.     }
  1356.  
  1357.     int idx1 = u_random(gCPMgr.numBaseControlPoints);
  1358.     r3d_assert(idx1 < gCPMgr.numBaseControlPoints);
  1359.     const BasePlayerSpawnPoint* spawn = gCPMgr.baseControlPoints[idx1];
  1360.     spawn->getSpawnPoint(*pos, *dir);
  1361.     return;
  1362. }
  1363.  
  1364. void ServerGameLogic::GetSpawnPositionAfterDeath(const r3dPoint3D& GamePos, r3dPoint3D* pos, float* dir)
  1365. {
  1366.     if(gCPMgr.numControlPoints_ == 0)
  1367.     {
  1368.         r3dOutToLog("!!!!!!!!!!!! THERE IS NO CONTROL POINT !!!!!!!\n");
  1369.         *pos = r3dPoint3D(0, 0, 0);
  1370.         *dir = 0;
  1371.         return;
  1372.     }
  1373.    
  1374.     // spawn to closest point
  1375.     float minDist = 99999999.0f;
  1376.     for(int i=0; i<gCPMgr.numControlPoints_; i++)
  1377.     {
  1378.         const BasePlayerSpawnPoint* spawn = gCPMgr.controlPoints_[i];
  1379.         for(int j=0; j<spawn->m_NumSpawnPoints; j++)
  1380.         {
  1381.             float dist = (GamePos - spawn->m_SpawnPoints[j].pos).LengthSq();
  1382.             if(dist < minDist)
  1383.             {
  1384.                 *pos    = spawn->m_SpawnPoints[j].pos;
  1385.                 *dir    = spawn->m_SpawnPoints[j].dir;
  1386.                 minDist = dist;
  1387.             }
  1388.            
  1389.         }
  1390.     }
  1391.  
  1392.     return;
  1393. }
  1394.  
  1395. r3dPoint3D ServerGameLogic::AdjustPositionToFloor(const r3dPoint3D& pos)
  1396. {
  1397.     // do this in a couple of steps. firstly try +0.25, +1, then +5, then +50, then absolute +1000
  1398.     PxRaycastHit hit;
  1399.     PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC);
  1400.  
  1401.     if(!g_pPhysicsWorld->raycastSingle(PxVec3(pos.x, pos.y+0.25f, pos.z), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  1402.         if(!g_pPhysicsWorld->raycastSingle(PxVec3(pos.x, pos.y+1.0f, pos.z), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  1403.             if(!g_pPhysicsWorld->raycastSingle(PxVec3(pos.x, pos.y+5.0f, pos.z), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  1404.                 if(!g_pPhysicsWorld->raycastSingle(PxVec3(pos.x, pos.y+50.0f, pos.z), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  1405.                     if(!g_pPhysicsWorld->raycastSingle(PxVec3(pos.x, 1000.0f, pos.z), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  1406.                     {
  1407.                         r3dOutToLog("!! there is no floor under %f %f %f\n", pos.x, pos.y, pos.z);
  1408.                         return pos;
  1409.                     }
  1410.    
  1411.     return r3dPoint3D(hit.impact.x, hit.impact.y + 0.001f, hit.impact.z);
  1412. }
  1413.  
  1414. //
  1415. // every server network object must call this function in their OnCreate() - TODO: think about better way to automatize that
  1416. //
  1417. void ServerGameLogic::NetRegisterObjectToPeers(GameObject* netObj)
  1418. {
  1419.     r3d_assert(netObj->GetNetworkID());
  1420.  
  1421.     // scan for all peers and see if they within distance of this object
  1422.     INetworkHelper* nh = netObj->GetNetworkHelper();
  1423.     for(int peerId=0; peerId<MAX_PEERS_COUNT; peerId++)
  1424.     {
  1425.         const peerInfo_s& peer = peers_[peerId];
  1426.         if(peer.player == NULL)
  1427.             continue;
  1428.            
  1429.         float dist = (peer.player->GetPosition() - netObj->GetPosition()).LengthSq();
  1430.         if(dist < nh->distToCreateSq)
  1431.         {
  1432. #ifdef _DEBUG          
  1433. r3dOutToLog("NETHELPER: %s: on create - entered visibility of network object %d %s\n", peer.player->userName, netObj->GetNetworkID(), netObj->Name.c_str());           
  1434. #endif
  1435.             r3d_assert(nh->PeerVisStatus[peerId] == 0);
  1436.             nh->PeerVisStatus[peerId] = 1;
  1437.  
  1438.             int packetSize = 0;
  1439.             DefaultPacket* packetData = nh->NetGetCreatePacket(&packetSize);
  1440.             if(packetData)
  1441.             {
  1442.                 preparePacket(netObj, packetData);
  1443.                 net_->SendToPeer(packetData, packetSize, peerId, true);
  1444.                 netSentPktSize[packetData->EventID] += packetSize;
  1445.             }
  1446.         }
  1447.     }
  1448.  
  1449. }
  1450.  
  1451. void ServerGameLogic::UpdateNetObjVisData(DWORD peerId, GameObject* netObj)
  1452. {
  1453.     r3d_assert(netObj->GetNetworkID());
  1454.     r3d_assert(!(netObj->ObjFlags & OBJFLAG_JustCreated)); // object must be fully created at this moment
  1455.    
  1456.     const peerInfo_s& peer = GetPeer(peerId);
  1457.     float dist = (peer.player->GetPosition() - netObj->GetPosition()).LengthSq();
  1458.  
  1459.     INetworkHelper* nh = netObj->GetNetworkHelper();
  1460.     if(nh->PeerVisStatus[peerId] == 0)
  1461.     {
  1462.         if(dist < nh->distToCreateSq)
  1463.         {
  1464. #ifdef _DEBUG          
  1465. r3dOutToLog("NETHELPER: %s: entered visibility of network object %d %s\n", peer.player->userName, netObj->GetNetworkID(), netObj->Name.c_str());           
  1466. #endif
  1467.             nh->PeerVisStatus[peerId] = 1;
  1468.  
  1469.             int packetSize = 0;
  1470.             DefaultPacket* packetData = nh->NetGetCreatePacket(&packetSize);
  1471.             if(packetData)
  1472.             {
  1473.                 preparePacket(netObj, packetData);
  1474.                 net_->SendToPeer(packetData, packetSize, peerId, true);
  1475.                 netSentPktSize[packetData->EventID] += packetSize;
  1476.             }
  1477.         }
  1478.     }
  1479.     else
  1480.     {
  1481.         // already visible
  1482.         if(dist > nh->distToDeleteSq)
  1483.         {
  1484. #ifdef _DEBUG          
  1485. r3dOutToLog("NETHELPER: %s: left visibility of network object %d %s\n", peer.player->userName, netObj->GetNetworkID(), netObj->Name.c_str());          
  1486. #endif
  1487.             PKT_S2C_DestroyNetObject_s n;
  1488.             n.spawnID = toP2pNetId(netObj->GetNetworkID());
  1489.            
  1490.             // send only to that peer!
  1491.             preparePacket(netObj, &n);
  1492.             net_->SendToPeer(&n, sizeof(n), peerId, true);
  1493.             netSentPktSize[n.EventID] += sizeof(n);
  1494.  
  1495.             nh->PeerVisStatus[peerId] = 0;
  1496.         }
  1497.     }
  1498. }
  1499.  
  1500. void ServerGameLogic::UpdateNetObjVisData(const obj_ServerPlayer* plr)
  1501. {
  1502.     DWORD peerId = plr->peerId_;
  1503.     r3d_assert(peers_[peerId].player == plr);
  1504.  
  1505.     // scan for all objects and create/destroy them based on distance
  1506.     for(GameObject* obj=GameWorld().GetFirstObject(); obj; obj=GameWorld().GetNextObject(obj))
  1507.     {
  1508.         if(obj->GetNetworkID() == 0)
  1509.             continue;
  1510.         if(obj->ObjFlags & OBJFLAG_JustCreated)
  1511.             continue;
  1512.         if(!obj->isActive())
  1513.             continue;
  1514.            
  1515.         UpdateNetObjVisData(peerId, obj);
  1516.     }
  1517. }
  1518.  
  1519. void ServerGameLogic::ResetNetObjVisData(const obj_ServerPlayer* plr)
  1520. {
  1521.     DWORD peerId       = plr->peerId_;
  1522.  
  1523.     // scan for all objects and reset their visibility of player
  1524.     for(GameObject* obj=GameWorld().GetFirstObject(); obj; obj=GameWorld().GetNextObject(obj))
  1525.     {
  1526.         if(obj->GetNetworkID() == 0)
  1527.             continue;
  1528.            
  1529.         INetworkHelper* nh = obj->GetNetworkHelper();
  1530.         nh->PeerVisStatus[peerId] = 0;
  1531.     }
  1532. }
  1533.  
  1534. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_Temp_Damage)
  1535. {
  1536.     obj_ServerPlayer* fromPlr = IsServerPlayer(fromObj);
  1537.     if(!fromPlr)
  1538.     {
  1539.         r3dOutToLog("PKT_C2S_Temp_Damage: fromPlr is NULL\n");
  1540.         return;
  1541.     }
  1542.    
  1543.     if(fromPlr->peerId_ != peerId)
  1544.     {
  1545.         // catch hackers here.
  1546.         LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Network, false, "TempDamagePeer",
  1547.             "peerID: %d, player: %d",
  1548.             peerId, fromPlr->peerId_);
  1549.         return;
  1550.     }
  1551.  
  1552.     GameObject* target = GameWorld().GetNetworkObject(n.targetId);
  1553.     if(!target)
  1554.     {
  1555.         r3dOutToLog("PKT_C2S_Temp_Damage: targetPlr is NULL\n");
  1556.         return;
  1557.     }
  1558.  
  1559.     /*if(n.wpnIdx <0 || n.wpnIdx >= NUM_WEAPONS_ON_PLAYER)
  1560.     {
  1561.         r3dOutToLog("PKT_C2S_Temp_Damage: wpnIdx is out of range\n");
  1562.         return;
  1563.     }
  1564.     if(fromPlr->m_WeaponArray[n.wpnIdx]==NULL)
  1565.     {
  1566.         r3dOutToLog("PKT_C2S_Temp_Damage: m_WeaponArray[n.wpnIdx] is NULL\n");
  1567.         return;
  1568.     }*/
  1569.  
  1570.     //const WeaponConfig* wc = fromPlr->m_WeaponArray[n.wpnIdx]->getConfig();
  1571.     const WeaponConfig* wc = g_pWeaponArmory->getWeaponConfig(101310);
  1572.  
  1573.     // check distance
  1574.     float dist = (n.explosion_pos-target->GetPosition()).Length();
  1575.     if(dist > wc->m_AmmoArea)
  1576.     {    
  1577.         r3dOutToLog("PKT_C2S_Temp_Damage: dist is more than AmmoArea\n");
  1578.         return;
  1579.     }
  1580.     if ( n.damagePercentage > 100 || n.damagePercentage < 0 ) {
  1581.        
  1582.         r3dOutToLog("PKT_C2S_Temp_Damage: Damagepercentage was %d, which is incorrect, potentially a hack, disgarded.\n", n.damagePercentage);
  1583.         return;
  1584.     }
  1585.  
  1586.     float damage = wc->m_AmmoDamage*(1.0f-(dist/wc->m_AmmoArea));
  1587.     damage *= n.damagePercentage / 100.0f; // damage through wall
  1588.  
  1589.     r3dOutToLog("temp_damage from %s to %s, damage=%.2f\n", fromObj->Name.c_str(), target->Name.c_str(), damage); CLOG_INDENT;
  1590.     ApplyDamage(fromObj, target, n.explosion_pos, damage, true, wc->category);
  1591. }
  1592.  
  1593. int ServerGameLogic::ProcessChatCommand(obj_ServerPlayer* plr, const char* cmd)
  1594. {
  1595.     r3dOutToLog("cmd: %s admin:%d\n", cmd, plr->profile_.ProfileData.isDevAccount);
  1596.     if(strncmp(cmd, "/tp", 3) == 0 && plr->profile_.ProfileData.isDevAccount)
  1597.         return Cmd_Teleport(plr, cmd);
  1598.  
  1599.     if(strncmp(cmd, "/gi", 3) == 0 && plr->profile_.ProfileData.isDevAccount)
  1600.         return Cmd_GiveItem(plr, cmd);
  1601.        
  1602.     if(strncmp(cmd, "/sv", 3) == 0 && plr->profile_.ProfileData.isDevAccount)
  1603.         return Cmd_SetVitals(plr, cmd);
  1604.  
  1605.     if(strncmp(cmd, "/dk", 3) == 0 && plr->profile_.ProfileData.isDevAccount)
  1606.         return Cmd_DevKit(plr, cmd);
  1607.  
  1608.     if(strncmp(cmd, "/gm", 3) == 0 && plr->profile_.ProfileData.isDevAccount)
  1609.         return Cmd_GodMode(plr, cmd);
  1610.    
  1611.     return 1;  
  1612. }
  1613.  
  1614. int ServerGameLogic::Cmd_Teleport(obj_ServerPlayer* plr, const char* cmd)
  1615. {
  1616.     char buf[128];
  1617.     int tpName = 0;
  1618.     float x, z;
  1619.    
  1620.     if(3 != sscanf(cmd, "%s %f %f", buf, &x, &z))
  1621.     {
  1622.         if(2 != sscanf(cmd, "%s %i", buf, &tpName))
  1623.             return 2;
  1624.     }
  1625.    
  1626.     if(tpName == 1){
  1627.         x = 7500;
  1628.         z = 4500;
  1629.     }else if(tpName == 2){
  1630.         x = 6500;
  1631.         z = 4650;
  1632.     }else if(tpName == 3){
  1633.         x = 2750;
  1634.         z = 2750;
  1635.     }else if(tpName == 4){
  1636.         x = 2650;
  1637.         z = 6200;
  1638.     }else if(tpName == 5){
  1639.         x = 2450;
  1640.         z = 5500;
  1641.     }else if(tpName == 6){
  1642.         x = 4000;
  1643.         z = 5750;
  1644.     }else if(tpName == 7){
  1645.         x = 5500;
  1646.         z = 6500;
  1647.     }else if(tpName == 8){
  1648.         x = 6500;
  1649.         z = 7000;
  1650.     }else if(tpName == -1){
  1651.         PKT_C2C_ChatMessage_s n2;
  1652.         n2.userFlag = 3;
  1653.         n2.msgChannel = 1;
  1654.         r3dscpy(n2.msg, "1 = Goblin Peak Settlement, 2 = Campos City, 3 = Ridgeway Airport");
  1655.         r3dscpy(n2.gamertag, "<system>");
  1656.         p2pSendToPeer(plr->peerId_, plr, &n2, sizeof(n2));
  1657.  
  1658.         r3dscpy(n2.msg, "4 = Massive Weatherstation, 5 = Frosty Pines, 6 = Norad Military");
  1659.         p2pSendToPeer(plr->peerId_, plr, &n2, sizeof(n2));
  1660.  
  1661.         r3dscpy(n2.msg, "7 = Blue Ridge settlement, 8 = Loco mountain");
  1662.         p2pSendToPeer(plr->peerId_, plr, &n2, sizeof(n2));
  1663.         return 0;
  1664.     }
  1665.  
  1666.     /*
  1667.     Goblin Peak Settlement - /tp 7500 4500
  1668.     Campos City - /tp 6500 4650
  1669.     Ridgeway Airport - /tp 2750 2750
  1670.     Massive Weatherstation - /tp 2650 6200
  1671.     Frosty Pines resort town - /tp 2450 5500
  1672.     Norad Military Base - /tp 4000 5750
  1673.     Blue Ridge settlement - /tp 5500 6500
  1674.     Loco mountain - /tp 6500 7000
  1675.     */
  1676.  
  1677.     // cast ray down and find where we should place mine. should be in front of character, facing away from him
  1678.     PxRaycastHit hit;
  1679.     PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC);
  1680.     if(!g_pPhysicsWorld->raycastSingle(PxVec3(x, 1000.0f, z), PxVec3(0, -1, 0), 2000.0f, PxSceneQueryFlag::eIMPACT, hit, filter))
  1681.     {
  1682.         r3dOutToLog("unable to teleport - no collision\n");
  1683.         return 2;
  1684.     }
  1685.    
  1686.     r3dPoint3D pos = AdjustPositionToFloor(r3dPoint3D(x, 0, z));
  1687.        
  1688.     PKT_S2C_MoveTeleport_s n;
  1689.     n.teleport_pos = pos;
  1690.     p2pBroadcastToActive(plr, &n, sizeof(n));
  1691.     plr->SetLatePacketsBarrier("teleport");
  1692.     plr->TeleportPlayer(pos);
  1693.     r3dOutToLog("%s teleported to %f, %f, %f\n", plr->userName, pos.x, pos.y, pos.z);
  1694.     return 0;
  1695. }
  1696.  
  1697. int ServerGameLogic::Cmd_GodMode(obj_ServerPlayer* plr, const char* cmd)
  1698. {
  1699.     //char buf[128];
  1700.    
  1701.     //if(2 != sscanf(cmd, "%s %d", buf, &itemid))
  1702.         //return 2;
  1703.  
  1704.     plr->loadout_->godModeStatus = !plr->loadout_->godModeStatus;
  1705.  
  1706.     PKT_C2C_ChatMessage_s n2;
  1707.     n2.userFlag = 3;
  1708.     n2.msgChannel = 1;
  1709.     r3dscpy(n2.msg, (plr->loadout_->godModeStatus) ? "GodMode activated" : "GodMode deactivated");
  1710.     r3dscpy(n2.gamertag, "<system>");
  1711.     p2pSendToPeer(plr->peerId_, plr, &n2, sizeof(n2));
  1712.    
  1713.     return 0;
  1714. }
  1715.  
  1716. int ServerGameLogic::Cmd_GiveItem(obj_ServerPlayer* plr, const char* cmd)
  1717. {
  1718.     char buf[128];
  1719.     int itemid;
  1720.    
  1721.     if(2 != sscanf(cmd, "%s %d", buf, &itemid))
  1722.         return 2;
  1723.        
  1724.     if(g_pWeaponArmory->getConfig(itemid) == NULL) {
  1725.         r3dOutToLog("Cmd_GiveItem: no item %d\n", itemid);
  1726.         return 3;
  1727.     }
  1728.  
  1729.     wiInventoryItem wi;
  1730.     wi.itemID   = itemid;
  1731.     wi.quantity = 1;   
  1732.     plr->BackpackAddItem(wi);
  1733.    
  1734.     return 0;
  1735. }
  1736.  
  1737. int ServerGameLogic::Cmd_DevKit(obj_ServerPlayer* plr, const char* cmd)
  1738. {
  1739.     wiInventoryItem wi;
  1740.     wi.itemID   = 400017;
  1741.     wi.quantity = 5;   
  1742.     plr->BackpackAddItem(wi);
  1743.    
  1744.     //wiInventoryItem wi;
  1745.     wi.itemID   = 20054;
  1746.     wi.quantity = 1;   
  1747.     plr->BackpackAddItem(wi);
  1748.    
  1749.     //wiInventoryItem wi;
  1750.     wi.itemID   = 20180;
  1751.     wi.quantity = 1;   
  1752.     plr->BackpackAddItem(wi);
  1753.    
  1754.     //wiInventoryItem wi;
  1755.     wi.itemID   = 20067;
  1756.     wi.quantity = 1;   
  1757.     plr->BackpackAddItem(wi);
  1758.    
  1759.     //wiInventoryItem wi;
  1760.     wi.itemID   = 400000;
  1761.     wi.quantity = 1;   
  1762.     plr->BackpackAddItem(wi);
  1763.    
  1764.     //wiInventoryItem wi;
  1765.     wi.itemID   = 400003;
  1766.     wi.quantity = 1;   
  1767.     plr->BackpackAddItem(wi);
  1768.    
  1769.     //wiInventoryItem wi;
  1770.     wi.itemID   = 400013;
  1771.     wi.quantity = 1;   
  1772.     plr->BackpackAddItem(wi);
  1773.    
  1774.     return 0;
  1775. }
  1776.  
  1777. int ServerGameLogic::Cmd_SetVitals(obj_ServerPlayer* plr, const char* cmd)
  1778. {
  1779.     char buf[128];
  1780.     int v1, v2, v3, v4;
  1781.    
  1782.     if(5 != sscanf(cmd, "%s %d %d %d %d", buf, &v1, &v2, &v3, &v4))
  1783.         return 2;
  1784.        
  1785.     plr->loadout_->Health = (float)v1;
  1786.     plr->loadout_->Hunger = (float)v2;
  1787.     plr->loadout_->Thirst = (float)v3;
  1788.     plr->loadout_->Toxic  = (float)v4;
  1789.     return 0;
  1790. }
  1791.  
  1792. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2C_ChatMessage)
  1793. {
  1794.     if(!IsNullTerminated(n.gamertag, sizeof(n.gamertag))) {
  1795.         DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #1");
  1796.         return;
  1797.     }
  1798.     if(!IsNullTerminated(n.msg, sizeof(n.msg))) {
  1799.         DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #1");
  1800.         return;
  1801.     }
  1802.     if(n.userFlag != 0) {
  1803.         DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #1 - flags");
  1804.         return;
  1805.     }
  1806.  
  1807.     // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  1808.     obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  1809.     if(!fromPlr) {
  1810.         return;
  1811.     }
  1812.  
  1813.     // overwrite gamertag in packet, as hacker can send any crap he wants and post messages as someone else
  1814.     {
  1815.         PKT_C2C_ChatMessage_s* n_non_const = const_cast<PKT_C2C_ChatMessage_s*>(&n);
  1816.         r3dscpy(n_non_const->gamertag, fromPlr->userName);
  1817.     }
  1818.  
  1819.     if(fromPlr->profile_.ProfileData.AccountType == 0)
  1820.     {
  1821.         *const_cast<BYTE*>(&n.userFlag) |= 1;
  1822.     }
  1823.     if(fromPlr->profile_.ProfileData.isDevAccount)
  1824.     {
  1825.         *const_cast<BYTE*>(&n.userFlag) |= 2;
  1826.     }
  1827.  
  1828.     const float curTime = r3dGetTime();
  1829.    
  1830.     if(n.msg[0] == '/')
  1831.     {
  1832.         int res = ProcessChatCommand(fromPlr, n.msg);
  1833.         if(res == 0)
  1834.         {
  1835.             PKT_C2C_ChatMessage_s n2;
  1836.             n2.userFlag = 3;
  1837.             n2.msgChannel = 1;
  1838.             r3dscpy(n2.msg, "command executed");
  1839.             r3dscpy(n2.gamertag, "<system>");
  1840.             p2pSendToPeer(peerId, fromPlr, &n2, sizeof(n2));
  1841.         }
  1842.         else if(res == 2)
  1843.         {
  1844.             PKT_C2C_ChatMessage_s n2;
  1845.             n2.userFlag = 3;
  1846.             n2.msgChannel = 1;
  1847.             r3dscpy(n2.msg, "invalid params");
  1848.             r3dscpy(n2.gamertag, "<system>");
  1849.             p2pSendToPeer(peerId, fromPlr, &n2, sizeof(n2));
  1850.         }
  1851.         else
  1852.         {
  1853.             PKT_C2C_ChatMessage_s n2;
  1854.             n2.userFlag = 3;
  1855.             n2.msgChannel = 1;
  1856.             sprintf(n2.msg, "no such command, %d", res);
  1857.             r3dscpy(n2.gamertag, "<system>");
  1858.             p2pSendToPeer(peerId, fromPlr, &n2, sizeof(n2));
  1859.         }
  1860.         return;
  1861.     }
  1862.    
  1863.     // check for chat spamming
  1864.     const float CHAT_DELAY_BETWEEN_MSG = 1.0f;  // expected delay between message
  1865.     const int   CHAT_NUMBER_TO_SPAM    = 4;     // number of messages below delay time to be considered spam
  1866.     float diff = curTime - fromPlr->lastChatTime_;
  1867.  
  1868.     if(diff > CHAT_DELAY_BETWEEN_MSG)
  1869.     {
  1870.         fromPlr->numChatMessages_ = 0;
  1871.         fromPlr->lastChatTime_    = curTime;
  1872.     }
  1873.     else
  1874.     {
  1875.         fromPlr->numChatMessages_++;
  1876.         if(fromPlr->numChatMessages_ >= CHAT_NUMBER_TO_SPAM)
  1877.         {
  1878.             DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #3 - spam");
  1879.             return;
  1880.         }
  1881.     }
  1882.    
  1883.     // note
  1884.     //   do not use p2p function here as they're visibility based now
  1885.  
  1886.     switch( n.msgChannel )
  1887.     {
  1888.         case 1: // global
  1889.         {
  1890.             for(int i=0; i<MAX_PEERS_COUNT; i++) {
  1891.                 if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  1892.                     net_->SendToPeer(&n, sizeof(n), i, true);
  1893.                 }
  1894.             }
  1895.         }
  1896.         break;
  1897.        
  1898.         case 0:  // proximity
  1899.             for(int i=0; i<MAX_PEERS_COUNT; i++) {
  1900.                 if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  1901.                     if((peers_[i].player->GetPosition() - fromPlr->GetPosition()).Length() < 200.0f)
  1902.                         net_->SendToPeer(&n, sizeof(n), i, true);
  1903.                 }
  1904.             }
  1905.             break;
  1906.  
  1907.         case 2: // clan
  1908.         {
  1909.             if(fromPlr->loadout_->ClanID != 0)
  1910.             {
  1911.                 for(int i=0; i<MAX_PEERS_COUNT; i++) {
  1912.                     if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  1913.                         if(fromPlr->loadout_->ClanID == peers_[i].player->loadout_->ClanID)
  1914.                             net_->SendToPeer(&n, sizeof(n), i, true);
  1915.                     }
  1916.                 }
  1917.             }
  1918.         }
  1919.         break;
  1920.  
  1921.         case 3: // group
  1922.         {
  1923.             if(0 != 0)
  1924.             {
  1925.                 for(int i=0; i<MAX_PEERS_COUNT; i++) {
  1926.                     if(peers_[i].status_ >= PEER_PLAYING && i != peerId && peers_[i].player) {
  1927.                         if(fromPlr->loadout_->ClanID == peers_[i].player->loadout_->ClanID)
  1928.                             net_->SendToPeer(&n, sizeof(n), i, true);
  1929.                     }
  1930.                 }
  1931.             }
  1932.         }
  1933.         break;
  1934.  
  1935.         default:
  1936.         {
  1937.             DisconnectPeer(peerId, true, "invalid PKT_C2C_ChatMessage #4 - wrong msgChannel");
  1938.             return;
  1939.         }
  1940.         break;
  1941.        
  1942.     }
  1943. }
  1944.  
  1945. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_DataUpdateReq)
  1946. {
  1947.     r3dOutToLog("got PKT_C2S_DataUpdateReq\n");
  1948.    
  1949.     // relay that event to master server.
  1950.     //gMasterServerLogic.RequestDataUpdate();
  1951. }
  1952.  
  1953. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_Admin_PlayerKick)
  1954. {
  1955.  
  1956.     peerInfo_s& peer = GetPeer(peerId);
  1957.  
  1958.     // check if received from legitimate admin account
  1959.     if(!peer.player || !peer.temp_profile.ProfileData.isDevAccount)
  1960.         return;
  1961.  
  1962.     for(int i=0; i<MAX_PEERS_COUNT; ++i)
  1963.     {
  1964.         peerInfo_s& pr = GetPeer(i);
  1965.         if(pr.status_ == PEER_PLAYING && pr.player)
  1966.         {
  1967.             if(pr.player->userName == n.pName) // found
  1968.             {
  1969.                 DisconnectPeer(i, false, "Kicked from the game by admin: %s", pr.player->userName);
  1970.                 return;
  1971.             }
  1972.         }
  1973.     }
  1974.  
  1975.     r3dOutToLog("%s not found %d", n.pName, n.netID);
  1976. }
  1977.  
  1978. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_Admin_GiveItem)
  1979. {
  1980.     peerInfo_s& peer = GetPeer(peerId);
  1981.  
  1982.     // check if received from legitimate admin account
  1983.     if(!peer.player || !peer.temp_profile.ProfileData.isDevAccount)
  1984.         return;
  1985.        
  1986.     if(g_pWeaponArmory->getConfig(n.ItemID) == NULL) {
  1987.         r3dOutToLog("PKT_C2S_Admin_GiveItem: no item %d\n", n.ItemID);
  1988.         return;
  1989.     }
  1990.  
  1991.     wiInventoryItem wi;
  1992.     wi.itemID   = n.ItemID;
  1993.     wi.quantity = 1;   
  1994.     peer.player->BackpackAddItem(wi);
  1995. }
  1996.  
  1997. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_SecurityRep)
  1998. {
  1999.     const float curTime = r3dGetTime();
  2000.     peerInfo_s& peer = GetPeer(peerId);
  2001.     if(peer.player==NULL) // cheat??
  2002.         return;
  2003.  
  2004.     if(peer.secRepGameTime < 0)
  2005.     {
  2006.         // first call.
  2007.         peer.secRepRecvTime = curTime;
  2008.         peer.secRepGameTime = n.gameTime;
  2009.         //r3dOutToLog("peer%02d, CustomerID:%d SecRep started\n");
  2010.         return;
  2011.     }
  2012.    
  2013.     float delta1 = n.gameTime - peer.secRepGameTime;
  2014.     float delta2 = curTime    - peer.secRepRecvTime;
  2015.  
  2016.     //@ ignore small values for now, until we resolve how that can happens without cheating.
  2017.     if(delta2 > ((float)PKT_C2S_SecurityRep_s::REPORT_PERIOD - 0.3f) && delta2 < PKT_C2S_SecurityRep_s::REPORT_PERIOD)
  2018.         delta2 = PKT_C2S_SecurityRep_s::REPORT_PERIOD;
  2019.  
  2020.     // account for late packets
  2021.     peer.secRepRecvAccum -= (delta2 - PKT_C2S_SecurityRep_s::REPORT_PERIOD);
  2022.  
  2023.     float k = delta1 - delta2;
  2024.     bool isLag = (k > 1.0f || k < -1.0f);
  2025.    
  2026.     /*
  2027.     r3dOutToLog("peer%02d, CID:%d SecRep: %f %f %f %f %s\n",
  2028.         peerId, peer.CustomerID, delta1, delta2, k, peer.secRepRecvAccum,
  2029.         isLag ? "net_lag" : "");*/
  2030.  
  2031.     // check for client timer
  2032.     if(fabs(delta1 - PKT_C2S_SecurityRep_s::REPORT_PERIOD) > 1.0f)
  2033.     {
  2034.         LogInfo(peerId, "client_lag?", "%f, %f, %f", delta1, delta2, peer.secRepRecvAccum);
  2035.     }
  2036.  
  2037.     // check if client was sending packets faster that he should, 20% limit
  2038.     if(peer.secRepRecvAccum > ((float)PKT_C2S_SecurityRep_s::REPORT_PERIOD * 0.2f))
  2039.     {
  2040.         LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_SpeedHack, true, "speedhack",
  2041.             "%f, %f, %f", delta1, delta2, peer.secRepRecvAccum
  2042.             );
  2043.  
  2044.         peer.secRepRecvAccum = 0;
  2045.     }
  2046.  
  2047.     // add check for d3d cheats
  2048.     if(n.detectedWireframeCheat)
  2049.     {
  2050.         LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Wireframe, false, "wireframe cheat");
  2051.     }
  2052.    
  2053.     if((GPP_Data.GetCrc32() ^ GPP_Seed) != n.GPP_Crc32)
  2054.     {
  2055.         LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_GPP, true, "GPP cheat");
  2056.     }
  2057.  
  2058.     peer.secRepRecvTime = curTime;
  2059.     peer.secRepGameTime = n.gameTime;
  2060.     return;
  2061. }
  2062.  
  2063. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_UseNetObject)
  2064. {
  2065.     //LogInfo(peerId, "PKT_C2S_UseNetObject", "%d", n.spawnID); CLOG_INDENT;
  2066.  
  2067.     // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  2068.     obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  2069.     if(!fromPlr) {
  2070.         return;
  2071.     }
  2072.  
  2073.     if(fromPlr->loadout_->Alive == 0) {
  2074.         // he might be dead on server, but still didn't know that on client
  2075.         return;
  2076.     }
  2077.        
  2078.     GameObject* base = GameWorld().GetNetworkObject(n.spawnID);
  2079.     if(!base) {
  2080.         // this is valid situation, as network item might be already despawned
  2081.         return;
  2082.     }
  2083.  
  2084.     // multiple players can try to activate it
  2085.     if(!base->isActive())
  2086.         return;
  2087.  
  2088.     // validate range (without Y)
  2089.     {
  2090.         r3dPoint3D bpos = base->GetPosition(); bpos.y = 0.0f;
  2091.         r3dPoint3D ppos = fromPlr->GetPosition(); ppos.y = 0.0f;
  2092.         float dist = (bpos - ppos).Length();
  2093.         if(dist > 5.0f)
  2094.         {
  2095.             gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "UseNetObject",
  2096.                 "dist %f", dist);
  2097.             return;
  2098.         }
  2099.     }
  2100.  
  2101.     if(base->Class->Name == "obj_SpawnedItem")
  2102.     {
  2103.         obj_SpawnedItem* obj = (obj_SpawnedItem*)base;
  2104.         if(fromPlr->BackpackAddItem(obj->m_Item))
  2105.             obj->setActiveFlag(0);
  2106.     }
  2107.     else if(base->Class->Name == "obj_DroppedItem")
  2108.     {
  2109.         obj_DroppedItem* obj = (obj_DroppedItem*)base;
  2110.         if(fromPlr->BackpackAddItem(obj->m_Item))
  2111.             obj->setActiveFlag(0);
  2112.     }
  2113.     else if(base->Class->Name == "obj_Note")
  2114.     {
  2115.         obj_Note* obj = (obj_Note*)base;
  2116.         obj->NetSendNoteData(peerId);
  2117.     }
  2118.     else
  2119.     {
  2120.         LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, false, "UesNetObject",
  2121.             "obj %s", base->Class->Name.c_str());
  2122.     }
  2123.  
  2124.     return;
  2125. }
  2126.  
  2127. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_CreateNote)
  2128. {
  2129.     // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  2130.     obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  2131.     if(!fromPlr) {
  2132.         return;
  2133.     }
  2134.  
  2135.     if(!IsNullTerminated(n.TextFrom, sizeof(n.TextFrom)) || !IsNullTerminated(n.TextSubj, sizeof(n.TextSubj))) {
  2136.         gServerLogic.LogCheat(peerId, PKT_S2C_CheatWarning_s::CHEAT_Protocol, true, "PKT_C2S_CreateNote",
  2137.             "no null in text");
  2138.         return;
  2139.     }
  2140.    
  2141.     // relay logic to player
  2142.     fromPlr->UseItem_CreateNote(n);
  2143.     return;
  2144. }
  2145.  
  2146. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_ReportNote)
  2147. {
  2148.     // ADD LOGIC
  2149.     obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  2150.     if(!fromPlr) {
  2151.         return;
  2152.     }
  2153.     r3dOutToLog("note reported!\n");
  2154.  
  2155.     CJobReportNote* job = new CJobReportNote(fromPlr);
  2156.     job->NoteID = n.NoteID;
  2157.     job->GameServerId= gServerLogic.ginfo_.gameServerId;
  2158.     job->CharID = fromPlr->loadout_->LoadoutID;
  2159.     g_AsyncApiMgr->AddJob(job);
  2160.     return;
  2161. }
  2162.  
  2163. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_TEST_SpawnDummyReq)
  2164. {
  2165.     r3dOutToLog("!!!!!!! NOPE: dummies not implemented\n");
  2166.     r3d_assert(fromObj);
  2167.     r3d_assert(IsServerPlayer(fromObj));
  2168.  
  2169.     return;
  2170. }
  2171.  
  2172. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_DBG_LogMessage)
  2173. {
  2174.     // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  2175.     obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  2176.     if(!fromPlr) {
  2177.         return;
  2178.     }
  2179.  
  2180.     // log that packet with temp cheat code
  2181.     LogCheat(fromPlr->peerId_, 98, false, "clientlog",
  2182.         "%s",
  2183.         n.msg
  2184.         );
  2185.     return;
  2186. }
  2187.  
  2188. IMPL_PACKET_FUNC(ServerGameLogic, PKT_C2S_SendHelpCall)
  2189. {
  2190.  
  2191.     // get player from peer, not from fromObj - more secure, no need to check for peer faking (player peer != p2p peer)
  2192.     obj_ServerPlayer* fromPlr = GetPeer(peerId).player;
  2193.     if(!fromPlr) {
  2194.         return;
  2195.     }
  2196.  
  2197.     HelpCalls[peerId].pos.x = n.pos.x;
  2198.     HelpCalls[peerId].pos.y = n.pos.y;
  2199.  
  2200.     HelpCalls[peerId].DistressText = n.DistressText;
  2201.     HelpCalls[peerId].rewardText = n.rewardText;
  2202.  
  2203.     for(int i=0; i<MAX_PEERS_COUNT; ++i)
  2204.     {
  2205.         peerInfo_s& pr = GetPeer(i);
  2206.         if(pr.status_ == PEER_PLAYING && pr.player)
  2207.         {
  2208.             PKT_S2C_SendHelpCall_s y;
  2209.             y.pos.x = n.pos.x;
  2210.             y.pos.y = n.pos.y;
  2211.             y.FromID = peerId;
  2212.  
  2213.             y.DistressText = n.DistressText;
  2214.             y.rewardText = n.rewardText;
  2215.         }
  2216.     }
  2217.  
  2218.     //r3dOutToLog("%s - %s: %f, %f", n.DistressText, n.rewardText, n.pos.x, n.pos.y);
  2219.     return;
  2220. }
  2221.  
  2222. void ServerGameLogic::OnPKT_C2S_ScreenshotData(DWORD peerId, const int size, const char* data)
  2223. {
  2224.     char    fname[MAX_PATH];
  2225.  
  2226.     const peerInfo_s& peer = GetPeer(peerId);
  2227.     if(peer.player == NULL) {
  2228.         return;
  2229.     } else {
  2230.         sprintf(fname, "logss\\JPG_%d_%d_%d_%x.jpg", ginfo_.gameServerId, peer.player->profile_.CustomerID, peer.player->loadout_->LoadoutID, GetTickCount());
  2231.     }
  2232.  
  2233.     r3dOutToLog("peer%02d received screenshot, fname:%s", peerId, fname);
  2234.  
  2235.     FILE* f = fopen(fname, "wb");
  2236.     if(f == NULL) {
  2237.         LogInfo(peerId, "SaveScreenshot", "unable to save fname:%s", fname);
  2238.         return;
  2239.     }
  2240.     fwrite(data, 1, size, f);
  2241.     fclose(f);
  2242.  
  2243.     return;
  2244. }
  2245.  
  2246.  
  2247. int ServerGameLogic::ProcessWorldEvent(GameObject* fromObj, DWORD eventId, DWORD peerId, const void* packetData, int packetSize)
  2248. {
  2249.     // do version check and game join request
  2250.     peerInfo_s& peer = GetPeer(peerId);
  2251.  
  2252.     switch(peer.status_)
  2253.     {
  2254.         // check version in connected state
  2255.     case PEER_CONNECTED:
  2256.         switch(eventId)
  2257.         {
  2258.             DEFINE_PACKET_HANDLER(PKT_C2S_ValidateConnectingPeer);
  2259.         }
  2260.         DisconnectPeer(peerId, true, "bad packet ID %d in connected state", eventId);
  2261.         return TRUE;
  2262.  
  2263.         // process join request in validated state
  2264.     case PEER_VALIDATED1:
  2265.         switch(eventId)
  2266.         {
  2267.             DEFINE_PACKET_HANDLER(PKT_C2S_JoinGameReq);
  2268.         }
  2269.         DisconnectPeer(peerId, true, "bad packet ID %d in validated1 state", eventId);
  2270.         return TRUE;
  2271.  
  2272.     case PEER_LOADING:
  2273.         switch(eventId)
  2274.         {
  2275.             DEFINE_PACKET_HANDLER(PKT_C2S_StartGameReq);
  2276.         }
  2277.         DisconnectPeer(peerId, true, "bad packet ID %d in loading state", eventId);
  2278.         return TRUE;
  2279.     }
  2280.  
  2281.     r3d_assert(peer.status_ == PEER_PLAYING);
  2282.  
  2283.     // validation and relay client code
  2284.     switch(eventId)
  2285.     {
  2286.         DEFINE_PACKET_HANDLER(PKT_C2S_Temp_Damage);
  2287.         DEFINE_PACKET_HANDLER(PKT_C2C_ChatMessage);
  2288.         DEFINE_PACKET_HANDLER(PKT_C2S_DataUpdateReq);
  2289.  
  2290.         DEFINE_PACKET_HANDLER(PKT_C2S_SecurityRep);
  2291.         DEFINE_PACKET_HANDLER(PKT_C2S_Admin_PlayerKick);
  2292.         DEFINE_PACKET_HANDLER(PKT_C2S_Admin_GiveItem);
  2293.         DEFINE_PACKET_HANDLER(PKT_C2S_UseNetObject);
  2294.         DEFINE_PACKET_HANDLER(PKT_C2S_CreateNote);
  2295.         DEFINE_PACKET_HANDLER(PKT_C2S_ReportNote);
  2296.         DEFINE_PACKET_HANDLER(PKT_C2S_TEST_SpawnDummyReq);
  2297.  
  2298.         DEFINE_PACKET_HANDLER(PKT_C2S_SendHelpCall);
  2299.        
  2300.         DEFINE_PACKET_HANDLER(PKT_C2S_DBG_LogMessage);
  2301.        
  2302.         // special packet case with variable length
  2303.         case PKT_C2S_ScreenshotData:
  2304.         {
  2305.             const PKT_C2S_ScreenshotData_s& n = *(PKT_C2S_ScreenshotData_s*)packetData;
  2306.             if(packetSize < sizeof(n)) {
  2307.                 LogInfo(peerId, "PKT_C2S_ScreenshotData", "packetSize %d < %d", packetSize, sizeof(n));
  2308.                 return TRUE;
  2309.             }
  2310.             if(n.errorCode != 0)
  2311.             {
  2312.                 LogInfo(peerId, "PKT_C2S_ScreenshotData", "screenshot grab failed: %d", n.errorCode);
  2313.                 return TRUE;
  2314.             }
  2315.            
  2316.             if(packetSize != sizeof(n) + n.dataSize) {
  2317.                 LogInfo(peerId, "PKT_C2S_ScreenshotData", "dataSize %d != %d+%d", packetSize, sizeof(n), n.dataSize);
  2318.                 return TRUE;
  2319.             }
  2320.            
  2321.             OnPKT_C2S_ScreenshotData(peerId, n.dataSize, (char*)packetData + sizeof(n));
  2322.             return TRUE;
  2323.         }
  2324.     }
  2325.  
  2326.     return FALSE;
  2327. }
  2328.  
  2329. void ServerGameLogic::TrackWeaponUsage(uint32_t ItemID, int ShotsFired, int ShotsHits, int Kills)
  2330. {
  2331.     WeaponStats_s* ws = NULL;
  2332.     for(size_t i = 0, size = weaponStats_.size(); i < size; ++i)
  2333.     {
  2334.         if(weaponStats_[i].ItemID == ItemID)
  2335.         {
  2336.             ws = &weaponStats_[i];
  2337.             break;
  2338.         }
  2339.     }
  2340.    
  2341.     if(ws == NULL)
  2342.     {
  2343.         weaponStats_.push_back(WeaponStats_s());
  2344.         ws = &weaponStats_.back();
  2345.         ws->ItemID = ItemID;
  2346.     }
  2347.    
  2348.     r3d_assert(ws);
  2349.     ws->ShotsFired += ShotsFired;
  2350.     ws->ShotsHits  += ShotsHits;
  2351.     ws->Kills      += Kills;
  2352.     return;
  2353. }
  2354.  
  2355. void ServerGameLogic::Tick()
  2356. {
  2357.     r3d_assert(maxPlayers_ > 0);
  2358.     net_->Update();
  2359.    
  2360.     const float curTime = r3dGetTime();
  2361.  
  2362.     // shutdown notify logic
  2363.     if(gMasterServerLogic.shuttingDown_)
  2364.     {
  2365.       // send note every 1 sec
  2366.       static float lastSent = 999999;
  2367.       if(fabs(lastSent - gMasterServerLogic.shutdownLeft_) > 1.0f)
  2368.       {
  2369.         lastSent = gMasterServerLogic.shutdownLeft_;
  2370.         r3dOutToLog("sent shutdown note\n");
  2371.      
  2372.         PKT_S2C_ShutdownNote_s n;
  2373.         n.reason   = 0;
  2374.         n.timeLeft = gMasterServerLogic.shutdownLeft_;
  2375.         p2pBroadcastToAll(NULL, &n, sizeof(n), true);
  2376.       }
  2377.  
  2378.       // close game when shutdown
  2379.       if(gMasterServerLogic.shutdownLeft_ < 0)
  2380.         throw "shutting down....";
  2381.     }
  2382.  
  2383.     CheckClientsSecurity();
  2384.    
  2385.     g_AsyncApiMgr->Tick();
  2386.  
  2387.     if(gameFinished_)
  2388.         return;
  2389.  
  2390.     /*DISABLED, as it complicate things a bit.
  2391.     if(gMasterServerLogic.gotWeaponUpdate_)
  2392.     {
  2393.         gMasterServerLogic.gotWeaponUpdate_ = false;
  2394.  
  2395.         weaponDataUpdates_++;
  2396.         SendWeaponsInfoToPlayer(true, 0);
  2397.     }*/
  2398.  
  2399.     //@@@ kill all players
  2400.     if(GetAsyncKeyState(VK_F11) & 0x8000)
  2401.     {
  2402.         r3dOutToLog("trying to kill all players\n");
  2403.         for(int i=0; i<maxPlayers_; i++) {
  2404.             obj_ServerPlayer* plr = GetPlayer(i);
  2405.             if(!plr || plr->loadout_->Alive == 0)
  2406.                 continue;
  2407.  
  2408.             DoKillPlayer(plr, plr, storecat_INVALID, true);
  2409.         }
  2410.     }
  2411.  
  2412.     static float nextDebugLog_ = 0;
  2413.     if(curTime > nextDebugLog_)
  2414.     {
  2415.         char apiStatus[128];
  2416.         g_AsyncApiMgr->GetStatus(apiStatus);
  2417.        
  2418.         nextDebugLog_ = curTime + 60.0f;
  2419.         r3dOutToLog("time: %.0f, plrs:%d/%d, net_lastFreeId: %d, objects: %d, async:%s\n",
  2420.             r3dGetTime() - gameStartTime_,
  2421.             curPlayers_, ginfo_.maxPlayers,
  2422.             net_lastFreeId,
  2423.             GameWorld().GetNumObjects(),
  2424.             apiStatus);
  2425.     }
  2426.  
  2427.     return;
  2428. }
  2429.  
  2430. void ServerGameLogic::DumpPacketStatistics()
  2431. {
  2432.   __int64 totsent = 0;
  2433.   __int64 totrecv = 0;
  2434.  
  2435.   for(int i=0; i<R3D_ARRAYSIZE(netRecvPktSize); i++) {
  2436.     totsent += netSentPktSize[i];
  2437.     totrecv += netRecvPktSize[i];
  2438.   }
  2439.  
  2440.   r3dOutToLog("Packet Statistics: out:%I64d in:%I64d, k:%f\n", totsent, totrecv, (float)totsent/(float)totrecv);
  2441.   CLOG_INDENT;
  2442.  
  2443.   for(int i=0; i<R3D_ARRAYSIZE(netRecvPktSize); i++) {
  2444.     if(netSentPktSize[i] == 0 && netRecvPktSize[i] == 0)
  2445.       continue;
  2446.      
  2447.     r3dOutToLog("%3d: out:%10I64d in:%10I64d out%%:%.1f%%\n",
  2448.       i,
  2449.       netSentPktSize[i],
  2450.       netRecvPktSize[i],
  2451.       (float)netSentPktSize[i] * 100.0f / float(totsent));
  2452.   }
  2453.  
  2454. }
  2455.  
  2456. __int64 ServerGameLogic::GetUtcGameTime()
  2457. {
  2458.     // "world time start" offset, so gametime at 1st sep 2012 will be in 2018 range
  2459.     struct tm toff = {0};
  2460.     toff.tm_year   = 2011-1900;
  2461.     toff.tm_mon    = 6;
  2462.     toff.tm_mday   = 1;
  2463.     toff.tm_isdst  = -1; // A value less than zero to have the C run-time library code compute whether standard time or daylight saving time is in effect.
  2464.     __int64 secs0 = _mkgmtime64(&toff); // world start time
  2465.     __int64 secs1 = _time64(&secs1);    // current UTC time
  2466.  
  2467.     // reassemble time, with speedup factor
  2468.     return secs0 + (secs1 - secs0) * (__int64)GPP_Data.c_iGameTimeCompression;
  2469. }
  2470.  
  2471. void ServerGameLogic::SendWeaponsInfoToPlayer(DWORD peerId)
  2472. {
  2473.     //r3dOutToLog("sending weapon info to peer %d\n", peerId);
  2474.  
  2475.     const peerInfo_s& peer = GetPeer(peerId);
  2476.  
  2477.     g_pWeaponArmory->startItemSearch();
  2478.     while(g_pWeaponArmory->searchNextItem())
  2479.     {
  2480.         uint32_t itemID = g_pWeaponArmory->getCurrentSearchItemID();
  2481.         const WeaponConfig* weaponConfig = g_pWeaponArmory->getWeaponConfig(itemID);
  2482.         if(weaponConfig)
  2483.         {
  2484.             PKT_S2C_UpdateWeaponData_s n;
  2485.             n.itemId = weaponConfig->m_itemID;
  2486.             weaponConfig->copyParametersTo(n.wi);
  2487.             p2pSendRawToPeer(peerId, &n, sizeof(n), true);
  2488.         }
  2489.  
  2490.         /* no need to send gear configs for now - there is nothing interesting
  2491.         const GearConfig* gearConfig = g_pWeaponArmory->getGearConfig(itemID);
  2492.         if(gearConfig)
  2493.         {
  2494.             PKT_S2C_UpdateGearData_s n;
  2495.             n.itemId = gearConfig->m_itemID;
  2496.             gearConfig->copyParametersTo(n.gi);
  2497.             p2pSendRawToPeer(peerId, &n, sizeof(n), true);
  2498.         }
  2499.         */
  2500.     }
  2501.  
  2502.     return;
  2503. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement