only save ip/port changes if actually changed, reconnect fixes

This commit is contained in:
CraftyBoss 2022-07-09 18:24:00 -07:00
parent 4f2bb984f2
commit 3c4a20a6d4
11 changed files with 205 additions and 103 deletions

View file

@ -25,6 +25,8 @@ class Keyboard {
return nullptr;
};
bool isKeyboardCancelled() const { return mIsCancelled; }
bool isThreadDone() { return mThread->isDone(); }
void setHeaderText(const char16_t* text) { mHeaderText = text; }
@ -35,14 +37,14 @@ class Keyboard {
al::AsyncFunctorThread* mThread;
nn::swkbd::String mResultString;
bool mIsDoneKeyboard;
sead::FixedSafeString<0x10> mInitialText;
KeyboardSetup mSetupFunc;
const char16_t *mHeaderText = u"Enter Server IP Here!";
const char16_t* mSubText = u"Must be a Valid Address.";
bool mIsCancelled = false;
char* mWorkBuf;
int mWorkBufSize;
char* mTextCheckBuf;

View file

@ -16,7 +16,7 @@ class SocketBase {
const char *getStateChar();
u8 getLogState();
s32 getSocket();
s32 getFd();
void set_sock_flags(int flags);

View file

@ -45,6 +45,7 @@ class StageSceneStateServerConfig : public al::HostStateBase<al::Scene>, public
void exeGamemodeConfig();
void exeGamemodeSelect();
void exeSaveData();
void exeConnectError();
void endSubMenu();
@ -84,4 +85,5 @@ namespace {
NERVE_HEADER(StageSceneStateServerConfig, GamemodeConfig)
NERVE_HEADER(StageSceneStateServerConfig, GamemodeSelect)
NERVE_HEADER(StageSceneStateServerConfig, SaveData)
NERVE_HEADER(StageSceneStateServerConfig, ConnectError)
}

View file

@ -2,13 +2,23 @@
#include <cstdint>
#include <cstdlib>
#include "types.h"
typedef unsigned long int ulong;
typedef unsigned short int ushort;
typedef unsigned int uint;
typedef unsigned char uchar;
namespace nn
{
namespace nn {
namespace applet {
enum ExitReason {
Normal = 0,
Canceled = 1,
Abnormal = 2,
Unexpected = 10
};
}
namespace swkbd
{
enum Preset
@ -103,6 +113,12 @@ namespace nn
Max_DictionaryLang
};
enum CloseResult
{
Enter,
Cancel
};
struct DictionaryInfo
{
uint offset; // 0x0
@ -110,34 +126,6 @@ namespace nn
DictionaryLang lang; // 0x6
};
// KeyboardMode keyboardMode; // 0x0
// const char okText[0x8]; // 0x8
// char leftOptionalSymbolKey; // 0x10
// char rightOptionalSymbolKey; // 0x12
// bool isPredictionEnabled; // 0x14
// InvalidChar invalidCharFlag; // 0x18
// InitialCursorPos initialCursorPos; // 0x1C
// const char headerText[0x40]; // 0x20
// const char subText[0x80]; // 0x28
// const char guideText[0x100]; // 0x30
// int textMaxLength; // 0x38
// int textMinLength; // 0x3C
// PasswordMode passwordMode; // 0x40
// InputFormMode inputFormMode; // 0x44
// bool isUseNewLine; // 0x48
// bool isUseUtf8; // 0x49
// bool isUseBlurBackground; // 0x4A
// int _initialStringOffset; // 0x4C
// int _initialStringLength; // 0x50
// int _userDictionaryOffset; // 0x54
// int _userDictionaryNum; // 0x58
// bool _isUseTextCheck; // 0x5C
// void *_textCheckCallback; // 0x60
// int* separateTextPos; // 0x68
// DictionaryInfo* _customizedDicInfoList; // 0x70
// unsigned char _customizedDicCount; // 0x78
// unsigned char* _reserved; // 0x80
struct KeyboardConfig
{
@ -193,6 +181,7 @@ namespace nn
ulong GetRequiredWorkBufferSize(bool);
ulong GetRequiredStringBufferSize(void);
nn::applet::ExitReason getExitReason();
void MakePreset(nn::swkbd::KeyboardConfig *,nn::swkbd::Preset);
//void SetHeaderText(nn::swkbd::KeyboardConfig *,char16_t const*);
//void SetSubText(nn::swkbd::KeyboardConfig*, char16_t const*);
@ -211,7 +200,9 @@ namespace nn
void SetInitialText(nn::swkbd::ShowKeyboardArg *,char16_t const*);
void SetInitialTextUtf8(nn::swkbd::ShowKeyboardArg *,char const*);
//void SetUserWordList(nn::swkbd::ShowKeyboardArg *,nn::swkbd::UserWord const*,int);
void ShowKeyboard(nn::swkbd::String *,nn::swkbd::ShowKeyboardArg const&);
int ShowKeyboard(nn::swkbd::String*, nn::swkbd::ShowKeyboardArg const&);
__attribute__((used)) static nn::applet::ExitReason g_ExitReason;
} // namespace swkbd
} // namespace nn

View file

@ -32,6 +32,7 @@
#include "game/GameData/GameDataHolderWriter.h"
#include "game/GameData/GameDataFunction.h"
#include "heap/seadFrameHeap.h"
#include "heap/seadHeap.h"
#include "layouts/HideAndSeekIcon.h"
#include "rs/util.hpp"
@ -180,8 +181,8 @@ class Client {
static void updateShines();
static void openKeyboardIP();
static void openKeyboardPort();
static bool openKeyboardIP();
static bool openKeyboardPort();
static GameModeInfoBase* getModeInfo() {
return sInstance ? sInstance->mModeInfo : nullptr;
@ -196,7 +197,15 @@ class Client {
static bool isModeActive() { return sInstance ? sInstance->mIsModeActive : false; }
static bool isSelectedMode(GameMode mode) { return sInstance ? sInstance->mCurMode->getMode() == mode: false; }
static bool isSelectedMode(GameMode mode) {
return sInstance ? sInstance->mCurMode->getMode() == mode : false;
}
static void showConnect();
static void showConnectError(const char16_t* msg);
static void hideConnect();
void resetCollectedShines();
@ -227,8 +236,6 @@ class Client {
al::AsyncFunctorThread *mReadThread = nullptr; // TODO: use this thread to send any queued packets
// al::AsyncFunctorThread *mRecvThread; // TODO: use this thread to recieve packets and update PuppetInfo
sead::SafeArray<UIDIndexNode, MAXPUPINDEX> puppetPlayerID;
int mConnectCount = 0;
nn::account::Uid mUserID;
@ -286,7 +293,7 @@ class Client {
u8 mScenario = 0;
sead::Heap *mHeap = nullptr; // Heap that Client::sInstance was created in
sead::FrameHeap *mHeap = nullptr; // Custom FrameHeap used for all Client related memory
// --- Mode Info ---

View file

@ -16,14 +16,10 @@ Keyboard::Keyboard(ulong strSize) : mResultString(strSize) {
mCustomizeDicSize = 0x400;
mCustomizeDicBuf = (char*)malloc(mCustomizeDicSize);
mIsDoneKeyboard = false;
}
void Keyboard::keyboardThread() {
mIsDoneKeyboard = false;
nn::swkbd::ShowKeyboardArg keyboardArg = nn::swkbd::ShowKeyboardArg();
nn::swkbd::MakePreset(&keyboardArg.keyboardConfig, nn::swkbd::Preset::Default);
@ -44,9 +40,8 @@ void Keyboard::keyboardThread() {
nn::swkbd::SetInitialTextUtf8(&keyboardArg, mInitialText.cstr());
}
nn::swkbd::ShowKeyboard(&mResultString, keyboardArg);
mIsDoneKeyboard = true;
mIsCancelled =
nn::swkbd::ShowKeyboard(&mResultString, keyboardArg) == 671; // no idea what 671 could be
}

View file

@ -66,7 +66,7 @@ void initPuppetActors(al::Scene *scene, al::ActorInitInfo const &rootInfo, char
}
// create a debug puppet for testing purposes
createPuppetActorFromFactory(rootInfo, playerPlacement, true);
// createPuppetActorFromFactory(rootInfo, playerPlacement, true);
}
al::initPlacementObjectMap(scene, rootInfo, listName); // run init for ObjectList after we init our puppet actors

View file

@ -30,6 +30,7 @@
#include "packets/PlayerConnect.h"
#include "packets/PlayerDC.h"
#include "packets/TagInf.h"
#include "prim/seadSafeString.h"
#include "puppets/PuppetInfo.h"
#include "sead/basis/seadRawPrint.h"
#include "sead/math/seadQuat.h"
@ -61,7 +62,7 @@ Client::Client() {
mPuppetHolder = new PuppetHolder(maxPuppets);
for (size_t i = 0; i < maxPuppets; i++)
for (size_t i = 0; i < MAXPUPINDEX; i++)
{
mPuppetInfoArr[i] = new PuppetInfo();
@ -70,8 +71,6 @@ Client::Client() {
strcpy(mDebugPuppetInfo.puppetName, "PuppetDebug");
puppetPlayerID.fill({0});
mConnectCount = 0;
curCollectedShines.fill(-1);
@ -115,6 +114,8 @@ void Client::init(al::LayoutInitInfo const &initInfo, GameDataHolderAccessor hol
StartThreads();
Logger::log("Remaining Heap Size: %d\n", mHeap->getFreeSize());
}
/**
@ -190,8 +191,6 @@ void Client::restartConnection() {
Logger::log("Sucessfully Closed Socket.\n");
}
sInstance->puppetPlayerID.fill({0,0});
sInstance->mConnectCount = 0;
sInstance->mIsConnectionActive = sInstance->mSocket->init(sInstance->mServerIP.cstr(), sInstance->mServerPort).isSuccess();
@ -203,7 +202,14 @@ void Client::restartConnection() {
PlayerConnect initPacket;
initPacket.mUserID = sInstance->mUserID;
strcpy(initPacket.clientName, sInstance->mUsername.cstr());
if (sInstance->isFirstConnect) {
initPacket.conType = ConnectionTypes::INIT;
sInstance->isFirstConnect = false;
} else {
initPacket.conType = ConnectionTypes::RECONNECT;
}
sInstance->mSocket->SEND(&initPacket);
} else {
@ -280,17 +286,18 @@ bool Client::startConnection() {
/**
* @brief Opens up OS's software keyboard in order to change the currently used server IP.
*
* @returns whether or not a new IP has been defined and needs to be saved.
*/
void Client::openKeyboardIP() {
bool Client::openKeyboardIP() {
if (!sInstance) {
Logger::log("Static Instance is null!\n");
return;
return false;
}
// opens swkbd with the initial text set to the last saved IP
sInstance->mKeyboard->openKeyboard(sInstance->mServerIP.cstr(), [] (nn::swkbd::KeyboardConfig& config) {
sInstance->mKeyboard->openKeyboard(
sInstance->mServerIP.cstr(), [](nn::swkbd::KeyboardConfig& config) {
config.keyboardMode = nn::swkbd::KeyboardMode::ModeNumeric;
config.leftOptionalSymbolKey = '.';
config.textMaxLength = 15;
@ -299,24 +306,31 @@ void Client::openKeyboardIP() {
config.inputFormMode = nn::swkbd::InputFormMode::OneLine;
});
sead::FixedSafeString<0x10> prevIp = sInstance->mServerIP;
while (true) {
if (sInstance->mKeyboard->isThreadDone()) {
if(!sInstance->mKeyboard->isKeyboardCancelled())
sInstance->mServerIP = sInstance->mKeyboard->getResult();
break;
}
nn::os::YieldThread(); // allow other threads to run
}
sInstance->isFirstConnect = prevIp != sInstance->mServerIP;
return sInstance->isFirstConnect;
}
/**
* @brief Opens up OS's software keyboard in order to change the currently used server port.
*
* @returns whether or not a new port has been defined and needs to be saved.
*/
void Client::openKeyboardPort() {
bool Client::openKeyboardPort() {
if (!sInstance) {
Logger::log("Static Instance is null!\n");
return;
return false;
}
// opens swkbd with the initial text set to the last saved port
@ -331,13 +345,20 @@ void Client::openKeyboardPort() {
config.inputFormMode = nn::swkbd::InputFormMode::OneLine;
});
int prevPort = sInstance->mServerPort;
while (true) {
if (sInstance->mKeyboard->isThreadDone()) {
if(!sInstance->mKeyboard->isKeyboardCancelled())
sInstance->mServerPort = ::atoi(sInstance->mKeyboard->getResult());
break;
}
nn::os::YieldThread(); // allow other threads to run
}
sInstance->isFirstConnect = prevPort != sInstance->mServerPort;
return sInstance->isFirstConnect;
}
/**
@ -380,6 +401,7 @@ void Client::readFunc() {
if (isFirstConnect) {
initPacket.conType = ConnectionTypes::INIT;
isFirstConnect = false;
} else {
initPacket.conType = ConnectionTypes::RECONNECT;
}
@ -390,8 +412,6 @@ void Client::readFunc() {
mConnectionWait->tryEnd();
isFirstConnect = false;
while(mIsConnectionActive) {
if (mSocket->getLogState() != SOCKET_LOG_CONNECTED) {
@ -411,8 +431,16 @@ void Client::readFunc() {
Logger::log("Connected!\n");
if (isFirstConnect) {
initPacket.conType =
ConnectionTypes::INIT; // if we've changed the IP/Port since last connect,
// send init instead of reconnect
isFirstConnect = false;
} else {
initPacket.conType = ConnectionTypes::RECONNECT;
mSocket->SEND(&initPacket); // re-send init packet as reconnect packet
}
mSocket->SEND(&initPacket);
mConnectionWait->tryEnd();
continue;
} else {
@ -421,7 +449,6 @@ void Client::readFunc() {
nn::os::YieldThread(); // if we're currently waiting on the socket to be initialized, wait until it is
nn::os::SleepThread(nn::TimeSpan::FromSeconds(5));
}
if(mSocket->RECV()) { // will block until a packet has been recieved, or socket disconnected
@ -1511,3 +1538,39 @@ GameModeConfigMenu* Client::tryCreateModeMenu() {
return nullptr;
}
}
void Client::showConnectError(const char16_t* msg) {
if (!sInstance)
return;
sInstance->mConnectionWait->setTxtMessageConfirm(msg);
al::hidePane(sInstance->mConnectionWait, "Page01"); // hide A button prompt
if (!sInstance->mConnectionWait->mIsAlive) {
sInstance->mConnectionWait->appear();
sInstance->mConnectionWait->playLoop();
}
al::startAction(sInstance->mConnectionWait, "Confirm", "State");
}
void Client::showConnect() {
if (!sInstance)
return;
sInstance->mConnectionWait->appear();
sInstance->mConnectionWait->playLoop();
}
void Client::hideConnect() {
if (!sInstance)
return;
sInstance->mConnectionWait->tryEnd();
}

View file

@ -59,7 +59,7 @@ s32 SocketBase::socket_read_char(char *out) {
return valread;
}
s32 SocketBase::getSocket() {
s32 SocketBase::getFd() {
if(this->socket_log_state == SOCKET_LOG_CONNECTED) {
return this->socket_log_socket;
}else {
@ -69,11 +69,9 @@ s32 SocketBase::getSocket() {
bool SocketBase::closeSocket() {
nn::Result result = nn::socket::Close(this->socket_log_socket);
this->socket_log_state = SOCKET_LOG_DISCONNECTED; // probably not safe to assume socket will be closed
if (result.isSuccess()) {
this->socket_log_state = SOCKET_LOG_DISCONNECTED;
}
nn::Result result = nn::socket::Close(this->socket_log_socket);
return result.isSuccess();
}

View file

@ -66,6 +66,8 @@ nn::Result SocketClient::init(const char* ip, u16 port) {
this->socket_log_state = SOCKET_LOG_CONNECTED;
Logger::log("Socket fd: %d\n", socket_log_socket);
return result;
}
@ -126,7 +128,7 @@ bool SocketClient::RECV() {
int fullSize = header->mPacketSize + sizeof(Packet);
if (header->mType != PacketType::UNKNOWN && fullSize <= MAXPACKSIZE && fullSize > 0) {
if (header->mType != PacketType::UNKNOWN && fullSize <= MAXPACKSIZE && fullSize > 0 && valread == sizeof(Packet)) {
if (header->mType != PLAYERINF && header->mType != HACKCAPINF)
Logger::log("Received packet (from %02X%02X): %s\n",
@ -163,6 +165,8 @@ bool SocketClient::RECV() {
free(packetBuf);
}
}
} else {
Logger::log("Failed to aquire valid data! Packet Type: %d Full Packet Size %d valread size: %d", header->mType, fullSize, valread);
}
return true;
@ -194,5 +198,11 @@ bool SocketClient::closeSocket() {
Logger::log("Closing Socket.\n");
return SocketBase::closeSocket();
bool result = false;
if (!(result = SocketBase::closeSocket())) {
Logger::log("Failed to close socket!\n");
}
return result;
}

View file

@ -170,10 +170,15 @@ void StageSceneStateServerConfig::exeOpenKeyboardIP() {
Client::getKeyboard()->setHeaderText(u"Set a Server IP Below.");
Client::getKeyboard()->setSubText(u"");
Client::openKeyboardIP();
// anything that happens after this will be ran after the keyboard closes
bool isSave = Client::openKeyboardIP(); // anything that happens after this will be ran after the keyboard closes
al::startHitReaction(mCurrentMenu, "リセット", 0);
if(isSave)
al::setNerve(this, &nrvStageSceneStateServerConfigSaveData);
else
al::setNerve(this, &nrvStageSceneStateServerConfigMainMenu);
}
}
@ -184,21 +189,36 @@ void StageSceneStateServerConfig::exeOpenKeyboardPort() {
Client::getKeyboard()->setHeaderText(u"Set a Server Port Below.");
Client::getKeyboard()->setSubText(u"");
Client::openKeyboardPort();
// anything that happens after this will be ran after the keyboard closes
bool isSave = Client::openKeyboardPort(); // anything that happens after this will be ran after the keyboard closes
al::startHitReaction(mCurrentMenu, "リセット", 0);
if(isSave)
al::setNerve(this, &nrvStageSceneStateServerConfigSaveData);
else
al::setNerve(this, &nrvStageSceneStateServerConfigMainMenu);
}
}
void StageSceneStateServerConfig::exeRestartServer() {
if (al::isFirstStep(this)) {
mCurrentList->deactivate();
Client::showConnect();
Client::restartConnection();
}
if (Client::isSocketActive()) {
Client::hideConnect();
al::startHitReaction(mCurrentMenu, "リセット", 0);
al::setNerve(this, &nrvStageSceneStateServerConfigMainMenu);
} else {
al::setNerve(this, &nrvStageSceneStateServerConfigConnectError);
}
}
@ -237,6 +257,30 @@ void StageSceneStateServerConfig::exeGamemodeSelect() {
}
}
void StageSceneStateServerConfig::exeConnectError() {
if (al::isFirstStep(this)) {
Client::showConnectError(u"Failed to Reconnect!");
}
if (al::isGreaterEqualStep(this, 60)) { // close after 1 second
Client::hideConnect();
al::startHitReaction(mCurrentMenu, "リセット", 0);
al::setNerve(this, &nrvStageSceneStateServerConfigMainMenu);
}
}
void StageSceneStateServerConfig::exeSaveData() {
if (al::isFirstStep(this)) {
SaveDataAccessFunction::startSaveDataWrite(mGameDataHolder);
}
if (SaveDataAccessFunction::updateSaveDataAccess(mGameDataHolder, false)) {
al::startHitReaction(mCurrentMenu, "リセット", 0);
al::setNerve(this, &nrvStageSceneStateServerConfigMainMenu);
}
}
void StageSceneStateServerConfig::endSubMenu() {
mCurrentList->deactivate();
mCurrentMenu->kill();
@ -291,17 +335,6 @@ void StageSceneStateServerConfig::subMenuUpdate() {
}
}
void StageSceneStateServerConfig::exeSaveData() {
if (al::isFirstStep(this)) {
SaveDataAccessFunction::startSaveDataWrite(mGameDataHolder);
}
if (SaveDataAccessFunction::updateSaveDataAccess(mGameDataHolder, false)) {
al::startHitReaction(mCurrentMenu, "リセット", 0);
al::setNerve(this, &nrvStageSceneStateServerConfigMainMenu);
}
}
namespace {
NERVE_IMPL(StageSceneStateServerConfig, MainMenu)
@ -311,4 +344,5 @@ NERVE_IMPL(StageSceneStateServerConfig, RestartServer)
NERVE_IMPL(StageSceneStateServerConfig, GamemodeConfig)
NERVE_IMPL(StageSceneStateServerConfig, GamemodeSelect)
NERVE_IMPL(StageSceneStateServerConfig, SaveData)
NERVE_IMPL(StageSceneStateServerConfig, ConnectError)
}