RakNetStuff.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "RakNetStuff.h"
  11. #include "NetworkIDManager.h"
  12. #include "CDemo.h"
  13. #include "RakNetTime.h"
  14. #include "GetTime.h"
  15. #include "SocketLayer.h"
  16. using namespace RakNet;
  17. RakPeerInterface *rakPeer;
  18. NetworkIDManager *networkIDManager;
  19. ReplicaManager3Irrlicht *replicaManager3;
  20. NatPunchthroughClient *natPunchthroughClient;
  21. CloudClient *cloudClient;
  22. RakNet::FullyConnectedMesh2 *fullyConnectedMesh2;
  23. PlayerReplica *playerReplica;
  24. /*
  25. class DebugBoxSceneNode : public scene::ISceneNode
  26. {
  27. public:
  28. DebugBoxSceneNode(scene::ISceneNode* parent,
  29. scene::ISceneManager* mgr,
  30. s32 id = -1);
  31. virtual const core::aabbox3d<f32>& getBoundingBox() const;
  32. virtual void OnRegisterSceneNode();
  33. virtual void render();
  34. CDemo *demo;
  35. };
  36. DebugBoxSceneNode::DebugBoxSceneNode(
  37. scene::ISceneNode* parent,
  38. scene::ISceneManager* mgr,
  39. s32 id)
  40. : scene::ISceneNode(parent, mgr, id)
  41. {
  42. #ifdef _DEBUG
  43. setDebugName("DebugBoxSceneNode");
  44. #endif
  45. setAutomaticCulling(scene::EAC_OFF);
  46. }
  47. const core::aabbox3d<f32>& DebugBoxSceneNode::getBoundingBox() const
  48. {
  49. return demo->GetSyndeyBoundingBox();
  50. }
  51. void DebugBoxSceneNode::OnRegisterSceneNode()
  52. {
  53. if (IsVisible)
  54. demo->GetSceneManager()->registerNodeForRendering(this, scene::ESNRP_SOLID);
  55. }
  56. void DebugBoxSceneNode::render()
  57. {
  58. if (DebugDataVisible)
  59. {
  60. video::IVideoDriver* driver = SceneManager->getVideoDriver();
  61. driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
  62. video::SMaterial m;
  63. m.Lighting = false;
  64. demo->GetDevice()->getVideoDriver()->setMaterial(m);
  65. demo->GetDevice()->getVideoDriver()->draw3DBox(demo->GetSyndeyBoundingBox());
  66. }
  67. }
  68. */
  69. DataStructures::List<PlayerReplica*> PlayerReplica::playerList;
  70. // Take this many milliseconds to move the visible position to the real position
  71. static const float INTERP_TIME_MS=100.0f;
  72. void InstantiateRakNetClasses(void)
  73. {
  74. static const int MAX_PLAYERS=32;
  75. static const unsigned short TCP_PORT=0;
  76. static const RakNet::TimeMS UDP_SLEEP_TIMER=30;
  77. // Basis of all UDP communications
  78. rakPeer=RakNet::RakPeerInterface::GetInstance();
  79. // Using fixed port so we can use AdvertiseSystem and connect on the LAN if the server is not available.
  80. RakNet::SocketDescriptor sd(1234,0);
  81. sd.socketFamily=AF_INET; // Only IPV4 supports broadcast on 255.255.255.255
  82. while (IRNS2_Berkley::IsPortInUse(sd.port, sd.hostAddress, sd.socketFamily, SOCK_DGRAM)==true)
  83. sd.port++;
  84. // +1 is for the connection to the NAT punchthrough server
  85. RakNet::StartupResult sr = rakPeer->Startup(MAX_PLAYERS+1,&sd,1);
  86. RakAssert(sr==RakNet::RAKNET_STARTED);
  87. rakPeer->SetMaximumIncomingConnections(MAX_PLAYERS);
  88. // Fast disconnect for easier testing of host migration
  89. rakPeer->SetTimeoutTime(5000,UNASSIGNED_SYSTEM_ADDRESS);
  90. // ReplicaManager3 replies on NetworkIDManager. It assigns numbers to objects so they can be looked up over the network
  91. // It's a class in case you wanted to have multiple worlds, then you could have multiple instances of NetworkIDManager
  92. networkIDManager=new NetworkIDManager;
  93. // Automatically sends around new / deleted / changed game objects
  94. replicaManager3=new ReplicaManager3Irrlicht;
  95. replicaManager3->SetNetworkIDManager(networkIDManager);
  96. rakPeer->AttachPlugin(replicaManager3);
  97. // Automatically destroy connections, but don't create them so we have more control over when a system is considered ready to play
  98. replicaManager3->SetAutoManageConnections(false,true);
  99. // Create and register the network object that represents the player
  100. playerReplica = new PlayerReplica;
  101. replicaManager3->Reference(playerReplica);
  102. // Lets you connect through routers
  103. natPunchthroughClient=new NatPunchthroughClient;
  104. rakPeer->AttachPlugin(natPunchthroughClient);
  105. // Uploads game instance, basically client half of a directory server
  106. // Server code is in NATCompleteServer sample
  107. cloudClient=new CloudClient;
  108. rakPeer->AttachPlugin(cloudClient);
  109. fullyConnectedMesh2=new FullyConnectedMesh2;
  110. fullyConnectedMesh2->SetAutoparticipateConnections(false);
  111. fullyConnectedMesh2->SetConnectOnNewRemoteConnection(false, "");
  112. rakPeer->AttachPlugin(fullyConnectedMesh2);
  113. // Connect to the NAT punchthrough server
  114. ConnectionAttemptResult car = rakPeer->Connect(DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_IP, DEFAULT_NAT_PUNCHTHROUGH_FACILITATOR_PORT,0,0);
  115. RakAssert(car==CONNECTION_ATTEMPT_STARTED);
  116. // Advertise ourselves on the lAN if the NAT punchthrough server is not available
  117. //for (int i=0; i < 8; i++)
  118. // rakPeer->AdvertiseSystem("255.255.255.255", 1234+i, 0,0,0);
  119. }
  120. void DeinitializeRakNetClasses(void)
  121. {
  122. // Shutdown so the server knows we stopped
  123. rakPeer->Shutdown(100,0);
  124. RakNet::RakPeerInterface::DestroyInstance(rakPeer);
  125. delete networkIDManager;
  126. delete replicaManager3;
  127. delete natPunchthroughClient;
  128. delete cloudClient;
  129. delete fullyConnectedMesh2;
  130. // ReplicaManager3 deletes all referenced objects, including this one
  131. //playerReplica->PreDestruction(0);
  132. //delete playerReplica;
  133. }
  134. BaseIrrlichtReplica::BaseIrrlichtReplica()
  135. {
  136. }
  137. BaseIrrlichtReplica::~BaseIrrlichtReplica()
  138. {
  139. }
  140. void BaseIrrlichtReplica::SerializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *destinationConnection)
  141. {
  142. constructionBitstream->Write(position);
  143. }
  144. bool BaseIrrlichtReplica::DeserializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *sourceConnection)
  145. {
  146. constructionBitstream->Read(position);
  147. return true;
  148. }
  149. RM3SerializationResult BaseIrrlichtReplica::Serialize(RakNet::SerializeParameters *serializeParameters)
  150. {
  151. return RM3SR_BROADCAST_IDENTICALLY;
  152. }
  153. void BaseIrrlichtReplica::Deserialize(RakNet::DeserializeParameters *deserializeParameters)
  154. {
  155. }
  156. void BaseIrrlichtReplica::Update(RakNet::TimeMS curTime)
  157. {
  158. }
  159. PlayerReplica::PlayerReplica()
  160. {
  161. model=0;
  162. rotationDeltaPerMS=0.0f;
  163. isMoving=false;
  164. deathTimeout=0;
  165. lastUpdate=RakNet::GetTimeMS();
  166. playerList.Push(this,_FILE_AND_LINE_);
  167. }
  168. PlayerReplica::~PlayerReplica()
  169. {
  170. unsigned int index = playerList.GetIndexOf(this);
  171. if (index != (unsigned int) -1)
  172. playerList.RemoveAtIndexFast(index);
  173. }
  174. void PlayerReplica::WriteAllocationID(RakNet::Connection_RM3 *destinationConnection, RakNet::BitStream *allocationIdBitstream) const
  175. {
  176. allocationIdBitstream->Write(RakNet::RakString("PlayerReplica"));
  177. }
  178. void PlayerReplica::SerializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *destinationConnection)
  179. {
  180. BaseIrrlichtReplica::SerializeConstruction(constructionBitstream, destinationConnection);
  181. constructionBitstream->Write(rotationAroundYAxis);
  182. constructionBitstream->Write(playerName);
  183. constructionBitstream->Write(IsDead());
  184. }
  185. bool PlayerReplica::DeserializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *sourceConnection)
  186. {
  187. if (!BaseIrrlichtReplica::DeserializeConstruction(constructionBitstream, sourceConnection))
  188. return false;
  189. constructionBitstream->Read(rotationAroundYAxis);
  190. constructionBitstream->Read(playerName);
  191. constructionBitstream->Read(isDead);
  192. return true;
  193. }
  194. void PlayerReplica::PostDeserializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *destinationConnection)
  195. {
  196. // Object was remotely created and all data loaded. Now we can make the object visible
  197. scene::IAnimatedMesh* mesh = 0;
  198. scene::ISceneManager *sm = demo->GetSceneManager();
  199. mesh = sm->getMesh(IRRLICHT_MEDIA_PATH "sydney.md2");
  200. model = sm->addAnimatedMeshSceneNode(mesh, 0);
  201. // DebugBoxSceneNode * debugBox = new DebugBoxSceneNode(model,sm);
  202. // debugBox->demo=demo;
  203. // debugBox->setDebugDataVisible(true);
  204. model->setPosition(position);
  205. model->setRotation(core::vector3df(0, rotationAroundYAxis, 0));
  206. model->setScale(core::vector3df(2,2,2));
  207. model->setMD2Animation(scene::EMAT_STAND);
  208. curAnim=scene::EMAT_STAND;
  209. model->setMaterialTexture(0, demo->GetDevice()->getVideoDriver()->getTexture(IRRLICHT_MEDIA_PATH "sydney.bmp"));
  210. model->setMaterialFlag(video::EMF_LIGHTING, true);
  211. model->addShadowVolumeSceneNode();
  212. model->setAutomaticCulling ( scene::EAC_BOX );
  213. model->setVisible(true);
  214. model->setAnimationEndCallback(this);
  215. wchar_t playerNameWChar[1024];
  216. mbstowcs(playerNameWChar, playerName.C_String(), 1024);
  217. scene::IBillboardSceneNode *bb = sm->addBillboardTextSceneNode(0, playerNameWChar, model);
  218. bb->setSize(core::dimension2df(40,20));
  219. bb->setPosition(core::vector3df(0,model->getBoundingBox().MaxEdge.Y+bb->getBoundingBox().MaxEdge.Y-bb->getBoundingBox().MinEdge.Y+5.0,0));
  220. bb->setColor(video::SColor(255,255,128,128), video::SColor(255,255,128,128));
  221. }
  222. void PlayerReplica::PreDestruction(RakNet::Connection_RM3 *sourceConnection)
  223. {
  224. if (model)
  225. model->remove();
  226. }
  227. RM3SerializationResult PlayerReplica::Serialize(RakNet::SerializeParameters *serializeParameters)
  228. {
  229. BaseIrrlichtReplica::Serialize(serializeParameters);
  230. serializeParameters->outputBitstream[0].Write(position);
  231. serializeParameters->outputBitstream[0].Write(rotationAroundYAxis);
  232. serializeParameters->outputBitstream[0].Write(isMoving);
  233. serializeParameters->outputBitstream[0].Write(IsDead());
  234. return RM3SR_BROADCAST_IDENTICALLY;
  235. }
  236. void PlayerReplica::Deserialize(RakNet::DeserializeParameters *deserializeParameters)
  237. {
  238. BaseIrrlichtReplica::Deserialize(deserializeParameters);
  239. deserializeParameters->serializationBitstream[0].Read(position);
  240. deserializeParameters->serializationBitstream[0].Read(rotationAroundYAxis);
  241. deserializeParameters->serializationBitstream[0].Read(isMoving);
  242. bool wasDead=isDead;
  243. deserializeParameters->serializationBitstream[0].Read(isDead);
  244. if (isDead==true && wasDead==false)
  245. {
  246. demo->PlayDeathSound(position);
  247. }
  248. core::vector3df positionOffset;
  249. positionOffset=position-model->getPosition();
  250. positionDeltaPerMS = positionOffset / INTERP_TIME_MS;
  251. float rotationOffset;
  252. rotationOffset=GetRotationDifference(rotationAroundYAxis,model->getRotation().Y);
  253. rotationDeltaPerMS = rotationOffset / INTERP_TIME_MS;
  254. interpEndTime = RakNet::GetTimeMS() + (RakNet::TimeMS) INTERP_TIME_MS;
  255. }
  256. void PlayerReplica::Update(RakNet::TimeMS curTime)
  257. {
  258. // Is a locally created object?
  259. if (creatingSystemGUID==rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS))
  260. {
  261. // Local player has no mesh to interpolate
  262. // Input our camera position as our player position
  263. playerReplica->position=demo->GetSceneManager()->getActiveCamera()->getPosition()-irr::core::vector3df(0,CAMERA_HEIGHT,0);
  264. playerReplica->rotationAroundYAxis=demo->GetSceneManager()->getActiveCamera()->getRotation().Y-90.0f;
  265. isMoving=demo->IsMovementKeyDown();
  266. // Ack, makes the screen messed up and the mouse move off the window
  267. // Find another way to keep the dead player from moving
  268. // demo->EnableInput(IsDead()==false);
  269. return;
  270. }
  271. // Update interpolation
  272. RakNet::TimeMS elapsed = curTime-lastUpdate;
  273. if (elapsed<=1)
  274. return;
  275. if (elapsed>100)
  276. elapsed=100;
  277. lastUpdate=curTime;
  278. irr::core::vector3df curPositionDelta = position-model->getPosition();
  279. irr::core::vector3df interpThisTick = positionDeltaPerMS*(float) elapsed;
  280. if (curTime < interpEndTime && interpThisTick.getLengthSQ() < curPositionDelta.getLengthSQ())
  281. {
  282. model->setPosition(model->getPosition()+positionDeltaPerMS*(float) elapsed);
  283. }
  284. else
  285. {
  286. model->setPosition(position);
  287. }
  288. float curRotationDelta = GetRotationDifference(rotationAroundYAxis,model->getRotation().Y);
  289. float interpThisTickRotation = rotationDeltaPerMS*(float)elapsed;
  290. if (curTime < interpEndTime && fabs(interpThisTickRotation) < fabs(curRotationDelta))
  291. {
  292. model->setRotation(model->getRotation()+core::vector3df(0,interpThisTickRotation,0));
  293. }
  294. else
  295. {
  296. model->setRotation(core::vector3df(0,rotationAroundYAxis,0));
  297. }
  298. if (isDead)
  299. {
  300. UpdateAnimation(scene::EMAT_DEATH_FALLBACK);
  301. model->setLoopMode(false);
  302. }
  303. else if (curAnim!=scene::EMAT_ATTACK)
  304. {
  305. if (isMoving)
  306. {
  307. UpdateAnimation(scene::EMAT_RUN);
  308. model->setLoopMode(true);
  309. }
  310. else
  311. {
  312. UpdateAnimation(scene::EMAT_STAND);
  313. model->setLoopMode(true);
  314. }
  315. }
  316. }
  317. void PlayerReplica::UpdateAnimation(irr::scene::EMD2_ANIMATION_TYPE anim)
  318. {
  319. if (anim!=curAnim)
  320. model->setMD2Animation(anim);
  321. curAnim=anim;
  322. }
  323. float PlayerReplica::GetRotationDifference(float r1, float r2)
  324. {
  325. float diff = r1-r2;
  326. while (diff>180.0f)
  327. diff-=360.0f;
  328. while (diff<-180.0f)
  329. diff+=360.0f;
  330. return diff;
  331. }
  332. void PlayerReplica::OnAnimationEnd(scene::IAnimatedMeshSceneNode* node)
  333. {
  334. if (curAnim==scene::EMAT_ATTACK)
  335. {
  336. if (isMoving)
  337. {
  338. UpdateAnimation(scene::EMAT_RUN);
  339. model->setLoopMode(true);
  340. }
  341. else
  342. {
  343. UpdateAnimation(scene::EMAT_STAND);
  344. model->setLoopMode(true);
  345. }
  346. }
  347. }
  348. void PlayerReplica::PlayAttackAnimation(void)
  349. {
  350. if (isDead==false)
  351. {
  352. UpdateAnimation(scene::EMAT_ATTACK);
  353. model->setLoopMode(false);
  354. }
  355. }
  356. bool PlayerReplica::IsDead(void) const
  357. {
  358. return deathTimeout > RakNet::GetTimeMS();
  359. }
  360. BallReplica::BallReplica()
  361. {
  362. creationTime=RakNet::GetTimeMS();
  363. }
  364. BallReplica::~BallReplica()
  365. {
  366. }
  367. void BallReplica::WriteAllocationID(RakNet::Connection_RM3 *destinationConnection, RakNet::BitStream *allocationIdBitstream) const
  368. {
  369. allocationIdBitstream->Write(RakNet::RakString("BallReplica"));
  370. }
  371. void BallReplica::SerializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *destinationConnection)
  372. {
  373. BaseIrrlichtReplica::SerializeConstruction(constructionBitstream, destinationConnection);
  374. constructionBitstream->Write(shotDirection);
  375. }
  376. bool BallReplica::DeserializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *sourceConnection)
  377. {
  378. if (!BaseIrrlichtReplica::DeserializeConstruction(constructionBitstream, sourceConnection))
  379. return false;
  380. constructionBitstream->Read(shotDirection);
  381. return true;
  382. }
  383. void BallReplica::PostDeserializeConstruction(RakNet::BitStream *constructionBitstream, RakNet::Connection_RM3 *destinationConnection)
  384. {
  385. // Shot visible effect and BallReplica classes are not linked, but they update the same way, such that
  386. // they are in the same spot all the time
  387. demo->shootFromOrigin(position, shotDirection);
  388. // Find the owner of this ball, and make them play the attack animation
  389. unsigned int idx;
  390. for (idx=0; idx < PlayerReplica::playerList.Size(); idx++)
  391. {
  392. if (PlayerReplica::playerList[idx]->creatingSystemGUID==creatingSystemGUID)
  393. {
  394. PlayerReplica::playerList[idx]->PlayAttackAnimation();
  395. break;
  396. }
  397. }
  398. }
  399. void BallReplica::PreDestruction(RakNet::Connection_RM3 *sourceConnection)
  400. {
  401. // The system that shot this ball destroyed it, or disconnected
  402. // Technically we should clear out the node visible effect too, but it's not important for now
  403. }
  404. RM3SerializationResult BallReplica::Serialize(RakNet::SerializeParameters *serializeParameters)
  405. {
  406. BaseIrrlichtReplica::Serialize(serializeParameters);
  407. return RM3SR_BROADCAST_IDENTICALLY;
  408. }
  409. void BallReplica::Deserialize(RakNet::DeserializeParameters *deserializeParameters)
  410. {
  411. BaseIrrlichtReplica::Deserialize(deserializeParameters);
  412. }
  413. void BallReplica::Update(RakNet::TimeMS curTime)
  414. {
  415. // Is a locally created object?
  416. if (creatingSystemGUID==rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS))
  417. {
  418. // Destroy if shot expired
  419. if (curTime > shotLifetime)
  420. {
  421. // Destroy on network
  422. BroadcastDestruction();
  423. delete this;
  424. return;
  425. }
  426. }
  427. // Keep at the same position as the visible effect
  428. // Deterministic, so no need to actually transmit position
  429. // The variable position is the origin that the ball was created at. For the player, it is their actual position
  430. RakNet::TimeMS elapsedTime;
  431. // Due to ping variances and timestamp miscalculations, it's possible with very low pings to get a slightly negative time, so we have to check
  432. if (curTime>=creationTime)
  433. elapsedTime = curTime - creationTime;
  434. else
  435. elapsedTime=0;
  436. irr::core::vector3df updatedPosition = position + shotDirection * (float) elapsedTime * SHOT_SPEED;
  437. // See if the bullet hit us
  438. if (creatingSystemGUID!=rakPeer->GetGuidFromSystemAddress(RakNet::UNASSIGNED_SYSTEM_ADDRESS))
  439. {
  440. if (playerReplica->IsDead()==false)
  441. {
  442. float playerHalfHeight=demo->GetSyndeyBoundingBox().getExtent().Y/2;
  443. irr::core::vector3df positionRelativeToCharacter = updatedPosition-playerReplica->position;//+core::vector3df(0,playerHalfHeight,0);
  444. if (demo->GetSyndeyBoundingBox().isPointInside(positionRelativeToCharacter))
  445. //if ((playerReplica->position+core::vector3df(0,playerHalfHeight,0)-updatedPosition).getLengthSQ() < BALL_DIAMETER*BALL_DIAMETER/4.0f)
  446. {
  447. // We're dead for 3 seconds
  448. playerReplica->deathTimeout=curTime+3000;
  449. }
  450. }
  451. }
  452. }
  453. RakNet::Replica3 *Connection_RM3Irrlicht::AllocReplica(RakNet::BitStream *allocationId, ReplicaManager3 *replicaManager3)
  454. {
  455. RakNet::RakString typeName; allocationId->Read(typeName);
  456. if (typeName=="PlayerReplica") {BaseIrrlichtReplica *r = new PlayerReplica; r->demo=demo; return r;}
  457. if (typeName=="BallReplica") {BaseIrrlichtReplica *r = new BallReplica; r->demo=demo; return r;}
  458. return 0;
  459. }
粤ICP备19079148号