2022-06-16 21:33:18 +00:00
# include "server/Client.hpp"
2022-09-04 09:23:02 +00:00
# include "al/layout/SimpleLayoutAppearWaitEnd.h"
2022-06-16 21:33:18 +00:00
# include "al/util/LiveActorUtil.h"
2022-07-05 19:45:22 +00:00
# include "game/SaveData/SaveDataAccessFunction.h"
2022-06-16 21:33:18 +00:00
# include "heap/seadHeapMgr.h"
# include "logger.hpp"
# include "packets/Packet.h"
2022-08-07 21:42:56 +00:00
# include "server/hns/HideAndSeekMode.hpp"
2022-06-16 21:33:18 +00:00
2022-07-08 08:02:28 +00:00
SEAD_SINGLETON_DISPOSER_IMPL ( Client )
2022-06-16 21:33:18 +00:00
typedef void ( Client : : * ClientThreadFunc ) ( void ) ;
/**
* @ brief Construct a new Client : : Client object
*
* @ param bufferSize defines the maximum amount of puppets the client can handle
*/
2022-07-08 08:02:28 +00:00
Client : : Client ( ) {
2022-09-04 09:23:02 +00:00
mHeap = sead : : ExpHeap : : create ( 0x50000 , " ClientHeap " , sead : : HeapMgr : : instance ( ) - > getCurrentHeap ( ) , 8 , sead : : Heap : : cHeapDirection_Forward , false ) ;
2022-07-08 08:02:28 +00:00
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter heapSetter (
mHeap ) ; // every new call after this will use ClientHeap instead of SequenceHeap
2022-07-08 08:02:28 +00:00
2022-09-04 09:23:02 +00:00
mReadThread = new al : : AsyncFunctorThread ( " ClientReadThread " , al : : FunctorV0M < Client * , ClientThreadFunc > ( this , & Client : : readFunc ) , 0 , 0x1000 , { 0 } ) ;
2022-06-16 21:33:18 +00:00
mKeyboard = new Keyboard ( nn : : swkbd : : GetRequiredStringBufferSize ( ) ) ;
2022-09-05 01:21:43 +00:00
mSocket = new SocketClient ( " SocketClient " , mHeap , this ) ;
2022-06-16 21:33:18 +00:00
mPuppetHolder = new PuppetHolder ( maxPuppets ) ;
2022-07-10 01:24:00 +00:00
for ( size_t i = 0 ; i < MAXPUPINDEX ; i + + )
2022-06-16 21:33:18 +00:00
{
mPuppetInfoArr [ i ] = new PuppetInfo ( ) ;
sprintf ( mPuppetInfoArr [ i ] - > puppetName , " Puppet%zu " , i ) ;
}
strcpy ( mDebugPuppetInfo . puppetName , " PuppetDebug " ) ;
mConnectCount = 0 ;
curCollectedShines . fill ( - 1 ) ;
collectedShineCount = 0 ;
mShineArray . allocBuffer ( 100 , nullptr ) ; // max of 100 shine actors in buffer
nn : : account : : GetLastOpenedUser ( & mUserID ) ;
nn : : account : : Nickname playerName ;
nn : : account : : GetNickname ( & playerName , mUserID ) ;
2022-07-08 08:02:28 +00:00
Logger : : setLogName ( playerName . name ) ; // set Debug logger name to player name
2022-06-16 21:33:18 +00:00
mUsername = playerName . name ;
2022-07-08 22:09:04 +00:00
mUserID . print ( ) ;
2022-06-16 21:33:18 +00:00
Logger : : log ( " Player Name: %s \n " , playerName . name ) ;
2022-07-05 19:45:22 +00:00
Logger : : log ( " %s Build Number: %s \n " , playerName . name , TOSTRING ( BUILDVERSTR ) ) ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief initializes client class using initInfo obtained from StageScene : : init
*
* @ param initInfo init info used to create layouts used by client
*/
2022-07-05 19:45:22 +00:00
void Client : : init ( al : : LayoutInitInfo const & initInfo , GameDataHolderAccessor holder ) {
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
mConnectStatus = new ( mHeap ) al : : SimpleLayoutAppearWaitEnd ( " " , " SaveMessage " , initInfo , 0 , false ) ;
al : : setPaneString ( mConnectStatus , " TxtSave " , u " Connecting to Server. " , 0 ) ;
al : : setPaneString ( mConnectStatus , " TxtSaveSh " , u " Connecting to Server. " , 0 ) ;
2022-06-16 21:33:18 +00:00
2023-07-08 18:45:53 +00:00
mUIMessage = new ( mHeap ) al : : WindowConfirmWait ( " ServerWaitConnect " , " WindowConfirmWait " , initInfo ) ;
mUIMessage - > setTxtMessage ( u " a " ) ;
mUIMessage - > setTxtMessageConfirm ( u " b " ) ;
2022-09-04 09:23:02 +00:00
mHolder = holder ;
2022-07-08 08:02:28 +00:00
2022-09-04 09:23:02 +00:00
startThread ( ) ;
2022-07-10 01:24:00 +00:00
2022-09-04 09:23:02 +00:00
Logger : : log ( " Heap Free Size: %f/%f \n " , mHeap - > getFreeSize ( ) * 0.001f , mHeap - > getSize ( ) * 0.001f ) ;
2022-06-16 21:33:18 +00:00
}
2022-09-05 01:21:43 +00:00
2022-06-16 21:33:18 +00:00
/**
* @ brief starts client read thread
*
2022-10-30 01:21:58 +00:00
* @ return true if read thread was succesfully started
2022-06-16 21:33:18 +00:00
* @ return false if read thread was unable to start , or thread was already started .
*/
2022-09-04 09:23:02 +00:00
bool Client : : startThread ( ) {
if ( mReadThread - > isDone ( ) ) {
mReadThread - > start ( ) ;
2022-10-30 01:21:58 +00:00
Logger : : log ( " Read Thread Successfully Started. \n " ) ;
2022-06-16 21:33:18 +00:00
return true ;
} else {
2022-09-04 09:23:02 +00:00
Logger : : log ( " Read Thread has already started! Or other unknown reason. \n " ) ;
2022-06-16 21:33:18 +00:00
return false ;
}
}
/**
* @ brief starts a connection using client ' s TCP socket class , pulling up the software keyboard for user inputted IP if save file does not have one saved .
*
* @ return true if successful connection to server
* @ return false if connection was unable to establish
*/
bool Client : : startConnection ( ) {
2022-07-05 19:45:22 +00:00
bool isNeedSave = false ;
2022-07-08 05:36:29 +00:00
bool isOverride = al : : isPadHoldZL ( - 1 ) ;
if ( mServerIP . isEmpty ( ) | | isOverride ) {
2022-06-16 21:33:18 +00:00
mKeyboard - > setHeaderText ( u " Save File does not contain an IP! " ) ;
mKeyboard - > setSubText ( u " Please set a Server IP Below. " ) ;
2022-07-18 01:30:14 +00:00
mServerIP = " 127.0.0.1 " ;
2022-06-19 00:48:37 +00:00
Client : : openKeyboardIP ( ) ;
2022-07-05 19:45:22 +00:00
isNeedSave = true ;
2022-06-19 00:48:37 +00:00
}
2022-06-16 21:33:18 +00:00
2022-07-08 05:36:29 +00:00
if ( ! mServerPort | | isOverride ) {
2022-06-19 00:48:37 +00:00
mKeyboard - > setHeaderText ( u " Save File does not contain a port! " ) ;
mKeyboard - > setSubText ( u " Please set a Server Port Below. " ) ;
mServerPort = 1027 ;
Client : : openKeyboardPort ( ) ;
2022-07-05 19:45:22 +00:00
isNeedSave = true ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
if ( isNeedSave ) {
SaveDataAccessFunction : : startSaveDataWrite ( mHolder . mData ) ;
}
mIsConnectionActive = mSocket - > init ( mServerIP . cstr ( ) , mServerPort ) . isSuccess ( ) ;
if ( mIsConnectionActive ) {
2022-10-30 01:21:58 +00:00
Logger : : log ( " Succesful Connection. Waiting to receive init packet. \n " ) ;
2022-06-16 21:33:18 +00:00
2022-07-06 21:42:41 +00:00
bool waitingForInitPacket = true ;
2022-06-16 21:33:18 +00:00
// wait for client init packet
2022-09-04 09:23:02 +00:00
2022-07-06 21:42:41 +00:00
while ( waitingForInitPacket ) {
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
Packet * curPacket = mSocket - > tryGetPacket ( ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
if ( curPacket ) {
if ( curPacket - > mType = = PacketType : : CLIENTINIT ) {
InitPacket * initPacket = ( InitPacket * ) curPacket ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
Logger : : log ( " Server Max Player Size: %d \n " , initPacket - > maxPlayers ) ;
2022-07-06 21:42:41 +00:00
2022-09-04 09:23:02 +00:00
maxPuppets = initPacket - > maxPlayers - 1 ;
2022-06-16 21:33:18 +00:00
2022-07-06 21:42:41 +00:00
waitingForInitPacket = false ;
}
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
mHeap - > free ( curPacket ) ;
2022-07-05 19:45:22 +00:00
} else {
2022-10-30 01:21:58 +00:00
Logger : : log ( " Receive failed! Stopping Connection. \n " ) ;
2022-07-05 19:45:22 +00:00
mIsConnectionActive = false ;
2022-07-06 21:42:41 +00:00
waitingForInitPacket = false ;
2022-06-16 21:33:18 +00:00
}
}
2022-09-03 08:57:57 +00:00
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
return mIsConnectionActive ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief Opens up OS ' s software keyboard in order to change the currently used server IP .
2022-07-10 01:24:00 +00:00
* @ returns whether or not a new IP has been defined and needs to be saved .
2022-06-16 21:33:18 +00:00
*/
2022-07-10 01:24:00 +00:00
bool Client : : openKeyboardIP ( ) {
2022-06-16 21:33:18 +00:00
if ( ! sInstance ) {
Logger : : log ( " Static Instance is null! \n " ) ;
2022-07-10 01:24:00 +00:00
return false ;
2022-06-16 21:33:18 +00:00
}
2022-06-19 00:48:37 +00:00
// opens swkbd with the initial text set to the last saved IP
2022-07-10 01:24:00 +00:00
sInstance - > mKeyboard - > openKeyboard (
sInstance - > mServerIP . cstr ( ) , [ ] ( nn : : swkbd : : KeyboardConfig & config ) {
2022-07-18 01:31:02 +00:00
config . keyboardMode = nn : : swkbd : : KeyboardMode : : ModeASCII ;
2022-07-10 06:13:28 +00:00
config . textMaxLength = MAX_HOSTNAME_LENGTH ;
2022-07-10 01:24:00 +00:00
config . textMinLength = 1 ;
config . isUseUtf8 = true ;
config . inputFormMode = nn : : swkbd : : InputFormMode : : OneLine ;
} ) ;
2022-07-10 06:13:28 +00:00
hostname prevIp = sInstance - > mServerIP ;
2022-06-16 21:33:18 +00:00
while ( true ) {
if ( sInstance - > mKeyboard - > isThreadDone ( ) ) {
2022-07-10 01:24:00 +00:00
if ( ! sInstance - > mKeyboard - > isKeyboardCancelled ( ) )
sInstance - > mServerIP = sInstance - > mKeyboard - > getResult ( ) ;
2022-06-16 21:33:18 +00:00
break ;
}
nn : : os : : YieldThread ( ) ; // allow other threads to run
}
2022-07-10 01:24:00 +00:00
2022-09-04 09:23:02 +00:00
bool isFirstConnect = prevIp ! = sInstance - > mServerIP ;
2022-07-10 01:24:00 +00:00
2022-09-04 09:23:02 +00:00
sInstance - > mSocket - > setIsFirstConn ( isFirstConnect ) ;
return isFirstConnect ;
2022-06-16 21:33:18 +00:00
}
2022-06-19 00:48:37 +00:00
/**
* @ brief Opens up OS ' s software keyboard in order to change the currently used server port .
2022-07-10 01:24:00 +00:00
* @ returns whether or not a new port has been defined and needs to be saved .
2022-06-19 00:48:37 +00:00
*/
2022-07-10 01:24:00 +00:00
bool Client : : openKeyboardPort ( ) {
2022-06-19 00:48:37 +00:00
if ( ! sInstance ) {
Logger : : log ( " Static Instance is null! \n " ) ;
2022-07-10 01:24:00 +00:00
return false ;
2022-06-19 00:48:37 +00:00
}
// opens swkbd with the initial text set to the last saved port
char buf [ 6 ] ;
nn : : util : : SNPrintf ( buf , 6 , " %u " , sInstance - > mServerPort ) ;
2022-07-10 01:24:00 +00:00
sInstance - > mKeyboard - > openKeyboard ( buf , [ ] ( nn : : swkbd : : KeyboardConfig & config ) {
2022-06-19 00:48:37 +00:00
config . keyboardMode = nn : : swkbd : : KeyboardMode : : ModeNumeric ;
config . textMaxLength = 5 ;
config . textMinLength = 2 ;
config . isUseUtf8 = true ;
config . inputFormMode = nn : : swkbd : : InputFormMode : : OneLine ;
} ) ;
2022-07-10 01:24:00 +00:00
int prevPort = sInstance - > mServerPort ;
2022-06-19 00:48:37 +00:00
while ( true ) {
if ( sInstance - > mKeyboard - > isThreadDone ( ) ) {
2022-07-10 01:24:00 +00:00
if ( ! sInstance - > mKeyboard - > isKeyboardCancelled ( ) )
sInstance - > mServerPort = : : atoi ( sInstance - > mKeyboard - > getResult ( ) ) ;
2022-06-19 00:48:37 +00:00
break ;
}
nn : : os : : YieldThread ( ) ; // allow other threads to run
}
2022-07-10 01:24:00 +00:00
2022-09-04 09:23:02 +00:00
bool isFirstConnect = prevPort ! = sInstance - > mServerPort ;
sInstance - > mSocket - > setIsFirstConn ( isFirstConnect ) ;
2022-07-10 01:24:00 +00:00
2022-09-04 09:23:02 +00:00
return isFirstConnect ;
2022-06-19 00:48:37 +00:00
}
2023-07-08 18:45:53 +00:00
void Client : : showUIMessage ( const char16_t * msg ) {
if ( ! sInstance ) {
return ;
}
sInstance - > mUIMessage - > setTxtMessageConfirm ( msg ) ;
al : : hidePane ( sInstance - > mUIMessage , " Page01 " ) ; // hide A button prompt
if ( ! sInstance - > mUIMessage - > mIsAlive ) {
sInstance - > mUIMessage - > appear ( ) ;
sInstance - > mUIMessage - > playLoop ( ) ;
}
al : : startAction ( sInstance - > mUIMessage , " Confirm " , " State " ) ;
}
void Client : : hideUIMessage ( ) {
if ( ! sInstance ) {
return ;
}
sInstance - > mUIMessage - > tryEnd ( ) ;
}
2022-06-16 21:33:18 +00:00
/**
2022-09-04 09:23:02 +00:00
* @ brief main thread function for read thread , responsible for processing packets from server
2022-06-16 21:33:18 +00:00
*
*/
void Client : : readFunc ( ) {
2022-06-25 00:46:58 +00:00
if ( waitForGameInit ) {
2022-06-16 21:33:18 +00:00
nn : : os : : YieldThread ( ) ; // sleep the thread for the first thing we do so that game init can finish
nn : : os : : SleepThread ( nn : : TimeSpan : : FromSeconds ( 2 ) ) ;
2022-06-25 00:46:58 +00:00
waitForGameInit = false ;
2022-06-16 21:33:18 +00:00
}
2022-09-04 09:23:02 +00:00
mConnectStatus - > appear ( ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
al : : startAction ( mConnectStatus , " Loop " , " Loop " ) ;
2022-06-16 21:33:18 +00:00
if ( ! startConnection ( ) ) {
2022-07-05 19:45:22 +00:00
Logger : : log ( " Failed to Connect to Server. \n " ) ;
2022-06-16 21:33:18 +00:00
nn : : os : : SleepThread ( nn : : TimeSpan : : FromNanoSeconds ( 250000000 ) ) ; // sleep active thread for 0.25 seconds
2022-09-04 09:23:02 +00:00
mConnectStatus - > end ( ) ;
2022-06-16 21:33:18 +00:00
return ;
}
nn : : os : : SleepThread ( nn : : TimeSpan : : FromNanoSeconds ( 500000000 ) ) ; // sleep for 0.5 seconds to let connection layout fully show (probably should find a better way to do this)
2022-09-04 09:23:02 +00:00
mConnectStatus - > end ( ) ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
while ( mIsConnectionActive ) {
2022-06-16 21:33:18 +00:00
2022-10-30 01:21:58 +00:00
Packet * curPacket = mSocket - > tryGetPacket ( ) ; // will block until a packet has been received, or socket disconnected
2022-09-04 09:23:02 +00:00
if ( curPacket ) {
switch ( curPacket - > mType )
{
case PacketType : : PLAYERINF :
updatePlayerInfo ( ( PlayerInf * ) curPacket ) ;
break ;
case PacketType : : GAMEINF :
updateGameInfo ( ( GameInf * ) curPacket ) ;
break ;
case PacketType : : HACKCAPINF :
updateHackCapInfo ( ( HackCapInf * ) curPacket ) ;
break ;
case PacketType : : CAPTUREINF :
updateCaptureInfo ( ( CaptureInf * ) curPacket ) ;
break ;
case PacketType : : PLAYERCON :
updatePlayerConnect ( ( PlayerConnect * ) curPacket ) ;
// Send relevant info packets when another client is connected
2022-09-05 01:21:43 +00:00
if ( lastGameInfPacket ! = emptyGameInfPacket ) {
// Assume game packets are empty from first connection
if ( lastGameInfPacket . mUserID ! = mUserID )
lastGameInfPacket . mUserID = mUserID ;
mSocket - > send ( & lastGameInfPacket ) ;
}
2022-09-04 09:23:02 +00:00
2022-09-05 01:21:43 +00:00
// No need to send player/costume packets if they're empty
if ( lastPlayerInfPacket . mUserID = = mUserID )
mSocket - > send ( & lastPlayerInfPacket ) ;
if ( lastCostumeInfPacket . mUserID = = mUserID )
mSocket - > send ( & lastCostumeInfPacket ) ;
2023-06-23 23:27:14 +00:00
if ( lastTagInfPacket . mUserID = = mUserID )
mSocket - > send ( & lastTagInfPacket ) ;
2023-06-24 00:42:54 +00:00
if ( lastCaptureInfPacket . mUserID = = mUserID )
mSocket - > send ( & lastCaptureInfPacket ) ;
2022-09-04 09:23:02 +00:00
break ;
case PacketType : : COSTUMEINF :
updateCostumeInfo ( ( CostumeInf * ) curPacket ) ;
break ;
case PacketType : : SHINECOLL :
updateShineInfo ( ( ShineCollect * ) curPacket ) ;
break ;
case PacketType : : PLAYERDC :
Logger : : log ( " Received Player Disconnect! \n " ) ;
curPacket - > mUserID . print ( ) ;
disconnectPlayer ( ( PlayerDC * ) curPacket ) ;
break ;
case PacketType : : TAGINF :
updateTagInfo ( ( TagInf * ) curPacket ) ;
break ;
case PacketType : : CHANGESTAGE :
sendToStage ( ( ChangeStagePacket * ) curPacket ) ;
break ;
case PacketType : : CLIENTINIT : {
InitPacket * initPacket = ( InitPacket * ) curPacket ;
Logger : : log ( " Server Max Player Size: %d \n " , initPacket - > maxPlayers ) ;
maxPuppets = initPacket - > maxPlayers - 1 ;
break ;
2022-06-16 21:33:18 +00:00
}
2022-10-23 23:37:47 +00:00
case PacketType : : UDPINIT : {
UdpInit * initPacket = ( UdpInit * ) curPacket ;
2022-10-26 10:31:32 +00:00
Logger : : log ( " Received udp init packet from server \n " ) ;
2022-10-23 23:37:47 +00:00
sInstance - > mSocket - > setPeerUdpPort ( initPacket - > port ) ;
sendUdpHolePunch ( ) ;
sendUdpInit ( ) ;
break ;
}
case PacketType : : HOLEPUNCH :
sendUdpHolePunch ( ) ;
break ;
2022-09-04 09:23:02 +00:00
default :
Logger : : log ( " Discarding Unknown Packet Type. \n " ) ;
break ;
2022-06-16 21:33:18 +00:00
}
2022-09-04 09:23:02 +00:00
mHeap - > free ( curPacket ) ;
2022-06-16 21:33:18 +00:00
2022-10-30 00:17:38 +00:00
} else { // if false, socket has errored or disconnected, so restart the connection
Logger : : log ( " Client Socket Encountered an Error, restarting connection! Errno: 0x%x \n " , mSocket - > socket_errno ) ;
2022-06-16 21:33:18 +00:00
}
}
2022-07-05 19:45:22 +00:00
Logger : : log ( " Client Read Thread ending. \n " ) ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief sends player info packet to current server
*
* @ param player pointer to current player class , used to get translation , animation , and capture data
*/
2022-08-10 21:11:52 +00:00
void Client : : sendPlayerInfPacket ( const PlayerActorBase * playerBase , bool isYukimaru ) {
2022-06-16 21:33:18 +00:00
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-08-10 21:11:52 +00:00
if ( ! playerBase ) {
2022-06-16 21:33:18 +00:00
Logger : : log ( " Error: Null Player Reference \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
PlayerInf * packet = new PlayerInf ( ) ;
packet - > mUserID = sInstance - > mUserID ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
packet - > playerPos = al : : getTrans ( playerBase ) ;
al : : calcQuat ( & packet - > playerRot ,
2022-08-10 21:11:52 +00:00
playerBase ) ; // calculate rotation based off pose instead of using quat rotation
2022-06-16 21:33:18 +00:00
2022-08-10 21:11:52 +00:00
if ( ! isYukimaru ) {
PlayerActorHakoniwa * player = ( PlayerActorHakoniwa * ) playerBase ;
2022-06-16 21:33:18 +00:00
2022-08-10 21:11:52 +00:00
for ( size_t i = 0 ; i < 6 ; i + + )
{
2022-09-04 09:23:02 +00:00
packet - > animBlendWeights [ i ] = player - > mPlayerAnimator - > getBlendWeight ( i ) ;
2022-08-10 21:11:52 +00:00
}
2022-06-16 21:33:18 +00:00
2022-08-10 21:11:52 +00:00
const char * hackName = player - > mHackKeeper - > getCurrentHackName ( ) ;
2022-06-16 21:33:18 +00:00
2022-08-10 21:11:52 +00:00
if ( hackName ! = nullptr ) {
2022-06-16 21:33:18 +00:00
2022-08-10 21:11:52 +00:00
sInstance - > isClientCaptured = true ;
2022-06-16 21:33:18 +00:00
2022-08-10 21:11:52 +00:00
const char * actName = al : : getActionName ( player - > mHackKeeper - > currentHackActor ) ;
if ( actName ) {
2022-09-04 09:23:02 +00:00
packet - > actName = PlayerAnims : : FindType ( actName ) ;
packet - > subActName = PlayerAnims : : Type : : Unknown ;
2022-08-10 21:11:52 +00:00
//strcpy(packet.actName, actName);
} else {
2022-09-04 09:23:02 +00:00
packet - > actName = PlayerAnims : : Type : : Unknown ;
packet - > subActName = PlayerAnims : : Type : : Unknown ;
2022-08-10 21:11:52 +00:00
}
2022-06-16 21:33:18 +00:00
} else {
2022-09-04 09:23:02 +00:00
packet - > actName = PlayerAnims : : FindType ( player - > mPlayerAnimator - > mAnimFrameCtrl - > getActionName ( ) ) ;
packet - > subActName = PlayerAnims : : FindType ( player - > mPlayerAnimator - > curSubAnim . cstr ( ) ) ;
2022-08-10 21:11:52 +00:00
sInstance - > isClientCaptured = false ;
2022-06-16 21:33:18 +00:00
}
2022-08-10 21:11:52 +00:00
2022-06-16 21:33:18 +00:00
} else {
2022-08-10 21:11:52 +00:00
// TODO: implement YukimaruRacePlayer syncing
for ( size_t i = 0 ; i < 6 ; i + + )
{
2022-09-04 09:23:02 +00:00
packet - > animBlendWeights [ i ] = 0 ;
2022-08-10 21:11:52 +00:00
}
2022-06-16 21:33:18 +00:00
sInstance - > isClientCaptured = false ;
2022-08-10 21:11:52 +00:00
2022-09-04 09:23:02 +00:00
packet - > actName = PlayerAnims : : Type : : Unknown ;
packet - > subActName = PlayerAnims : : Type : : Unknown ;
2022-06-16 21:33:18 +00:00
}
2022-09-04 09:23:02 +00:00
if ( sInstance - > lastPlayerInfPacket ! = * packet ) {
sInstance - > lastPlayerInfPacket = * packet ; // deref packet and store in client memory
sInstance - > mSocket - > queuePacket ( packet ) ;
} else {
sInstance - > mHeap - > free ( packet ) ; // free packet if we're not using it
2022-06-16 21:33:18 +00:00
}
}
2022-09-05 01:21:43 +00:00
2022-06-16 21:33:18 +00:00
/**
* @ brief sends info related to player ' s cap actor to server
*
* @ param hackCap pointer to cap actor , used to get translation , animation , and state info
*/
void Client : : sendHackCapInfPacket ( const HackCap * hackCap ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-06-16 21:33:18 +00:00
bool isFlying = hackCap - > isFlying ( ) ;
// if cap is in flying state, send packet as often as this function is called
if ( isFlying ) {
2022-09-04 09:23:02 +00:00
HackCapInf * packet = new HackCapInf ( ) ;
packet - > mUserID = sInstance - > mUserID ;
packet - > capPos = al : : getTrans ( hackCap ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
packet - > isCapVisible = isFlying ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
packet - > capQuat . x = hackCap - > mJointKeeper - > mJointRot . x ;
packet - > capQuat . y = hackCap - > mJointKeeper - > mJointRot . y ;
packet - > capQuat . z = hackCap - > mJointKeeper - > mJointRot . z ;
packet - > capQuat . w = hackCap - > mJointKeeper - > mSkew ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
strcpy ( packet - > capAnim , al : : getActionName ( hackCap ) ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
sInstance - > mSocket - > queuePacket ( packet ) ;
2022-06-16 21:33:18 +00:00
sInstance - > isSentHackInf = true ;
} else if ( sInstance - > isSentHackInf ) { // if cap is not flying, check to see if previous function call sent a packet, and if so, send one final packet resetting cap data.
2022-09-04 09:23:02 +00:00
HackCapInf * packet = new HackCapInf ( ) ;
packet - > mUserID = sInstance - > mUserID ;
packet - > isCapVisible = false ;
packet - > capPos = sead : : Vector3f : : zero ;
packet - > capQuat = sead : : Quatf : : unit ;
sInstance - > mSocket - > queuePacket ( packet ) ;
2022-06-16 21:33:18 +00:00
sInstance - > isSentHackInf = false ;
}
}
/**
* @ brief
2022-08-10 21:11:52 +00:00
* Sends both stage info and player 2 D info to the server .
2022-06-16 21:33:18 +00:00
* @ param player
* @ param holder
*/
void Client : : sendGameInfPacket ( const PlayerActorHakoniwa * player , GameDataHolderAccessor holder ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
GameInf * packet = new GameInf ( ) ;
packet - > mUserID = sInstance - > mUserID ;
2022-06-16 21:33:18 +00:00
if ( player ) {
2022-09-04 09:23:02 +00:00
packet - > is2D = player - > mDimKeeper - > is2DModel ;
2022-06-16 21:33:18 +00:00
} else {
2022-09-04 09:23:02 +00:00
packet - > is2D = false ;
2022-06-16 21:33:18 +00:00
}
2022-09-04 09:23:02 +00:00
packet - > scenarioNo = holder . mData - > mGameDataFile - > getScenarioNo ( ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
strcpy ( packet - > stageName , GameDataFunction : : getCurrentStageName ( holder ) ) ;
2022-06-16 21:33:18 +00:00
2022-09-05 01:21:43 +00:00
if ( * packet ! = sInstance - > lastGameInfPacket & & * packet ! = sInstance - > emptyGameInfPacket ) {
2022-09-04 09:23:02 +00:00
sInstance - > lastGameInfPacket = * packet ;
sInstance - > mSocket - > queuePacket ( packet ) ;
} else {
sInstance - > mHeap - > free ( packet ) ; // free packet if we're not using it
2022-06-16 21:33:18 +00:00
}
}
2022-09-05 01:21:43 +00:00
2022-06-16 21:33:18 +00:00
/**
* @ brief
2022-08-10 21:11:52 +00:00
* Sends only stage info to the server .
2022-06-16 21:33:18 +00:00
* @ param holder
*/
void Client : : sendGameInfPacket ( GameDataHolderAccessor holder ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
GameInf * packet = new GameInf ( ) ;
packet - > mUserID = sInstance - > mUserID ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
packet - > is2D = false ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
packet - > scenarioNo = holder . mData - > mGameDataFile - > getScenarioNo ( ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
strcpy ( packet - > stageName , GameDataFunction : : getCurrentStageName ( holder ) ) ;
2022-06-16 21:33:18 +00:00
2022-09-05 01:21:43 +00:00
if ( * packet ! = sInstance - > emptyGameInfPacket ) {
sInstance - > lastGameInfPacket = * packet ;
sInstance - > mSocket - > queuePacket ( packet ) ;
}
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
*/
void Client : : sendTagInfPacket ( ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-08-07 21:42:56 +00:00
HideAndSeekMode * hsMode = GameModeManager : : instance ( ) - > getMode < HideAndSeekMode > ( ) ;
if ( ! GameModeManager : : instance ( ) - > isMode ( GameMode : : HIDEANDSEEK ) ) {
2022-06-16 21:33:18 +00:00
Logger : : log ( " State is not Hide and Seek! \n " ) ;
return ;
}
2022-08-07 21:42:56 +00:00
HideAndSeekInfo * curInfo = GameModeManager : : instance ( ) - > getInfo < HideAndSeekInfo > ( ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
TagInf * packet = new TagInf ( ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
packet - > mUserID = sInstance - > mUserID ;
2022-06-16 21:33:18 +00:00
2023-06-23 02:18:41 +00:00
packet - > isIt = hsMode - > isPlayerIt ( ) & & hsMode - > isModeActive ( ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
packet - > minutes = curInfo - > mHidingTime . mMinutes ;
packet - > seconds = curInfo - > mHidingTime . mSeconds ;
packet - > updateType = static_cast < TagUpdateType > ( TagUpdateType : : STATE | TagUpdateType : : TIME ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
sInstance - > mSocket - > queuePacket ( packet ) ;
2023-06-23 23:27:14 +00:00
sInstance - > lastTagInfPacket = * packet ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
* @ param body
* @ param cap
*/
void Client : : sendCostumeInfPacket ( const char * body , const char * cap ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
2022-09-05 01:21:43 +00:00
if ( ! strcmp ( body , " " ) & & ! strcmp ( cap , " " ) ) { return ; }
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
CostumeInf * packet = new CostumeInf ( body , cap ) ;
packet - > mUserID = sInstance - > mUserID ;
sInstance - > lastCostumeInfPacket = * packet ;
sInstance - > mSocket - > queuePacket ( packet ) ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
* @ param player
*/
void Client : : sendCaptureInfPacket ( const PlayerActorHakoniwa * player ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-06-16 21:33:18 +00:00
if ( sInstance - > isClientCaptured & & ! sInstance - > isSentCaptureInf ) {
2022-09-04 09:23:02 +00:00
CaptureInf * packet = new CaptureInf ( ) ;
packet - > mUserID = sInstance - > mUserID ;
strcpy ( packet - > hackName , tryConvertName ( player - > mHackKeeper - > getCurrentHackName ( ) ) ) ;
sInstance - > mSocket - > queuePacket ( packet ) ;
2023-06-24 00:42:54 +00:00
sInstance - > lastCaptureInfPacket = * packet ;
2022-06-16 21:33:18 +00:00
sInstance - > isSentCaptureInf = true ;
} else if ( ! sInstance - > isClientCaptured & & sInstance - > isSentCaptureInf ) {
2022-09-04 09:23:02 +00:00
CaptureInf * packet = new CaptureInf ( ) ;
packet - > mUserID = sInstance - > mUserID ;
strcpy ( packet - > hackName , " " ) ;
sInstance - > mSocket - > queuePacket ( packet ) ;
2023-06-24 00:42:54 +00:00
sInstance - > lastCaptureInfPacket = * packet ;
2022-06-16 21:33:18 +00:00
sInstance - > isSentCaptureInf = false ;
}
}
2022-09-05 01:21:43 +00:00
/**
* @ brief
*/
void Client : : resendInitPackets ( ) {
// CostumeInfPacket
if ( lastCostumeInfPacket . mUserID = = mUserID ) {
mSocket - > queuePacket ( & lastCostumeInfPacket ) ;
}
// GameInfPacket
if ( lastGameInfPacket ! = emptyGameInfPacket ) {
mSocket - > queuePacket ( & lastGameInfPacket ) ;
}
2023-06-23 23:27:14 +00:00
// TagInfPacket
if ( lastTagInfPacket . mUserID = = mUserID ) {
mSocket - > queuePacket ( & lastTagInfPacket ) ;
}
2023-06-24 00:42:54 +00:00
// CaptureInfPacket
if ( lastCaptureInfPacket . mUserID = = mUserID ) {
mSocket - > queuePacket ( & lastCaptureInfPacket ) ;
}
2022-09-05 01:21:43 +00:00
}
2022-06-16 21:33:18 +00:00
/**
* @ brief
*
* @ param shineID
*/
void Client : : sendShineCollectPacket ( int shineID ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-09-04 09:23:02 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
2022-06-16 21:33:18 +00:00
if ( sInstance - > lastCollectedShine ! = shineID ) {
2022-09-04 09:23:02 +00:00
ShineCollect * packet = new ShineCollect ( ) ;
packet - > mUserID = sInstance - > mUserID ;
packet - > shineId = shineID ;
2022-06-16 21:33:18 +00:00
sInstance - > lastCollectedShine = shineID ;
2022-09-04 09:23:02 +00:00
sInstance - > mSocket - > queuePacket ( packet ) ;
2022-06-16 21:33:18 +00:00
}
}
/**
* @ brief
*
* @ param packet
*/
void Client : : updatePlayerInfo ( PlayerInf * packet ) {
2022-07-05 19:45:22 +00:00
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , false ) ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( ! curInfo ) {
return ;
}
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( ! curInfo - > isConnected ) {
curInfo - > isConnected = true ;
}
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
curInfo - > playerPos = packet - > playerPos ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
// check if rotation is larger than zero and less than or equal to 1
if ( abs ( packet - > playerRot . x ) > 0.f | | abs ( packet - > playerRot . y ) > 0.f | | abs ( packet - > playerRot . z ) > 0.f | | abs ( packet - > playerRot . w ) > 0.f ) {
if ( abs ( packet - > playerRot . x ) < = 1.f | | abs ( packet - > playerRot . y ) < = 1.f | | abs ( packet - > playerRot . z ) < = 1.f | | abs ( packet - > playerRot . w ) < = 1.f ) {
curInfo - > playerRot = packet - > playerRot ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
}
2022-06-16 21:33:18 +00:00
if ( packet - > actName ! = PlayerAnims : : Type : : Unknown ) {
strcpy ( curInfo - > curAnimStr , PlayerAnims : : FindStr ( packet - > actName ) ) ;
2022-06-25 00:55:34 +00:00
if ( curInfo - > curAnimStr [ 0 ] = = ' \0 ' )
Logger : : log ( " [ERROR] %s: actName was out of bounds: %d \n " , __func__ , packet - > actName ) ;
2022-06-16 21:33:18 +00:00
} else {
strcpy ( curInfo - > curAnimStr , " Wait " ) ;
}
if ( packet - > subActName ! = PlayerAnims : : Type : : Unknown ) {
strcpy ( curInfo - > curSubAnimStr , PlayerAnims : : FindStr ( packet - > subActName ) ) ;
2022-06-25 00:55:34 +00:00
if ( curInfo - > curSubAnimStr [ 0 ] = = ' \0 ' )
Logger : : log ( " [ERROR] %s: subActName was out of bounds: %d \n " , __func__ , packet - > subActName ) ;
2022-06-16 21:33:18 +00:00
} else {
strcpy ( curInfo - > curSubAnimStr , " " ) ;
}
2022-07-05 19:45:22 +00:00
curInfo - > curAnim = packet - > actName ;
curInfo - > curSubAnim = packet - > subActName ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
for ( size_t i = 0 ; i < 6 ; i + + )
{
// weights can only be between 0 and 1
if ( packet - > animBlendWeights [ i ] > = 0.f & & packet - > animBlendWeights [ i ] < = 1.f ) {
curInfo - > blendWeights [ i ] = packet - > animBlendWeights [ i ] ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
}
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
//TEMP
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( ! curInfo - > isCapThrow ) {
curInfo - > capPos = packet - > playerPos ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
* @ param packet
*/
void Client : : updateHackCapInfo ( HackCapInf * packet ) {
2022-07-05 19:45:22 +00:00
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , false ) ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( curInfo ) {
curInfo - > capPos = packet - > capPos ;
curInfo - > capRot = packet - > capQuat ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
curInfo - > isCapThrow = packet - > isCapVisible ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
strcpy ( curInfo - > capAnim , packet - > capAnim ) ;
2022-06-16 21:33:18 +00:00
}
}
/**
* @ brief
*
* @ param packet
*/
2022-07-05 19:45:22 +00:00
void Client : : updateCaptureInfo ( CaptureInf * packet ) {
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , false ) ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( ! curInfo ) {
return ;
}
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
curInfo - > isCaptured = strlen ( packet - > hackName ) > 0 ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( curInfo - > isCaptured ) {
strcpy ( curInfo - > curHack , packet - > hackName ) ;
2022-06-16 21:33:18 +00:00
}
}
/**
* @ brief
*
* @ param packet
*/
void Client : : updateCostumeInfo ( CostumeInf * packet ) {
2022-07-05 19:45:22 +00:00
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , false ) ;
if ( ! curInfo ) {
return ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
strcpy ( curInfo - > costumeBody , packet - > bodyModel ) ;
strcpy ( curInfo - > costumeHead , packet - > capModel ) ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
* @ param packet
*/
void Client : : updateShineInfo ( ShineCollect * packet ) {
if ( collectedShineCount < curCollectedShines . size ( ) - 1 ) {
curCollectedShines [ collectedShineCount ] = packet - > shineId ;
collectedShineCount + + ;
}
}
/**
* @ brief
*
* @ param packet
*/
2022-07-05 19:45:22 +00:00
void Client : : updatePlayerConnect ( PlayerConnect * packet ) {
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , true ) ;
if ( ! curInfo ) {
return ;
}
if ( curInfo - > isConnected ) {
Logger : : log ( " Info is already being used by another connected player! \n " ) ;
packet - > mUserID . print ( " Connection ID " ) ;
curInfo - > playerID . print ( " Target Info " ) ;
} else {
packet - > mUserID . print ( " Player Connected! ID " ) ;
2022-06-16 21:33:18 +00:00
curInfo - > playerID = packet - > mUserID ;
curInfo - > isConnected = true ;
strcpy ( curInfo - > puppetName , packet - > clientName ) ;
2022-07-05 19:45:22 +00:00
mConnectCount + + ;
2022-06-16 21:33:18 +00:00
}
}
2022-09-05 01:21:43 +00:00
2022-06-16 21:33:18 +00:00
/**
* @ brief
*
* @ param packet
*/
void Client : : updateGameInfo ( GameInf * packet ) {
2022-07-05 19:45:22 +00:00
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , false ) ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( ! curInfo ) {
return ;
}
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( curInfo - > isConnected ) {
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
curInfo - > scenarioNo = packet - > scenarioNo ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( strcmp ( packet - > stageName , " " ) ! = 0 & & strlen ( packet - > stageName ) > 3 ) {
strcpy ( curInfo - > stageName , packet - > stageName ) ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
curInfo - > is2D = packet - > is2D ;
2022-06-16 21:33:18 +00:00
}
}
/**
* @ brief
*
* @ param packet
*/
void Client : : updateTagInfo ( TagInf * packet ) {
// if the packet is for our player, edit info for our player
2022-08-07 21:42:56 +00:00
if ( packet - > mUserID = = mUserID & & GameModeManager : : instance ( ) - > isMode ( GameMode : : HIDEANDSEEK ) ) {
2022-06-16 21:33:18 +00:00
2022-08-07 21:42:56 +00:00
HideAndSeekMode * mMode = GameModeManager : : instance ( ) - > getMode < HideAndSeekMode > ( ) ;
HideAndSeekInfo * curInfo = GameModeManager : : instance ( ) - > getInfo < HideAndSeekInfo > ( ) ;
2022-06-16 21:33:18 +00:00
if ( packet - > updateType & TagUpdateType : : STATE ) {
mMode - > setPlayerTagState ( packet - > isIt ) ;
}
if ( packet - > updateType & TagUpdateType : : TIME ) {
curInfo - > mHidingTime . mSeconds = packet - > seconds ;
curInfo - > mHidingTime . mMinutes = packet - > minutes ;
}
return ;
}
2022-07-05 19:45:22 +00:00
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , false ) ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
if ( ! curInfo ) {
return ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
curInfo - > isIt = packet - > isIt ;
curInfo - > seconds = packet - > seconds ;
curInfo - > minutes = packet - > minutes ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
* @ param packet
*/
void Client : : sendToStage ( ChangeStagePacket * packet ) {
if ( mSceneInfo & & mSceneInfo - > mSceneObjHolder ) {
GameDataHolderAccessor accessor ( mSceneInfo - > mSceneObjHolder ) ;
Logger : : log ( " Sending Player to %s at Entrance %s in Scenario %d \n " , packet - > changeStage ,
packet - > changeID , packet - > scenarioNo ) ;
ChangeStageInfo info ( accessor . mData , packet - > changeID , packet - > changeStage , false , packet - > scenarioNo , static_cast < ChangeStageInfo : : SubScenarioType > ( packet - > subScenarioType ) ) ;
GameDataFunction : : tryChangeNextStage ( accessor , & info ) ;
}
}
2022-10-23 23:37:47 +00:00
/**
* @ brief
* Send a udp holepunch packet to the server
*/
void Client : : sendUdpHolePunch ( ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
HolePunch * packet = new HolePunch ( ) ;
packet - > mUserID = sInstance - > mUserID ;
sInstance - > mSocket - > queuePacket ( packet ) ;
}
/**
* @ brief
* Send a udp init packet to server
*/
void Client : : sendUdpInit ( ) {
if ( ! sInstance ) {
Logger : : log ( " Static Instance is Null! \n " ) ;
return ;
}
2022-06-16 21:33:18 +00:00
2022-10-23 23:37:47 +00:00
sead : : ScopedCurrentHeapSetter setter ( sInstance - > mHeap ) ;
UdpInit * packet = new UdpInit ( ) ;
packet - > mUserID = sInstance - > mUserID ;
packet - > port = sInstance - > mSocket - > getLocalUdpPort ( ) ;
sInstance - > mSocket - > queuePacket ( packet ) ;
}
2022-06-16 21:33:18 +00:00
/**
* @ brief
*
* @ param packet
*/
void Client : : disconnectPlayer ( PlayerDC * packet ) {
2022-07-05 19:45:22 +00:00
PuppetInfo * curInfo = findPuppetInfo ( packet - > mUserID , false ) ;
2022-06-16 21:33:18 +00:00
2022-07-08 05:36:29 +00:00
if ( ! curInfo | | ! curInfo - > isConnected ) {
2022-07-05 19:45:22 +00:00
return ;
}
curInfo - > isConnected = false ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
curInfo - > scenarioNo = - 1 ;
strcpy ( curInfo - > stageName , " " ) ;
curInfo - > isInSameStage = false ;
2022-06-16 21:33:18 +00:00
2022-07-05 19:45:22 +00:00
mConnectCount - - ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
* @ param shineId
* @ return true
* @ return false
*/
bool Client : : isShineCollected ( int shineId ) {
for ( size_t i = 0 ; i < curCollectedShines . size ( ) ; i + + )
{
if ( curCollectedShines [ i ] > = 0 ) {
if ( curCollectedShines [ i ] = = shineId ) {
return true ;
}
}
}
return false ;
}
/**
* @ brief
*
* @ param id
* @ return int
*/
2022-07-05 19:45:22 +00:00
PuppetInfo * Client : : findPuppetInfo ( const nn : : account : : Uid & id , bool isFindAvailable ) {
PuppetInfo * firstAvailable = nullptr ;
2022-07-08 22:09:04 +00:00
for ( size_t i = 0 ; i < getMaxPlayerCount ( ) - 1 ; i + + ) {
2022-07-05 19:45:22 +00:00
PuppetInfo * curInfo = mPuppetInfoArr [ i ] ;
if ( curInfo - > playerID = = id ) {
return curInfo ;
} else if ( isFindAvailable & & ! firstAvailable & & ! curInfo - > isConnected ) {
firstAvailable = curInfo ;
2022-06-16 21:33:18 +00:00
}
}
2022-07-05 19:45:22 +00:00
if ( ! firstAvailable ) {
Logger : : log ( " Unable to find Assigned Puppet for Player! \n " ) ;
id . print ( " User ID " ) ;
2022-06-16 21:33:18 +00:00
}
2022-07-05 19:45:22 +00:00
return firstAvailable ;
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
* @ param holder
*/
void Client : : setStageInfo ( GameDataHolderAccessor holder ) {
if ( sInstance ) {
sInstance - > mStageName = GameDataFunction : : getCurrentStageName ( holder ) ;
sInstance - > mScenario = holder . mData - > mGameDataFile - > getScenarioNo ( ) ; //holder.mData->mGameDataFile->getMainScenarioNoCurrent();
2022-07-08 08:02:28 +00:00
sInstance - > mPuppetHolder - > setStageInfo ( sInstance - > mStageName . cstr ( ) , sInstance - > mScenario ) ;
2022-06-16 21:33:18 +00:00
}
}
/**
* @ brief
*
* @ param puppet
* @ return true
* @ return false
*/
bool Client : : tryAddPuppet ( PuppetActor * puppet ) {
2022-07-08 08:02:28 +00:00
if ( sInstance ) {
return sInstance - > mPuppetHolder - > tryRegisterPuppet ( puppet ) ;
2022-06-16 21:33:18 +00:00
} else {
return false ;
}
}
/**
* @ brief
*
* @ param puppet
* @ return true
* @ return false
*/
bool Client : : tryAddDebugPuppet ( PuppetActor * puppet ) {
2022-07-08 08:02:28 +00:00
if ( sInstance ) {
return sInstance - > mPuppetHolder - > tryRegisterDebugPuppet ( puppet ) ;
2022-06-16 21:33:18 +00:00
} else {
return false ;
}
}
/**
* @ brief
*
* @ param idx
* @ return PuppetActor *
*/
PuppetActor * Client : : getPuppet ( int idx ) {
2022-07-08 08:02:28 +00:00
if ( sInstance ) {
return sInstance - > mPuppetHolder - > getPuppetActor ( idx ) ;
2022-06-16 21:33:18 +00:00
} else {
return nullptr ;
}
}
/**
* @ brief
*
* @ return PuppetInfo *
*/
PuppetInfo * Client : : getLatestInfo ( ) {
2022-07-08 08:02:28 +00:00
if ( sInstance ) {
return Client : : getPuppetInfo ( sInstance - > mPuppetHolder - > getSize ( ) - 1 ) ;
2022-06-16 21:33:18 +00:00
} else {
return nullptr ;
}
}
/**
* @ brief
*
* @ param idx
* @ return PuppetInfo *
*/
PuppetInfo * Client : : getPuppetInfo ( int idx ) {
2022-07-08 08:02:28 +00:00
if ( sInstance ) {
2022-06-16 21:33:18 +00:00
// unsafe get
2022-07-08 08:02:28 +00:00
PuppetInfo * curInfo = sInstance - > mPuppetInfoArr [ idx ] ;
2022-06-16 21:33:18 +00:00
if ( ! curInfo ) {
Logger : : log ( " Attempting to Access Puppet Out of Bounds! Value: %d \n " , idx ) ;
return nullptr ;
}
return curInfo ;
} else {
return nullptr ;
}
}
/**
* @ brief
*
*/
void Client : : resetCollectedShines ( ) {
collectedShineCount = 0 ;
curCollectedShines . fill ( - 1 ) ;
}
/**
* @ brief
*
* @ param shineId
*/
void Client : : removeShine ( int shineId ) {
for ( size_t i = 0 ; i < curCollectedShines . size ( ) ; i + + )
{
if ( curCollectedShines [ i ] = = shineId ) {
curCollectedShines [ i ] = - 1 ;
collectedShineCount - - ;
}
}
}
/**
* @ brief
*
* @ return true
* @ return false
*/
bool Client : : isNeedUpdateShines ( ) {
return sInstance ? sInstance - > collectedShineCount > 0 : false ;
}
/**
* @ brief
*
*/
void Client : : updateShines ( ) {
if ( ! sInstance ) {
Logger : : log ( " Client Null! \n " ) ;
return ;
}
// skip shine sync if player is in cap kingdom scenario zero (very start of the game)
if ( sInstance - > mStageName = = " CapWorldHomeStage " & & ( sInstance - > mScenario = = 0 | | sInstance - > mScenario = = 1 ) ) {
return ;
}
GameDataHolderAccessor accessor ( sInstance - > mCurStageScene ) ;
for ( size_t i = 0 ; i < sInstance - > getCollectedShinesCount ( ) ; i + + )
{
int shineID = sInstance - > getShineID ( i ) ;
2022-09-04 09:23:02 +00:00
if ( shineID < 0 ) continue ;
Logger : : log ( " Shine UID: %d \n " , shineID ) ;
GameDataFile : : HintInfo * shineInfo = CustomGameDataFunction : : getHintInfoByUniqueID ( accessor , shineID ) ;
2022-06-16 21:33:18 +00:00
2022-09-04 09:23:02 +00:00
if ( shineInfo ) {
if ( ! GameDataFunction : : isGotShine ( accessor , shineInfo - > mStageName . cstr ( ) , shineInfo - > mObjId . cstr ( ) ) ) {
Shine * stageShine = findStageShine ( shineID ) ;
2022-06-16 21:33:18 +00:00
if ( stageShine ) {
if ( al : : isDead ( stageShine ) ) {
stageShine - > makeActorAlive ( ) ;
}
stageShine - > getDirect ( ) ;
stageShine - > onSwitchGet ( ) ;
}
2022-09-04 09:23:02 +00:00
accessor . mData - > mGameDataFile - > setGotShine ( shineInfo ) ;
2022-06-16 21:33:18 +00:00
}
}
}
sInstance - > resetCollectedShines ( ) ;
2022-08-10 21:11:52 +00:00
sInstance - > mCurStageScene - > mSceneLayout - > startShineCountAnim ( false ) ;
2022-09-04 09:23:02 +00:00
sInstance - > mCurStageScene - > mSceneLayout - > updateCounterParts ( ) ; // updates shine chip layout to (maybe) prevent softlocks
2022-06-16 21:33:18 +00:00
}
/**
* @ brief
*
*/
2022-09-04 09:23:02 +00:00
void Client : : update ( ) {
if ( sInstance ) {
2022-06-16 21:33:18 +00:00
sInstance - > mPuppetHolder - > update ( ) ;
2022-09-04 09:23:02 +00:00
if ( isNeedUpdateShines ( ) ) {
updateShines ( ) ;
}
2022-08-07 21:42:56 +00:00
GameModeManager : : instance ( ) - > update ( ) ;
2022-06-16 21:33:18 +00:00
}
}
/**
* @ brief
*
*/
void Client : : clearArrays ( ) {
if ( sInstance ) {
sInstance - > mPuppetHolder - > clearPuppets ( ) ;
sInstance - > mShineArray . clear ( ) ;
}
}
/**
* @ brief
*
* @ return PuppetInfo *
*/
PuppetInfo * Client : : getDebugPuppetInfo ( ) {
2022-07-08 08:02:28 +00:00
if ( sInstance ) {
return & sInstance - > mDebugPuppetInfo ;
2022-06-16 21:33:18 +00:00
} else {
return nullptr ;
}
}
/**
* @ brief
*
* @ return PuppetActor *
*/
PuppetActor * Client : : getDebugPuppet ( ) {
2022-07-08 08:02:28 +00:00
if ( sInstance ) {
return sInstance - > mPuppetHolder - > getDebugPuppet ( ) ;
2022-06-16 21:33:18 +00:00
} else {
return nullptr ;
}
}
2022-06-19 00:48:37 +00:00
/**
* @ brief
*
* @ return Keyboard *
*/
Keyboard * Client : : getKeyboard ( ) {
if ( sInstance ) {
return sInstance - > mKeyboard ;
}
return nullptr ;
}
2022-06-16 21:33:18 +00:00
/**
* @ brief
*
* @ return const char *
*/
const char * Client : : getCurrentIP ( ) {
if ( sInstance ) {
return sInstance - > mServerIP . cstr ( ) ;
}
return nullptr ;
}
2022-06-19 04:42:59 +00:00
/**
* @ brief
*
* @ return const int
*/
const int Client : : getCurrentPort ( ) {
if ( sInstance ) {
return sInstance - > mServerPort ;
}
return - 1 ;
}
2022-06-16 21:33:18 +00:00
/**
* @ brief sets server IP to supplied string , used specifically for loading IP from the save file .
*
* @ param ip
*/
void Client : : setLastUsedIP ( const char * ip ) {
if ( sInstance ) {
sInstance - > mServerIP = ip ;
}
}
2022-06-19 04:42:59 +00:00
/**
* @ brief sets server port to supplied string , used specifically for loading port from the save file .
*
* @ param port
*/
void Client : : setLastUsedPort ( const int port ) {
if ( sInstance ) {
sInstance - > mServerPort = port ;
}
}
2022-06-16 21:33:18 +00:00
/**
* @ brief creates new scene info and copies supplied info to the new info , as well as stores a const ptr to the current stage scene .
*
* @ param initInfo
* @ param stageScene
*/
void Client : : setSceneInfo ( const al : : ActorInitInfo & initInfo , const StageScene * stageScene ) {
if ( ! sInstance ) {
Logger : : log ( " Client Null! \n " ) ;
return ;
}
sInstance - > mSceneInfo = new al : : ActorSceneInfo ( ) ;
memcpy ( sInstance - > mSceneInfo , & initInfo . mActorSceneInfo , sizeof ( al : : ActorSceneInfo ) ) ;
sInstance - > mCurStageScene = stageScene ;
}
/**
* @ brief stores shine pointer supplied into a ptr array if space is available , and shine is not collected .
*
* @ param shine
* @ return true if shine was able to be successfully stored
* @ return false if shine is already collected , or ptr array is full
*/
bool Client : : tryRegisterShine ( Shine * shine ) {
if ( sInstance ) {
if ( ! sInstance - > mShineArray . isFull ( ) ) {
if ( ! shine - > isGot ( ) ) {
sInstance - > mShineArray . pushBack ( shine ) ;
return true ;
}
}
}
return false ;
}
/**
* @ brief finds the actor pointer stored in the shine ptr array based off shine ID
*
* @ param shineID Unique ID used for shine actor
* @ return Shine * if shine ptr array contains actor with supplied shine ID .
*/
Shine * Client : : findStageShine ( int shineID ) {
if ( sInstance ) {
for ( int i = 0 ; i < sInstance - > mShineArray . size ( ) ; i + + ) {
2022-09-04 09:23:02 +00:00
2022-06-16 21:33:18 +00:00
Shine * curShine = sInstance - > mShineArray [ i ] ;
2022-09-04 09:23:02 +00:00
2022-06-16 21:33:18 +00:00
if ( curShine ) {
2022-09-04 09:23:02 +00:00
auto hintInfo =
CustomGameDataFunction : : getHintInfoByIndex ( curShine , curShine - > mShineIdx ) ;
if ( hintInfo - > mUniqueID = = shineID ) {
2022-06-16 21:33:18 +00:00
return curShine ;
}
}
}
}
return nullptr ;
}