the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at master 611 lines 18 kB view raw
1#include "stdafx.h" 2#include "SQRNetworkPlayer.h" 3 4#ifdef __PS3__ 5#include <cell/rudp.h> 6#include "PS3/Network/SonyVoiceChat.h" 7 8#elif defined __ORBIS__ 9#include <rudp.h> 10#include "Orbis/Network/SonyVoiceChat_Orbis.h" 11 12#else // __PSVITA__ 13#include <rudp.h> 14#include <adhoc_matching.h> 15#include "PSVita/Network/SonyVoiceChat_Vita.h" 16 17#endif 18 19//#define PRINT_ACK_STATS 20 21#ifdef __PS3__ 22static const int sc_wouldBlockFlag = CELL_RUDP_ERROR_WOULDBLOCK; 23#else // __ORBIS__ 24static const int sc_wouldBlockFlag = SCE_RUDP_ERROR_WOULDBLOCK; 25#endif 26 27 28 29static const bool sc_verbose = false; 30 31int SQRNetworkPlayer::GetSmallId() 32{ 33 return m_ISD.m_smallId; 34} 35 36wchar_t *SQRNetworkPlayer::GetName() 37{ 38 return m_name; 39} 40 41bool SQRNetworkPlayer::IsRemote() 42{ 43 return !IsLocal(); 44} 45 46bool SQRNetworkPlayer::IsHost() 47{ 48 return (m_type == SNP_TYPE_HOST); 49} 50 51bool SQRNetworkPlayer::IsLocal() 52{ 53 // m_host determines whether this *machine* is hosting the game, not this player (which is determined by m_type) 54 if( m_host ) 55 { 56 // If we are the hosting machine, then both the host & local players are local to this machine 57 return (m_type == SNP_TYPE_HOST) || (m_type == SNP_TYPE_LOCAL); 58 } 59 else 60 { 61 // Not hosting, just local players are actually physically local 62 return (m_type == SNP_TYPE_LOCAL) ; 63 } 64} 65 66int SQRNetworkPlayer::GetLocalPlayerIndex() 67{ 68 return m_localPlayerIdx; 69} 70 71bool SQRNetworkPlayer::IsSameSystem(SQRNetworkPlayer *other) 72{ 73 return (m_roomMemberId == other->m_roomMemberId); 74} 75 76uintptr_t SQRNetworkPlayer::GetCustomDataValue() 77{ 78 return m_customData; 79} 80 81void SQRNetworkPlayer::SetCustomDataValue(uintptr_t data) 82{ 83 m_customData = data; 84} 85 86SQRNetworkPlayer::SQRNetworkPlayer(SQRNetworkManager *manager, eSQRNetworkPlayerType playerType, bool onHost, SceNpMatching2RoomMemberId roomMemberId, int localPlayerIdx, int rudpCtx, PlayerUID *pUID) 87{ 88 m_roomMemberId = roomMemberId; 89 m_localPlayerIdx = localPlayerIdx; 90 m_rudpCtx = rudpCtx; 91 m_flags = 0; 92 m_type = playerType; 93 m_host = onHost; 94 m_manager = manager; 95 m_customData = 0; 96 m_acksOutstanding = 0; 97 m_totalBytesInSendQueue = 0; 98 if( pUID ) 99 { 100 memcpy(&m_ISD.m_UID,pUID,sizeof(PlayerUID)); 101#ifdef __PSVITA__ 102 if(CGameNetworkManager::usingAdhocMode() && pUID->getOnlineID()[0] == 0) 103 { 104 assert(localPlayerIdx == 0); 105 // player doesn't have an online UID, set it from the player name 106 m_ISD.m_UID.setForAdhoc(); 107 } 108#endif // __PSVITA__ 109 } 110 else 111 { 112 memset(&m_ISD.m_UID,0,sizeof(PlayerUID)); 113 } 114 SetNameFromUID(); 115 InitializeCriticalSection(&m_csQueue); 116 InitializeCriticalSection(&m_csAcks); 117#ifdef __ORBIS__ 118 if(IsLocal()) 119 { 120 SonyVoiceChat_Orbis::initLocalPlayer(m_localPlayerIdx); 121 } 122#endif 123 124#ifndef _CONTENT_PACKAGE 125 m_minAckTime = INT_MAX; 126 m_maxAckTime = 0; 127 m_totalAcks = 0; 128 m_totalAckTime = 0; 129 m_averageAckTime = 0; 130#endif 131 132} 133 134SQRNetworkPlayer::~SQRNetworkPlayer() 135{ 136#ifdef __ORBIS__ 137 SQRNetworkManager_Orbis* pMan = (SQRNetworkManager_Orbis*)m_manager; 138// pMan->removePlayerFromVoiceChat(this); 139// m_roomMemberId = -1; 140#endif 141 DeleteCriticalSection(&m_csQueue); 142} 143 144bool SQRNetworkPlayer::IsReady() 145{ 146 return ( ( m_flags & SNP_FLAG_READY_MASK ) == SNP_FLAG_READY_MASK ); 147} 148 149PlayerUID SQRNetworkPlayer::GetUID() 150{ 151 return m_ISD.m_UID; 152} 153 154void SQRNetworkPlayer::SetUID(PlayerUID UID) 155{ 156 m_ISD.m_UID = UID; 157 SetNameFromUID(); 158} 159 160bool SQRNetworkPlayer::HasConnectionAndSmallId() 161{ 162 const int reqFlags = ( SNP_FLAG_CONNECTION_COMPLETE | SNP_FLAG_SMALLID_ALLOCATED ); 163 return (( m_flags & reqFlags) == reqFlags); 164} 165 166void SQRNetworkPlayer::ConnectionComplete() 167{ 168 m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:"); 169 app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ConnectionComplete\n"); 170 m_flags |= SNP_FLAG_CONNECTION_COMPLETE; 171} 172 173void SQRNetworkPlayer::SmallIdAllocated(unsigned char smallId) 174{ 175 m_ISD.m_smallId = smallId; 176 m_flags |= SNP_FLAG_SMALLID_ALLOCATED; 177 m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:"); 178 app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID allocated\n"); 179 180 181 // If this is a non-network sort of player then flag now as having its small id confirmed 182 if( ( m_type == SNP_TYPE_HOST ) || 183 ( m_host && ( m_type == SNP_TYPE_LOCAL ) ) || 184 ( !m_host && ( m_type == SNP_TYPE_REMOTE ) ) ) 185 { 186 m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:"); 187 app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID confirmed\n"); 188 189 m_flags |= SNP_FLAG_SMALLID_CONFIRMED; 190 } 191} 192 193void SQRNetworkPlayer::InitialDataReceived(SQRNetworkPlayer::InitSendData *ISD) 194{ 195 assert(m_ISD.m_smallId == ISD->m_smallId); 196 memcpy(&m_ISD, ISD, sizeof(InitSendData) ); 197#ifdef __PSVITA__ 198 SetNameFromUID(); 199#endif 200 m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:"); 201 app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID confirmed\n"); 202 m_flags |= SNP_FLAG_SMALLID_CONFIRMED; 203} 204 205bool SQRNetworkPlayer::HasSmallIdConfirmed() 206{ 207 return ( m_flags & SNP_FLAG_SMALLID_CONFIRMED ); 208} 209 210// To confirm to the host that we are ready, send a single byte with our small id. 211void SQRNetworkPlayer::ConfirmReady() 212{ 213 SendInternal(&m_ISD, sizeof(InitSendData), e_flag_AckNotRequested); 214 215 // Final flag for a local player on the client, as we are now safe to send data on to the host 216 m_host ? app.DebugPrintf(sc_verbose, "host : ") : app.DebugPrintf(sc_verbose, "client:"); 217 app.DebugPrintf(sc_verbose, ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Small ID confirmed\n"); 218 m_flags |= SNP_FLAG_SMALLID_CONFIRMED; 219} 220 221// Attempt to send data, of any size, from this player to that specified by pPlayerTarget. This may not be possible depending on the two players, due to 222// our star shaped network connectivity. Data may be any size, and is copied so on returning from this method it does not need to be preserved. 223void SQRNetworkPlayer::SendData( SQRNetworkPlayer *pPlayerTarget, const void *data, unsigned int dataSize, bool ack ) 224{ 225 AckFlags ackFlags = ack ? e_flag_AckRequested : e_flag_AckNotRequested; 226 // Our network is connected as a star. If we are the host, then we can send to any remote player. If we're a client, we can send only to the host. 227 // The host can also send to other local players, but this doesn't need to go through Rudp. 228 if( m_host ) 229 { 230 if( ( m_type == SNP_TYPE_HOST ) && ( pPlayerTarget->m_type == SNP_TYPE_LOCAL ) ) 231 { 232 // Special internal communication from host to local player 233 m_manager->LocalDataSend( this, pPlayerTarget, data, dataSize ); 234 } 235 else if( ( m_type == SNP_TYPE_LOCAL ) && ( pPlayerTarget->m_type == SNP_TYPE_HOST ) ) 236 { 237 // Special internal communication from local player to host 238 m_manager->LocalDataSend( this, pPlayerTarget, data, dataSize ); 239 } 240 else if( ( m_type == SNP_TYPE_HOST ) && ( pPlayerTarget->m_type == SNP_TYPE_REMOTE ) ) 241 { 242 // Rudp communication from host to remote player - handled by remote player instance 243 pPlayerTarget->SendInternal(data,dataSize, ackFlags); 244 } 245 else 246 { 247 // Can't do any other types of communications 248 assert(false); 249 } 250 } 251 else 252 { 253 if( ( m_type == SNP_TYPE_LOCAL ) && ( pPlayerTarget->m_type == SNP_TYPE_HOST ) ) 254 { 255 // Rudp communication from client to host - handled by this player instace 256 SendInternal(data, dataSize, ackFlags); 257 } 258 else 259 { 260 // Can't do any other types of communications 261 assert(false); 262 } 263 } 264} 265 266// Internal send function - to simplify the number of mechanisms we have for sending data, this method just adds the data to be send to the player's internal queue, 267// and then calls SendMoreInternal. This method can take any size of data, which it will split up into payload size chunks before sending. All input data is copied 268// into internal buffers. 269void SQRNetworkPlayer::SendInternal(const void *data, unsigned int dataSize, AckFlags ackFlags) 270{ 271 EnterCriticalSection(&m_csQueue); 272 bool bOutstandingPackets = (m_sendQueue.size() > 0); // check if there are still packets in the queue, we won't be calling SendMoreInternal here if there are 273 QueuedSendBlock sendBlock; 274 275 unsigned char *dataCurrent = (unsigned char *)data; 276 unsigned int dataRemaining = dataSize; 277 278 if(ackFlags == e_flag_AckReturning) 279 { 280 // no data, just the flag 281 assert(dataSize == 0); 282 assert(data == NULL); 283 int dataSize = dataRemaining; 284 if( dataSize > SNP_MAX_PAYLOAD ) dataSize = SNP_MAX_PAYLOAD; 285 sendBlock.start = NULL; 286 sendBlock.end = NULL; 287 sendBlock.current = NULL; 288 sendBlock.ack = ackFlags; 289 m_sendQueue.push(sendBlock); 290 } 291 else 292 { 293 while( dataRemaining ) 294 { 295 int dataSize = dataRemaining; 296 if( dataSize > SNP_MAX_PAYLOAD ) dataSize = SNP_MAX_PAYLOAD; 297 sendBlock.start = new unsigned char [dataSize]; 298 sendBlock.end = sendBlock.start + dataSize; 299 sendBlock.current = sendBlock.start; 300 sendBlock.ack = ackFlags; 301 memcpy( sendBlock.start, dataCurrent, dataSize); 302 m_sendQueue.push(sendBlock); 303 dataRemaining -= dataSize; 304 dataCurrent += dataSize; 305 } 306 307 } 308 m_totalBytesInSendQueue += dataSize; 309 310 // if the queue had something in it already, then the UDP callback will fire and call SendMoreInternal 311 // so we don't call it here, to avoid a deadlock 312 if(!bOutstandingPackets) 313 { 314 // Now try and send as much as we can 315 SendMoreInternal(); 316 } 317 318 LeaveCriticalSection(&m_csQueue); 319} 320 321 322int SQRNetworkPlayer::WriteDataPacket(const void* data, int dataSize, AckFlags ackFlags) 323 { 324 DataPacketHeader header(dataSize, ackFlags); 325 int headerSize = sizeof(header); 326 int packetSize = dataSize+headerSize; 327 unsigned char* packetData = new unsigned char[packetSize]; 328 *((DataPacketHeader*)packetData) = header; 329 memcpy(&packetData[headerSize], data, dataSize); 330 331#ifndef _CONTENT_PACKAGE 332 if(ackFlags == e_flag_AckRequested) 333 m_ackStats.push_back(System::currentTimeMillis()); 334#endif 335 336#ifdef __PS3__ 337 int ret = cellRudpWrite( m_rudpCtx, packetData, packetSize, 0);//CELL_RUDP_MSG_LATENCY_CRITICAL ); 338#else // __ORBIS__ && __PSVITA__ 339 int ret = sceRudpWrite( m_rudpCtx, packetData, packetSize, 0);//SCE_RUDP_MSG_LATENCY_CRITICAL ); 340#endif 341 if(ret == sc_wouldBlockFlag) 342 { 343 // nothing was sent! 344 } 345 else 346 { 347 assert(ret==packetSize || ret > headerSize); // we must make sure we've sent the entire packet or the header and some data at least 348 ret -= headerSize; 349 if(ackFlags == e_flag_AckRequested) 350 { 351 EnterCriticalSection(&m_csAcks); 352 m_acksOutstanding++; 353 LeaveCriticalSection(&m_csAcks); 354 } 355 } 356 delete packetData; 357 358 return ret; 359} 360 361int SQRNetworkPlayer::GetPacketDataSize() 362{ 363 unsigned int ackFlag; 364 int headerSize = sizeof(ackFlag); 365#ifdef __PS3__ 366 unsigned int packetSize = cellRudpGetSizeReadable(m_rudpCtx); 367#else 368 unsigned int packetSize = sceRudpGetSizeReadable(m_rudpCtx); 369#endif 370 if(packetSize == 0) 371 return 0; 372 373 unsigned int dataSize = packetSize - headerSize; 374 assert(dataSize >= 0); 375 if(dataSize == 0) 376 { 377 // header only, must just be an ack returning 378 ReadAck(); 379 } 380 return dataSize; 381} 382 383int SQRNetworkPlayer::ReadDataPacket(void* data, int dataSize) 384{ 385 int headerSize = sizeof(DataPacketHeader); 386 int packetSize = dataSize+headerSize; 387 388 unsigned char* packetData = new unsigned char[packetSize]; 389#ifdef __PS3__ 390 int bytesRead = cellRudpRead( m_rudpCtx, packetData, packetSize, 0, NULL ); 391#else // __ORBIS__ && __PSVITA__ 392 int bytesRead = sceRudpRead( m_rudpCtx, packetData, packetSize, 0, NULL ); 393#endif 394 if(bytesRead == sc_wouldBlockFlag) 395 { 396 delete packetData; 397 return 0; 398 } 399 // check the header, and see if we need to send back an ack 400 DataPacketHeader header = *((DataPacketHeader*)packetData); 401 if(header.GetAckFlags() == e_flag_AckRequested) 402 { 403 // Don't send the ack back directly from here, as this is called from a rudp event callback, and we end up in a thread lock situation between the lock librudp uses 404 // internally (which is locked already here since we are being called in the event handler), and our own lock that we do for processing our write queue 405 m_manager->RequestWriteAck(GetSmallId()); 406 } 407 else 408 { 409 assert(header.GetAckFlags() == e_flag_AckNotRequested); 410 } 411 if(bytesRead > 0) 412 { 413 bytesRead -= headerSize; 414 memcpy(data, &packetData[headerSize], bytesRead); 415 } 416 assert(header.GetDataSize() == bytesRead); 417 418 delete packetData; 419 420 return bytesRead; 421} 422 423 424 425void SQRNetworkPlayer::ReadAck() 426{ 427 DataPacketHeader header; 428#ifdef __PS3__ 429 int bytesRead = cellRudpRead( m_rudpCtx, &header, sizeof(header), 0, NULL ); 430#else // __ORBIS__ && __PSVITA__ 431 int bytesRead = sceRudpRead( m_rudpCtx, &header, sizeof(header), 0, NULL ); 432#endif 433 if(bytesRead == sc_wouldBlockFlag) 434 { 435 return; 436 } 437 438 assert(header.GetAckFlags() == e_flag_AckReturning); 439 EnterCriticalSection(&m_csAcks); 440 m_acksOutstanding--; 441 assert(m_acksOutstanding >=0); 442 LeaveCriticalSection(&m_csAcks); 443 444#ifndef _CONTENT_PACKAGE 445#ifdef PRINT_ACK_STATS 446 __int64 timeTaken = System::currentTimeMillis() - m_ackStats[0]; 447 if(timeTaken < m_minAckTime) 448 m_minAckTime = timeTaken; 449 if(timeTaken > m_maxAckTime) 450 m_maxAckTime = timeTaken; 451 m_totalAcks++; 452 m_totalAckTime += timeTaken; 453 m_averageAckTime = m_totalAckTime / m_totalAcks; 454 app.DebugPrintf("RUDP ctx : %d : Time taken for ack - %4d ms : min - %4d : max %4d : avg %4d\n", m_rudpCtx, timeTaken, m_minAckTime, m_maxAckTime, m_averageAckTime); 455 m_ackStats.erase(m_ackStats.begin()); 456#endif 457#endif 458} 459 460void SQRNetworkPlayer::WriteAck() 461{ 462 SendInternal(NULL, 0, e_flag_AckReturning); 463} 464 465int SQRNetworkPlayer::GetOutstandingAckCount() 466{ 467 return m_manager->GetOutstandingAckCount(this); 468} 469 470int SQRNetworkPlayer::GetTotalOutstandingAckCount() 471{ 472 return m_acksOutstanding; 473} 474 475int SQRNetworkPlayer::GetTotalSendQueueBytes() 476{ 477 return m_totalBytesInSendQueue; 478} 479 480int SQRNetworkPlayer::GetTotalSendQueueMessages() 481{ 482 CriticalSectionScopeLock lock(&m_csQueue); 483 return m_sendQueue.size(); 484 485} 486 487int SQRNetworkPlayer::GetSendQueueSizeBytes() 488{ 489 return m_manager->GetSendQueueSizeBytes(); 490} 491 492int SQRNetworkPlayer::GetSendQueueSizeMessages() 493{ 494 return m_manager->GetSendQueueSizeMessages(); 495} 496 497 498 499// Internal send function. This attempts to send as many elements in the queue as possible until the write function tells us that we can't send any more. This way, 500// we are guaranteed that if there *is* anything more in the queue left to send, we'll get a CELL_RUDP_CONTEXT_EVENT_WRITABLE event when whatever we've managed to 501// send here is complete, and can continue on. 502void SQRNetworkPlayer::SendMoreInternal() 503{ 504 EnterCriticalSection(&m_csQueue); 505 assert(m_sendQueue.size() > 0); // this should never be called with an empty queue. 506 507 bool keepSending; 508 do 509 { 510 keepSending = false; 511 if( m_sendQueue.size() > 0) 512 { 513 // Attempt to send the full data in the first element in our queue 514 unsigned char *data= m_sendQueue.front().current; 515 int dataSize = m_sendQueue.front().end - m_sendQueue.front().current; 516 int ret = WriteDataPacket(data, dataSize, m_sendQueue.front().ack); 517 518 if( ret == dataSize ) 519 { 520 // Fully sent, remove from queue - will loop in the while loop to see if there's anything else in the queue we could send 521 m_totalBytesInSendQueue -= ret; 522 delete [] m_sendQueue.front().start; 523 m_sendQueue.pop(); 524 if( m_sendQueue.size() ) 525 { 526 keepSending = true; 527 } 528 } 529 else if( ( ret >= 0 ) || ( ret == sc_wouldBlockFlag ) ) 530 { 531 532 // Things left to send - adjust this element in the queue 533 int remainingBytes; 534 if( ret >= 0 ) 535 { 536 // Only ret bytes sent so far 537 m_totalBytesInSendQueue -= ret; 538 remainingBytes = dataSize - ret; 539 assert(remainingBytes > 0 ); 540 } 541 else 542 { 543 // Is CELL_RUDP_ERROR_WOULDBLOCK, nothing has yet been sent 544 remainingBytes = dataSize; 545 } 546 m_sendQueue.front().current = m_sendQueue.front().end - remainingBytes; 547 } 548 } 549 } while (keepSending); 550 LeaveCriticalSection(&m_csQueue); 551} 552 553void SQRNetworkPlayer::SetNameFromUID() 554{ 555 mbstowcs(m_name, m_ISD.m_UID.getOnlineID(), 16); 556 m_name[16] = 0; 557#ifdef __PS3__ // only 1 player on vita, and they have to be online (or adhoc), and with PS4 all local players need to be signed in 558 // Not an online player? Add a suffix with the controller ID on 559 if( m_ISD.m_UID.isSignedIntoPSN() == 0) 560 { 561 int pos = wcslen(m_name); 562 swprintf(&m_name[pos], 5, L" (%d)", m_ISD.m_UID.getQuadrant() + 1 ); 563 } 564#endif 565} 566 567void SQRNetworkPlayer::SetName(char *name) 568{ 569 mbstowcs(m_name, name, 20); 570 m_name[20] = 0; 571} 572 573int SQRNetworkPlayer::GetSessionIndex() 574{ 575 return m_manager->GetSessionIndex(this); 576} 577 578bool SQRNetworkPlayer::HasVoice() 579{ 580#ifdef __ORBIS__ 581 return SonyVoiceChat_Orbis::hasMicConnected(this); 582#elif defined __PSVITA__ 583 return SonyVoiceChat_Vita::hasMicConnected(this); 584#else 585 return SonyVoiceChat::hasMicConnected(&m_roomMemberId); 586#endif 587} 588 589bool SQRNetworkPlayer::IsTalking() 590{ 591#ifdef __ORBIS__ 592 return SonyVoiceChat_Orbis::isTalking(this); 593#elif defined __PSVITA__ 594 return SonyVoiceChat_Vita::isTalking(this); 595#else 596 return SonyVoiceChat::isTalking(&m_roomMemberId); 597#endif 598} 599 600bool SQRNetworkPlayer::IsMutedByLocalUser(int userIndex) 601{ 602#ifdef __ORBIS__ 603// assert(0); // this is never called, so isn't implemented in the PS4 voice stuff at the moment 604 return false; 605#elif defined __PSVITA__ 606 return false;// this is never called, so isn't implemented in the Vita voice stuff at the moment 607#else 608 SQRNetworkManager_PS3* pMan = (SQRNetworkManager_PS3*)m_manager; 609 return SonyVoiceChat::isMutedPlayer(pMan->m_roomSyncData.players[userIndex].m_roomMemberId); 610#endif 611}