diff --git a/.github/actions/build/action.yml b/.github/actions/build/action.yml index 78a7f1a..ec64178 100644 --- a/.github/actions/build/action.yml +++ b/.github/actions/build/action.yml @@ -11,7 +11,7 @@ inputs: required : false default : '' emu: - description : 'what system the build is for, Switch or Emulators' + description : 'what system the build is for: Switch, Ryujinx or yuzu' required : false default : 'Switch' @@ -31,8 +31,8 @@ runs: shell : bash run: | VERS=${{ inputs.tag }} - echo "::set-output name=version::${VERS:1}" - echo "::set-output name=filename::${{ inputs.prefix }}SMO_Online${{ (inputs.tag != '' && format('_{0}', inputs.tag)) || '' }}_for_${{ inputs.emu }}" + echo "version=${VERS:1}" >>$GITHUB_OUTPUT + echo "filename=${{ inputs.prefix }}SMO_Online${{ (inputs.tag != '' && format('_{0}', inputs.tag)) || '' }}_for_${{ inputs.emu }}" >>$GITHUB_OUTPUT - name : Set up Docker Buildx uses : docker/setup-buildx-action@v2 @@ -56,11 +56,22 @@ runs: docker run --rm \ -u `id -u`:`id -g` \ -v "/$PWD/":/app/ \ - -e ISEMU=${{ (inputs.emu == 'Emulators' && '1') || '0' }} \ + -e ISEMU=${{ (inputs.emu != 'Switch' && '1') || '0' }} \ ${{ (steps.env.outputs.version != '' && format('-e BUILDVER={0}', steps.env.outputs.version)) || '' }} \ smoo-build-env \ ; cp -r ./romfs/ ./starlight_patch_100/atmosphere/contents/0100000000010000/. + - + name : Yuzu + shell : bash + if : ${{ inputs.emu == 'yuzu' }} + run: | + cd ./starlight_patch_100/ + mkdir ./SMOO/ + mv ./atmosphere/contents/0100000000010000/exefs ./SMOO/exefs + mv ./atmosphere/contents/0100000000010000/romfs ./SMOO/romfs + mv ./atmosphere/exefs_patches/StarlightBase/3CA12DFAAF9C82DA064D1698DF79CDA1.ips ./SMOO/exefs/ + rm -rf ./atmosphere/ - name : Upload artifacts uses : actions/upload-artifact@v3 diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 25259ca..76179ae 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -22,7 +22,7 @@ jobs: build: strategy: matrix: - emu : [ Switch, Emulators ] + emu : [ Switch, Ryujinx, yuzu ] runs-on: ubuntu-latest steps: - diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml index d8aea1a..000ffea 100644 --- a/.github/workflows/dev-release.yml +++ b/.github/workflows/dev-release.yml @@ -21,11 +21,12 @@ jobs: build: strategy: matrix: - emu : [ Switch, Emulators ] + emu : [ Switch, Ryujinx, yuzu ] runs-on: ubuntu-latest outputs: filename1: ${{ steps.set-output.outputs.filename-Switch }} - filename2: ${{ steps.set-output.outputs.filename-Emulators }} + filename2: ${{ steps.set-output.outputs.filename-Ryujinx }} + filename3: ${{ steps.set-output.outputs.filename-yuzu }} steps: - name : Checkout @@ -35,7 +36,7 @@ jobs: id : env shell : bash run: | - echo "::set-output name=prefix::$(date +'%Y%m%d_%H%M%S_' --utc)" + echo "prefix=$(date +'%Y%m%d_%H%M%S_' --utc)" >>$GITHUB_OUTPUT - name : Build artifacts id : build @@ -48,7 +49,7 @@ jobs: id : set-output shell : bash run : | - echo "::set-output name=filename-${{ matrix.emu }}::${{ steps.build.outputs.filename }}" + echo "filename-${{ matrix.emu }}=${{ steps.build.outputs.filename }}" >>$GITHUB_OUTPUT attach: needs: build @@ -63,7 +64,7 @@ jobs: shell : bash run: | url=`curl -sS --fail ${{ github.api_url }}/repos/${{ github.repository }}/releases/tags/${{ env.TAG }} | jq .upload_url -r` - echo "::set-output name=upload_url::$url" + echo "upload_url=$url" >>$GITHUB_OUTPUT - name : Attach build artifacts to release (Switch) uses : ./.github/actions/attach @@ -72,12 +73,19 @@ jobs: upload_url : ${{ steps.release.outputs.upload_url }} GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} - - name : Attach build artifacts to release (Emulators) + name : Attach build artifacts to release (Ryujinx) uses : ./.github/actions/attach with: filename : ${{ needs.build.outputs.filename2 }} upload_url : ${{ steps.release.outputs.upload_url }} GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} + - + name : Attach build artifacts to release (yuzu) + uses : ./.github/actions/attach + with: + filename : ${{ needs.build.outputs.filename3 }} + upload_url : ${{ steps.release.outputs.upload_url }} + GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} move: needs: attach diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1d72252..859a4d7 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,11 +14,12 @@ jobs: build: strategy: matrix: - emu : [ Switch, Emulators ] + emu : [ Switch, Ryujinx, yuzu ] runs-on: ubuntu-latest outputs: filename1: ${{ steps.set-output.outputs.filename-Switch }} - filename2: ${{ steps.set-output.outputs.filename-Emulators }} + filename2: ${{ steps.set-output.outputs.filename-Ryujinx }} + filename3: ${{ steps.set-output.outputs.filename-yuzu }} steps: - name : Checkout @@ -59,9 +60,16 @@ jobs: upload_url : ${{ steps.release.outputs.upload_url }} GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} - - name : Attach build artifacts to release (Emulators) + name : Attach build artifacts to release (Ryujinx) uses : ./.github/actions/attach with: filename : ${{ needs.build.outputs.filename2 }} upload_url : ${{ steps.release.outputs.upload_url }} GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} + - + name : Attach build artifacts to release (yuzu) + uses : ./.github/actions/attach + with: + filename : ${{ needs.build.outputs.filename3 }} + upload_url : ${{ steps.release.outputs.upload_url }} + GITHUB_TOKEN : ${{ secrets.GITHUB_TOKEN }} diff --git a/Dockerfile b/Dockerfile index 7cf9951..b2f0afa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,26 +1,13 @@ -FROM ubuntu:20.04 as builder +FROM devkitpro/devkita64:latest as builder # install dependencies RUN apt-get update \ && apt-get install -y \ - curl \ - apt-transport-https \ python3 \ python3-pip \ - && pip install keystone-engine \ -; - -# install devkitpro -RUN ln -s /proc/self/mounts /etc/mtab \ - && mkdir /devkitpro/ \ - && echo "deb [signed-by=/devkitpro/pub.gpg] https://apt.devkitpro.org stable main" >/etc/apt/sources.list.d/devkitpro.list \ - && curl --fail -o /devkitpro/pub.gpg https://apt.devkitpro.org/devkitpro-pub.gpg \ - && apt-get update \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y devkitpro-pacman \ - && dkp-pacman --noconfirm -S switch-dev \ + && pip3 install keystone-engine \ ; WORKDIR /app/ -ENV DEVKITPRO /opt/devkitpro ENTRYPOINT make diff --git a/include/game/StageScene/StageSceneStateServerConfig.hpp b/include/game/StageScene/StageSceneStateServerConfig.hpp index 8956bdc..9f9c245 100644 --- a/include/game/StageScene/StageSceneStateServerConfig.hpp +++ b/include/game/StageScene/StageSceneStateServerConfig.hpp @@ -29,7 +29,6 @@ class StageSceneStateServerConfig : public al::HostStateBase, public enum ServerConfigOption { GAMEMODECONFIG, GAMEMODESWITCH, - RECONNECT, SETIP, SETPORT }; @@ -42,11 +41,9 @@ class StageSceneStateServerConfig : public al::HostStateBase, public void exeMainMenu(); void exeOpenKeyboardIP(); void exeOpenKeyboardPort(); - void exeRestartServer(); void exeGamemodeConfig(); void exeGamemodeSelect(); void exeSaveData(); - void exeConnectError(); void endSubMenu(); @@ -63,7 +60,7 @@ class StageSceneStateServerConfig : public al::HostStateBase, public SimpleLayoutMenu* mCurrentMenu = nullptr; CommonVerticalList* mCurrentList = nullptr; - // Root Page, contains buttons for gamemode config, server reconnecting, and server ip address changing + // Root Page, contains buttons for gamemode config, and server ip address changing SimpleLayoutMenu* mMainOptions = nullptr; CommonVerticalList *mMainOptionsList = nullptr; // Sub-Page of Mode config, used to select a gamemode for the client to use @@ -86,9 +83,7 @@ namespace { NERVE_HEADER(StageSceneStateServerConfig, MainMenu) NERVE_HEADER(StageSceneStateServerConfig, OpenKeyboardIP) NERVE_HEADER(StageSceneStateServerConfig, OpenKeyboardPort) - NERVE_HEADER(StageSceneStateServerConfig, RestartServer) NERVE_HEADER(StageSceneStateServerConfig, GamemodeConfig) NERVE_HEADER(StageSceneStateServerConfig, GamemodeSelect) NERVE_HEADER(StageSceneStateServerConfig, SaveData) - NERVE_HEADER(StageSceneStateServerConfig, ConnectError) -} \ No newline at end of file +} diff --git a/include/packets/GameInf.h b/include/packets/GameInf.h index 34c5793..f435421 100644 --- a/include/packets/GameInf.h +++ b/include/packets/GameInf.h @@ -6,7 +6,7 @@ struct PACKED GameInf : Packet { GameInf() : Packet() {this->mType = PacketType::GAMEINF; mPacketSize = sizeof(GameInf) - sizeof(Packet);}; bool1 is2D = false; - u8 scenarioNo = -1; + u8 scenarioNo = 255; char stageName[0x40] = {}; bool operator==(const GameInf &rhs) const { @@ -19,4 +19,4 @@ struct PACKED GameInf : Packet { bool operator!=(const GameInf& rhs) const { return !operator==(rhs); } -}; \ No newline at end of file +}; diff --git a/include/server/Client.hpp b/include/server/Client.hpp index 188c9b5..ab1b873 100644 --- a/include/server/Client.hpp +++ b/include/server/Client.hpp @@ -88,7 +88,6 @@ class Client { bool startThread(); void readFunc(); - static void restartConnection(); static bool isSocketActive() { return sInstance ? sInstance->mSocket->isConnected() : false; }; bool isPlayerConnected(int index) { return mPuppetInfoArr[index]->isConnected; } @@ -103,6 +102,7 @@ class Client { static void sendShineCollectPacket(int shineId); static void sendTagInfPacket(); static void sendCaptureInfPacket(const PlayerActorHakoniwa *player); + void resendInitPackets(); int getCollectedShinesCount() { return curCollectedShines.size(); } int getShineID(int index) { if (index < curCollectedShines.size()) { return curCollectedShines[index]; } return -1; } @@ -174,11 +174,8 @@ class Client { static bool openKeyboardIP(); static bool openKeyboardPort(); - static void showConnect(); - - static void showConnectError(const char16_t* msg); - - static void hideConnect(); + static void showUIMessage(const char16_t* msg); + static void hideUIMessage(); void resetCollectedShines(); @@ -228,7 +225,10 @@ class Client { // Backups for our last player/game packets, used for example to re-send them for newly connected clients PlayerInf lastPlayerInfPacket = PlayerInf(); GameInf lastGameInfPacket = GameInf(); + GameInf emptyGameInfPacket = GameInf(); CostumeInf lastCostumeInfPacket = CostumeInf(); + TagInf lastTagInfPacket = TagInf(); + CaptureInf lastCaptureInfPacket = CaptureInf(); Keyboard* mKeyboard = nullptr; // keyboard for setting server IP @@ -240,9 +240,7 @@ class Client { bool mIsFirstConnect = true; // --- Game Layouts --- - - al::WindowConfirmWait* mConnectionWait; - + al::WindowConfirmWait* mUIMessage; al::SimpleLayoutAppearWaitEnd *mConnectStatus; // --- Game Info --- diff --git a/include/server/SocketClient.hpp b/include/server/SocketClient.hpp index da2bb7f..bae3af9 100644 --- a/include/server/SocketClient.hpp +++ b/include/server/SocketClient.hpp @@ -20,9 +20,11 @@ #include "packets/Packet.h" +class Client; + class SocketClient : public SocketBase { public: - SocketClient(const char *name, sead::Heap *heap); + SocketClient(const char* name, sead::Heap* heap, Client* client); nn::Result init(const char* ip, u16 port) override; bool tryReconnect(); bool closeSocket() override; @@ -63,6 +65,7 @@ class SocketClient : public SocketBase { private: sead::Heap* mHeap = nullptr; + Client* client = nullptr; al::AsyncFunctorThread* mRecvThread = nullptr; al::AsyncFunctorThread* mSendThread = nullptr; diff --git a/include/server/hns/HideAndSeekConfigMenu.hpp b/include/server/hns/HideAndSeekConfigMenu.hpp index f2039c9..3564912 100644 --- a/include/server/hns/HideAndSeekConfigMenu.hpp +++ b/include/server/hns/HideAndSeekConfigMenu.hpp @@ -9,11 +9,13 @@ public: HideAndSeekConfigMenu(); void initMenu(const al::LayoutInitInfo &initInfo) override; - const sead::WFixedSafeString<0x200> *getStringData() override; + const sead::WFixedSafeString<0x200>* getStringData() override; bool updateMenu(int selectIndex) override; const int getMenuSize() override { return mItemCount; } private: - static constexpr int mItemCount = 2; -}; \ No newline at end of file + static constexpr int mItemCount = 1; + sead::SafeArray, mItemCount>* gravityOn = nullptr; + sead::SafeArray, mItemCount>* gravityOff = nullptr; +}; diff --git a/source/server/Client.cpp b/source/server/Client.cpp index 36bc2d7..f30da5d 100644 --- a/source/server/Client.cpp +++ b/source/server/Client.cpp @@ -27,7 +27,7 @@ Client::Client() { mKeyboard = new Keyboard(nn::swkbd::GetRequiredStringBufferSize()); - mSocket = new SocketClient("SocketClient", mHeap); + mSocket = new SocketClient("SocketClient", mHeap, this); mPuppetHolder = new PuppetHolder(maxPuppets); @@ -71,22 +71,21 @@ Client::Client() { */ void Client::init(al::LayoutInitInfo const &initInfo, GameDataHolderAccessor holder) { - mConnectionWait = new (mHeap) al::WindowConfirmWait("ServerWaitConnect", "WindowConfirmWait", initInfo); - mConnectStatus = new (mHeap) al::SimpleLayoutAppearWaitEnd("", "SaveMessage", initInfo, 0, false); - - mConnectionWait->setTxtMessage(u"Connecting to Server."); - mConnectionWait->setTxtMessageConfirm(u"Failed to Connect!"); - al::setPaneString(mConnectStatus, "TxtSave", u"Connecting to Server.", 0); al::setPaneString(mConnectStatus, "TxtSaveSh", u"Connecting to Server.", 0); + mUIMessage = new (mHeap) al::WindowConfirmWait("ServerWaitConnect", "WindowConfirmWait", initInfo); + mUIMessage->setTxtMessage(u"a"); + mUIMessage->setTxtMessageConfirm(u"b"); + mHolder = holder; startThread(); Logger::log("Heap Free Size: %f/%f\n", mHeap->getFreeSize() * 0.001f, mHeap->getSize() * 0.001f); } + /** * @brief starts client read thread * @@ -103,54 +102,7 @@ bool Client::startThread() { return false; } } -/** - * @brief restarts currently active connection to server - * - */ -void Client::restartConnection() { - Logger::log("Restarting connection.\n"); - if (!sInstance) { - Logger::log("Static Instance is null!\n"); - return; - } - - sead::ScopedCurrentHeapSetter setter(sInstance->mHeap); - - Logger::log("Sending Disconnect.\n"); - - PlayerDC *playerDC = new PlayerDC(); - - playerDC->mUserID = sInstance->mUserID; - - - sInstance->mSocket->setQueueOpen(false); - sInstance->mSocket->clearMessageQueues(); - - sInstance->mSocket->send(playerDC); - - sInstance->mHeap->free(playerDC); - - if (sInstance->mSocket->closeSocket()) { - Logger::log("Succesfully Closed Socket.\n"); - } - - Logger::log("Waiting for send/recv threads to finish.\n"); - sInstance->mSocket->waitForThreads(); - - sInstance->mConnectCount = 0; - - Logger::log("Reinitializing connection\n"); - sInstance->mIsConnectionActive = sInstance->mSocket->init(sInstance->mServerIP.cstr(), sInstance->mServerPort).isSuccess(); - - if(sInstance->mSocket->getLogState() == SOCKET_LOG_CONNECTED) { - - Logger::log("Reconnect Succesful!\n"); - - } else { - Logger::log("Reconnect Unsuccessful.\n"); - } -} /** * @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. * @@ -303,6 +255,33 @@ bool Client::openKeyboardPort() { return isFirstConnect; } + +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(); +} + /** * @brief main thread function for read thread, responsible for processing packets from server * @@ -359,16 +338,22 @@ void Client::readFunc() { // Send relevant info packets when another client is connected - // Assume game packets are empty from first connection - if (lastGameInfPacket.mUserID != mUserID) - lastGameInfPacket.mUserID = mUserID; - mSocket->send(&lastGameInfPacket); + if (lastGameInfPacket != emptyGameInfPacket) { + // Assume game packets are empty from first connection + if (lastGameInfPacket.mUserID != mUserID) + lastGameInfPacket.mUserID = mUserID; + mSocket->send(&lastGameInfPacket); + } - // 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); + // 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); + if (lastTagInfPacket.mUserID == mUserID) + mSocket->send(&lastTagInfPacket); + if (lastCaptureInfPacket.mUserID == mUserID) + mSocket->send(&lastCaptureInfPacket); break; case PacketType::COSTUMEINF: @@ -416,7 +401,6 @@ void Client::readFunc() { }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); - this->restartConnection(); } } @@ -506,6 +490,7 @@ void Client::sendPlayerInfPacket(const PlayerActorBase *playerBase, bool isYukim } } + /** * @brief sends info related to player's cap actor to server * @@ -580,14 +565,14 @@ void Client::sendGameInfPacket(const PlayerActorHakoniwa* player, GameDataHolder strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder)); - if(*packet != sInstance->lastGameInfPacket) { + if (*packet != sInstance->lastGameInfPacket && *packet != sInstance->emptyGameInfPacket) { sInstance->lastGameInfPacket = *packet; sInstance->mSocket->queuePacket(packet); } else { sInstance->mHeap->free(packet); // free packet if we're not using it } - } + /** * @brief * Sends only stage info to the server. @@ -611,9 +596,10 @@ void Client::sendGameInfPacket(GameDataHolderAccessor holder) { strcpy(packet->stageName, GameDataFunction::getCurrentStageName(holder)); - sInstance->lastGameInfPacket = *packet; - - sInstance->mSocket->queuePacket(packet); + if (*packet != sInstance->emptyGameInfPacket) { + sInstance->lastGameInfPacket = *packet; + sInstance->mSocket->queuePacket(packet); + } } /** @@ -642,13 +628,15 @@ void Client::sendTagInfPacket() { packet->mUserID = sInstance->mUserID; - packet->isIt = hsMode->isPlayerIt(); + packet->isIt = hsMode->isPlayerIt() && hsMode->isModeActive(); packet->minutes = curInfo->mHidingTime.mMinutes; packet->seconds = curInfo->mHidingTime.mSeconds; packet->updateType = static_cast(TagUpdateType::STATE | TagUpdateType::TIME); sInstance->mSocket->queuePacket(packet); + + sInstance->lastTagInfPacket = *packet; } /** @@ -664,6 +652,8 @@ void Client::sendCostumeInfPacket(const char* body, const char* cap) { return; } + if (!strcmp(body, "") && !strcmp(cap, "")) { return; } + sead::ScopedCurrentHeapSetter setter(sInstance->mHeap); CostumeInf *packet = new CostumeInf(body, cap); @@ -691,16 +681,43 @@ void Client::sendCaptureInfPacket(const PlayerActorHakoniwa* player) { packet->mUserID = sInstance->mUserID; strcpy(packet->hackName, tryConvertName(player->mHackKeeper->getCurrentHackName())); sInstance->mSocket->queuePacket(packet); + sInstance->lastCaptureInfPacket = *packet; sInstance->isSentCaptureInf = true; } else if (!sInstance->isClientCaptured && sInstance->isSentCaptureInf) { CaptureInf *packet = new CaptureInf(); packet->mUserID = sInstance->mUserID; strcpy(packet->hackName, ""); sInstance->mSocket->queuePacket(packet); + sInstance->lastCaptureInfPacket = *packet; sInstance->isSentCaptureInf = false; } } +/** + * @brief + */ +void Client::resendInitPackets() { + // CostumeInfPacket + if (lastCostumeInfPacket.mUserID == mUserID) { + mSocket->queuePacket(&lastCostumeInfPacket); + } + + // GameInfPacket + if (lastGameInfPacket != emptyGameInfPacket) { + mSocket->queuePacket(&lastGameInfPacket); + } + + // TagInfPacket + if (lastTagInfPacket.mUserID == mUserID) { + mSocket->queuePacket(&lastTagInfPacket); + } + + // CaptureInfPacket + if (lastCaptureInfPacket.mUserID == mUserID) { + mSocket->queuePacket(&lastCaptureInfPacket); + } +} + /** * @brief * @@ -885,6 +902,7 @@ void Client::updatePlayerConnect(PlayerConnect* packet) { mConnectCount++; } } + /** * @brief * @@ -1433,37 +1451,3 @@ Shine* Client::findStageShine(int shineID) { } 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(); -} diff --git a/source/server/SocketClient.cpp b/source/server/SocketClient.cpp index d959140..24021a7 100644 --- a/source/server/SocketClient.cpp +++ b/source/server/SocketClient.cpp @@ -14,7 +14,9 @@ #include "thread/seadMessageQueue.h" #include "types.h" -SocketClient::SocketClient(const char* name, sead::Heap* heap) : mHeap(heap), SocketBase(name) { +SocketClient::SocketClient(const char* name, sead::Heap* heap, Client* client) : mHeap(heap), SocketBase(name) { + + this->client = client; #if EMU this->pollTime = 0; #else @@ -121,6 +123,26 @@ nn::Result SocketClient::init(const char* ip, u16 port) { send(&initPacket); + // on a reconnect, resend some maybe missing packets + if (initPacket.conType == ConnectionTypes::RECONNECT) { + client->resendInitPackets(); + } else { + // empty TagInf + TagInf tagInf; + tagInf.mUserID = initPacket.mUserID; + tagInf.isIt = false; + tagInf.minutes = 0; + tagInf.seconds = 0; + tagInf.updateType = static_cast(TagUpdateType::STATE | TagUpdateType::TIME); + send(&tagInf); + + // empty CaptureInf + CaptureInf capInf; + capInf.mUserID = initPacket.mUserID; + strcpy(capInf.hackName, ""); + send(&capInf); + } + return result; } diff --git a/source/server/hns/HideAndSeekConfigMenu.cpp b/source/server/hns/HideAndSeekConfigMenu.cpp index 79fc7a4..c34e786 100644 --- a/source/server/hns/HideAndSeekConfigMenu.cpp +++ b/source/server/hns/HideAndSeekConfigMenu.cpp @@ -5,20 +5,27 @@ #include "server/hns/HideAndSeekMode.hpp" #include "server/Client.hpp" -HideAndSeekConfigMenu::HideAndSeekConfigMenu() : GameModeConfigMenu() {} +HideAndSeekConfigMenu::HideAndSeekConfigMenu() : GameModeConfigMenu() { + gravityOn = new sead::SafeArray, mItemCount>(); + gravityOn->mBuffer[0].copy(u"Toggle H&S Gravity (ON)"); + + gravityOff = new sead::SafeArray, mItemCount>(); + gravityOff->mBuffer[0].copy(u"Toggle H&S Gravity (OFF)"); +} void HideAndSeekConfigMenu::initMenu(const al::LayoutInitInfo &initInfo) { } -const sead::WFixedSafeString<0x200> *HideAndSeekConfigMenu::getStringData() { - sead::SafeArray, mItemCount>* gamemodeConfigOptions = - new sead::SafeArray, mItemCount>(); - - gamemodeConfigOptions->mBuffer[0].copy(u"Toggle H&S Gravity On"); - gamemodeConfigOptions->mBuffer[1].copy(u"Toggle H&S Gravity Off"); - - return gamemodeConfigOptions->mBuffer; +const sead::WFixedSafeString<0x200>* HideAndSeekConfigMenu::getStringData() { + HideAndSeekInfo *curMode = GameModeManager::instance()->getInfo(); + return ( + GameModeManager::instance()->isMode(GameMode::HIDEANDSEEK) + && curMode != nullptr + && curMode->mIsUseGravity + ? gravityOn->mBuffer + : gravityOff->mBuffer + ); } bool HideAndSeekConfigMenu::updateMenu(int selectIndex) { @@ -35,13 +42,7 @@ bool HideAndSeekConfigMenu::updateMenu(int selectIndex) { switch (selectIndex) { case 0: { if (GameModeManager::instance()->isMode(GameMode::HIDEANDSEEK)) { - curMode->mIsUseGravity = true; - } - return true; - } - case 1: { - if (GameModeManager::instance()->isMode(GameMode::HIDEANDSEEK)) { - curMode->mIsUseGravity = false; + curMode->mIsUseGravity = !curMode->mIsUseGravity; } return true; } @@ -50,4 +51,4 @@ bool HideAndSeekConfigMenu::updateMenu(int selectIndex) { return false; } -} \ No newline at end of file +} diff --git a/source/server/hns/HideAndSeekMode.cpp b/source/server/hns/HideAndSeekMode.cpp index 65e97c0..9efbdaf 100644 --- a/source/server/hns/HideAndSeekMode.cpp +++ b/source/server/hns/HideAndSeekMode.cpp @@ -84,6 +84,8 @@ void HideAndSeekMode::begin() { playGuideLyt->end(); GameModeBase::begin(); + + Client::sendTagInfPacket(); } void HideAndSeekMode::end() { @@ -109,6 +111,8 @@ void HideAndSeekMode::end() { playGuideLyt->appear(); GameModeBase::end(); + + Client::sendTagInfPacket(); } void HideAndSeekMode::update() { diff --git a/source/states/StageSceneStateServerConfig.cpp b/source/states/StageSceneStateServerConfig.cpp index e8d0e2e..3d6a096 100644 --- a/source/states/StageSceneStateServerConfig.cpp +++ b/source/states/StageSceneStateServerConfig.cpp @@ -41,14 +41,13 @@ StageSceneStateServerConfig::StageSceneStateServerConfig(const char *name, al::S mMainOptionsList->unkInt1 = 1; - mMainOptionsList->initDataNoResetSelected(5); + mMainOptionsList->initDataNoResetSelected(4); - sead::SafeArray, 5>* mainMenuOptions = - new sead::SafeArray, 5>(); + sead::SafeArray, 4>* mainMenuOptions = + new sead::SafeArray, 4>(); mainMenuOptions->mBuffer[ServerConfigOption::GAMEMODECONFIG].copy(u"Gamemode Config"); mainMenuOptions->mBuffer[ServerConfigOption::GAMEMODESWITCH].copy(u"Change Gamemode"); - mainMenuOptions->mBuffer[ServerConfigOption::RECONNECT].copy(u"Reconnect to Server"); mainMenuOptions->mBuffer[ServerConfigOption::SETIP].copy(u"Change Server IP"); mainMenuOptions->mBuffer[ServerConfigOption::SETPORT].copy(u"Change Server Port"); @@ -101,11 +100,6 @@ StageSceneStateServerConfig::StageSceneStateServerConfig(const char *name, al::S entry.mList = new CommonVerticalList(entry.mLayout, initInfo, true); al::setPaneString(entry.mLayout, "TxtOption", u"Gamemode Configuration", 0); - - entry.mList->initDataNoResetSelected(entry.mMenu->getMenuSize()); - - - entry.mList->addStringData(entry.mMenu->getStringData(), "TxtContent"); } @@ -115,6 +109,15 @@ StageSceneStateServerConfig::StageSceneStateServerConfig(const char *name, al::S void StageSceneStateServerConfig::init() { initNerve(&nrvStageSceneStateServerConfigMainMenu, 0); + + #ifdef EMU + char ryujinx[0x10] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + nn::account::Uid user; + nn::account::GetLastOpenedUser(&user); + if (memcmp(user.data, ryujinx, 0x10) == 0) { + Client::showUIMessage(u"Error: Ryujinx default profile detected.\nYou have to create a new user profile!"); + } + #endif } void StageSceneStateServerConfig::appear(void) { @@ -176,10 +179,6 @@ void StageSceneStateServerConfig::exeMainMenu() { al::setNerve(this, &nrvStageSceneStateServerConfigGamemodeSelect); break; } - case ServerConfigOption::RECONNECT: { - al::setNerve(this, &nrvStageSceneStateServerConfigRestartServer); - break; - } case ServerConfigOption::SETIP: { al::setNerve(this, &nrvStageSceneStateServerConfigOpenKeyboardIP); break; @@ -233,32 +232,16 @@ void StageSceneStateServerConfig::exeOpenKeyboardPort() { } } -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); - } -} - void StageSceneStateServerConfig::exeGamemodeConfig() { if (al::isFirstStep(this)) { mGamemodeConfigMenu = &mGamemodeConfigMenus[GameModeManager::instance()->getGameMode()]; + + mGamemodeConfigMenu->mList->initDataNoResetSelected(mGamemodeConfigMenu->mMenu->getMenuSize()); + mGamemodeConfigMenu->mList->addStringData(mGamemodeConfigMenu->mMenu->getStringData(), "TxtContent"); + mCurrentList = mGamemodeConfigMenu->mList; mCurrentMenu = mGamemodeConfigMenu->mLayout; + subMenuStart(); } @@ -290,18 +273,6 @@ 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)) { @@ -373,9 +344,7 @@ namespace { NERVE_IMPL(StageSceneStateServerConfig, MainMenu) NERVE_IMPL(StageSceneStateServerConfig, OpenKeyboardIP) NERVE_IMPL(StageSceneStateServerConfig, OpenKeyboardPort) -NERVE_IMPL(StageSceneStateServerConfig, RestartServer) NERVE_IMPL(StageSceneStateServerConfig, GamemodeConfig) NERVE_IMPL(StageSceneStateServerConfig, GamemodeSelect) NERVE_IMPL(StageSceneStateServerConfig, SaveData) -NERVE_IMPL(StageSceneStateServerConfig, ConnectError) -} \ No newline at end of file +}