Skip to content

Commit

Permalink
Merge pull request #64 from MikeIsAStar/allow-for-the-open-host-featu…
Browse files Browse the repository at this point in the history
…re-to-be-enabled-in-a-room

[MKW] Allow for the "Open Host" feature to be enabled while in a room
  • Loading branch information
mkwcat authored Apr 21, 2024
2 parents b20b02b + 00336f1 commit 2e38a2b
Show file tree
Hide file tree
Showing 5 changed files with 298 additions and 165 deletions.
7 changes: 6 additions & 1 deletion payload/import/mkw/net/net.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ static_assert(sizeof(RacePacket) == 0x10);
class NetController
{
public:
enum JoinType {
enum class JoinType {
NotJoining = 0,
WorldwideVersusRace = 1,
ContinentalVersusRace = 2,
Expand Down Expand Up @@ -116,6 +116,11 @@ class NetController
return isAidTheServer(myAid());
}

bool amITheRoomHost() const
{
return m_joinType == JoinType::RoomHost;
}

bool inVanillaMatch() const
{
switch (m_joinType) {
Expand Down
79 changes: 79 additions & 0 deletions payload/import/mkw/ui/page/friendRoomPage.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#pragma once

#include "import/mkw/net/net.hpp"
#include "openHostPage.hpp"

namespace mkw::UI
{

#if RMC

class FriendRoomPage : public OpenHostPage
{
public:
void onActivate() override
{
LONGCALL void onActivate(FriendRoomPage * friendRoomPage)
AT(RMCXD_PORT(0x805D8444, 0x806289B8, 0x805D7D20, 0x805C65E0));

onActivate(this);

if (mkw::Net::NetController::Instance()->amITheRoomHost()) {
OpenHostPage::onActivate();
}
}

void onDeactivate() override
{
LONGCALL void onDeactivate(FriendRoomPage * friendRoomPage)
AT(RMCXD_PORT(0x805D84FC, 0x80628A70, 0x805D7DD8, 0x805C6698));

onDeactivate(this);

if (mkw::Net::NetController::Instance()->amITheRoomHost()) {
OpenHostPage::onDeactivate();
}
}

void onRefocus() override
{
LONGCALL void onRefocus(FriendRoomPage * friendRoomPage)
AT(RMCXD_PORT(0x805D8C98, 0x8062920C, 0x805D8574, 0x805C6E34));

onRefocus(this);

if (mkw::Net::NetController::Instance()->amITheRoomHost()) {
OpenHostPage::onRefocus();
}
}

private:
/* 0x044 */ u8 _044[0xDC4 - 0x044];
};

static_assert(sizeof(FriendRoomPage) == 0xDC4);

#endif

} // namespace mkw::UI

#if RMC

extern "C" {
static void FriendRoomPage_onActivate(mkw::UI::FriendRoomPage* friendRoomPage)
{
friendRoomPage->FriendRoomPage::onActivate();
}

static void FriendRoomPage_onDeactivate(mkw::UI::FriendRoomPage* friendRoomPage)
{
friendRoomPage->FriendRoomPage::onDeactivate();
}

static void FriendRoomPage_onRefocus(mkw::UI::FriendRoomPage* friendRoomPage)
{
friendRoomPage->FriendRoomPage::onRefocus();
}
}

#endif
181 changes: 181 additions & 0 deletions payload/import/mkw/ui/page/openHostPage.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
#pragma once

#include "import/cxx.hpp"
#include "import/dwc.h"
#include "import/mkw/system/system.hpp"
#include "import/mkw/ui/multiMenuInputManager.hpp"
#include "import/mkw/ui/section/sectionManager.hpp"
#include "messagePopupPage.hpp"
#include "yesNoPopupPage.hpp"

namespace mkw::UI
{

#if RMC

class OpenHostPage : public Page
{
public:
void onActivate() override
{
EGG::Heap* systemHeap = mkw::System::System::Instance().systemHeap();

s_onOption =
new (systemHeap, 4) MenuInputManager::Handler<OpenHostPage>(
this, &OpenHostPage::onOption
);
MultiControlInputManager* multiControlInputManager =
reinterpret_cast<MultiControlInputManager*>(menuInputManager());
multiControlInputManager->setHandler(
MenuInputManager::InputType::Option, s_onOption
);

s_onYesOrNo = new (systemHeap, 4)
YesNoPage::Handler<OpenHostPage>(this, &OpenHostPage::onYesOrNo);
}

void onDeactivate() override
{
MultiControlInputManager* multiControlInputManager =
reinterpret_cast<MultiControlInputManager*>(menuInputManager());
multiControlInputManager->setHandler(
MenuInputManager::InputType::Option, nullptr
);
delete s_onOption;
s_onOption = nullptr;

delete s_onYesOrNo;
s_onYesOrNo = nullptr;
}

void onRefocus() override
{
transition(resolve());
}

private:
OpenHostPage();

enum class State {
Previous,
Prompt,
Result,
};

State resolve() const
{
switch (s_state) {
case State::Previous: {
break;
}
case State::Prompt: {
return State::Result;
}
case State::Result: {
return State::Previous;
}
}

return s_state;
}

void transition(State state)
{
Section* section = SectionManager::Instance()->currentSection();

if (state == s_state) {
return;
}

switch (state) {
case State::Previous: {
break;
}
case State::Prompt: {
FormatParam formatParam{};
formatParam.strings[0] =
L"Enable Open Host?\n\n"
L"This feature allows players who\n"
L"add your friend code to meet up with you,\n"
L"even if you don't add them back.";

YesNoPopupPage* yesNoPopupPage =
section->page<YesNoPopupPage>(PageId::YesNoPopup);
yesNoPopupPage->reset();
yesNoPopupPage->setWindowMessage(0x19CA, &formatParam);
yesNoPopupPage->configureButton(
0, 0xFAC, nullptr, Animation::None, s_onYesOrNo
);
yesNoPopupPage->configureButton(
1, 0xFAD, nullptr, Animation::None, s_onYesOrNo
);
yesNoPopupPage->setDefaultChoice(1);

push(PageId::YesNoPopup, Animation::Next);
break;
}
case State::Result: {
FormatParam formatParam{};
if (!s_sentOpenHostValue) {
formatParam.strings[0] = L"You have lost connection to\n"
L"the server.\n\n"
L"Please try again later.";
} else {
if (s_enableOpenHost) {
formatParam.strings[0] = L"Open Host is now enabled!";
} else {
formatParam.strings[0] = L"Open Host is now disabled!";
}
}

MessagePopupPage* messagePopupPage =
section->page<MessagePopupPage>(PageId::MessagePopup);
messagePopupPage->reset();
messagePopupPage->setWindowMessage(0x19CA, &formatParam);

push(PageId::MessagePopup, Animation::Next);
break;
}
}

s_state = state;
}

void onOption(u32 /* localPlayerId */)
{
transition(State::Prompt);
}

void onYesOrNo(int choice, void* /* pushButton */)
{
GameSpy::GPConnection* gpConnection = DWC::stpMatchCnt->connection;
if (!gpConnection) {
s_sentOpenHostValue = false;
return;
}
s_sentOpenHostValue = true;

bool enableOpenHost = choice == 0;

char openHostValue[2];
openHostValue[0] = '0' + enableOpenHost;
openHostValue[1] = '\0';
GameSpy::gpiSendLocalInfo(
gpConnection, "\\wwfc_openhost\\", openHostValue
);

s_enableOpenHost = enableOpenHost;
}

static State s_state;
static mkw::UI::MenuInputManager::Handler<OpenHostPage>* s_onOption;
static mkw::UI::YesNoPage::Handler<OpenHostPage>* s_onYesOrNo;
static bool s_enableOpenHost;
static bool s_sentOpenHostValue;
};

static_assert(sizeof(OpenHostPage) == sizeof(Page));

#endif

} // namespace mkw::UI
Loading

0 comments on commit 2e38a2b

Please sign in to comment.