Skip to content

Commit

Permalink
Feat: Added partial modal form support
Browse files Browse the repository at this point in the history
  • Loading branch information
zzz-mimimi committed Jan 1, 2025
1 parent 9f63e50 commit 07b9c8d
Show file tree
Hide file tree
Showing 12 changed files with 202 additions and 3 deletions.
2 changes: 2 additions & 0 deletions LatiteRewrite.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,8 @@
<ClInclude Include="src\sdk\common\network\PacketSender.h" />
<ClInclude Include="src\sdk\common\network\packet\ActorEventPacket.h" />
<ClInclude Include="src\sdk\common\network\packet\CommandRequestPacket.h" />
<ClInclude Include="src\sdk\common\network\packet\ModalFormRequestPacket.h" />
<ClInclude Include="src\sdk\common\network\packet\ModalFormResponsePacket.h" />
<ClInclude Include="src\sdk\common\network\packet\SetScorePacket.h" />
<ClInclude Include="src\sdk\common\network\packet\SetTitlePacket.h" />
<ClInclude Include="src\sdk\common\network\packet\TextPacket.h" />
Expand Down
2 changes: 2 additions & 0 deletions LatiteRewrite.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,8 @@
<ClInclude Include="assets\lang\zh_CN.json" />
<ClInclude Include="assets\lang\zh_TW.json" />
<ClInclude Include="src\client\script\objects\OSScriptingObject.h" />
<ClInclude Include="src\sdk\common\network\packet\ModalFormRequestPacket.h" />
<ClInclude Include="src\sdk\common\network\packet\ModalFormResponsePacket.h" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="LatiteRewrite.rc" />
Expand Down
16 changes: 16 additions & 0 deletions src/client/Latite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1200,4 +1200,20 @@ void Latite::writeServerIP() {
}
}
lastServer = server;
}

void* Latite::networkIdentifier = nullptr;
void* Latite::netEventCallback = nullptr;

void Latite::setNetwork(void* netId, void* netEv) {
networkIdentifier = netId;
netEventCallback = netEv;
}

void* Latite::getNetId() {
return networkIdentifier;
}

void* Latite::getNetEv() {
return netEventCallback;
}
7 changes: 7 additions & 0 deletions src/client/Latite.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ class Latite final : public Listener {
void queueForClientThread(std::function<void()> callback);
void queueForDXRender(std::function<void(ID2D1DeviceContext* ctx)> callback);

static void* networkIdentifier;
static void* netEventCallback;

static void setNetwork(void* netId, void* netEv);
static void* getNetId();
static void* getNetEv();

Latite() = default;
~Latite() = default;

Expand Down
48 changes: 45 additions & 3 deletions src/client/hook/impl/PacketHooks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,16 +19,45 @@ void PacketHooks::PacketSender_sendToServer(SDK::PacketSender* sender, SDK::Pack
return;
}

if (packet->getID() == SDK::PacketID::MODAL_FORM_RESPONSE) {
using MFRP = SDK::ModalFormResponsePacket;
MFRP* pkt = static_cast<MFRP*>(packet);

auto id = PluginManager::Event::Value(L"id");
id.val = (double)pkt->Id;

auto json = PluginManager::Event::Value(L"json");
json.val = L"";

auto cancelreason = PluginManager::Event::Value(L"cancelreason");
cancelreason.val = L"";

if (pkt->Json.has_value()) {
nlohmann::json value = pkt->Json.value();
json.val = util::StrToWStr(value.dump());
}

if (pkt->CancelReason.has_value()) {
cancelreason.val = pkt->CancelReason.value() == MFRP::Reason::UserBusy ? L"UserBusy" : L"UserClosed";
}

PluginManager::Event sEv{ XW("modal-response"), { id, json, cancelreason }, true };

if (Latite::getPluginManager().dispatchEvent(sEv)) return;
}

SendToServerHook->oFunc<decltype(&PacketSender_sendToServer)>()(sender, packet);
}

std::shared_ptr<SDK::Packet> PacketHooks::MinecraftPackets_createPacket(SDK::PacketID packetId) {
auto genPacket = CreatePacketHook->oFunc<decltype(&MinecraftPackets_createPacket)>()(packetId);

return genPacket;
}

void PacketHooks::PacketHandlerDispatcherInstance_handle(void* instance, void* networkIdentifier, void* netEventCallback, std::shared_ptr<SDK::Packet>& packet) {
Latite::setNetwork(networkIdentifier, netEventCallback);

auto& hook = PacketHookArray[(size_t)packet->getID()];

if (Latite::isMainThread()) {
Expand All @@ -50,10 +79,23 @@ void PacketHooks::PacketHandlerDispatcherInstance_handle(void* instance, void* n
PluginManager::Event sEv{ XW("set-score"), { data }, false };
Latite::getPluginManager().dispatchEvent(sEv);
}
else if (packetId == SDK::PacketID::MODAL_FORM_REQUEST) {
auto pkt = std::static_pointer_cast<SDK::ModalFormRequestPacket>(packet);

auto id = PluginManager::Event::Value(L"id");
id.val = (double)pkt->Id;

auto json = PluginManager::Event::Value(L"json");
json.val = util::StrToWStr(pkt->Json);

PluginManager::Event sEv{ XW("modal-request"), { id, json }, false };
Latite::getPluginManager().dispatchEvent(sEv);
}
else if (packetId == SDK::PacketID::TRANSFER) {
PluginManager::Event sEv{ XW("transfer"), {}, false };
Latite::getPluginManager().dispatchEvent(sEv);
} else if (packetId == SDK::PacketID::SET_TITLE) {
}
else if (packetId == SDK::PacketID::SET_TITLE) {
auto pkt = std::static_pointer_cast<SDK::SetTitlePacket>(packet);
auto v1 = PluginManager::Event::Value(L"type");

Expand Down Expand Up @@ -178,4 +220,4 @@ PacketHooks::PacketHooks() {
void PacketHooks::initPacketSender(SDK::PacketSender* sender) {
uintptr_t* vtable = *reinterpret_cast<uintptr_t**>(sender);
SendToServerHook = addTableSwapHook((uintptr_t)(vtable + 2), PacketSender_sendToServer, "PacketSender::sendToServer");
}
}
2 changes: 2 additions & 0 deletions src/client/hook/impl/PacketHooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include "sdk/common/network/packet/SetTitlePacket.h"
#include "sdk/common/network/packet/TextPacket.h"
#include "sdk/common/network/packet/SetScorePacket.h"
#include "sdk/common/network/packet/ModalFormRequestPacket.h"
#include "sdk/common/network/packet/ModalFormResponsePacket.h"

class PacketHooks : public HookGroup {
static void* SetTitlePacket_readExtended(SDK::SetTitlePacket* pkt, void* b, void* c);
Expand Down
2 changes: 2 additions & 0 deletions src/client/script/PluginManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,8 @@ void PluginManager::initListeners()
eventListeners[L"pre-move"] = {};
eventListeners[L"post-move"] = {};
eventListeners[L"set-score"] = {};
eventListeners[L"modal-request"] = {};
eventListeners[L"modal-response"] = {};
}

void PluginManager::unloadScript(std::shared_ptr<JsPlugin> ptr) {
Expand Down
30 changes: 30 additions & 0 deletions src/client/script/objects/GameScriptingObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "../class/impl/game/JsPlayerClass.h"
#include "../class/impl/game/JsLocalPlayerClass.h"
#include <sdk/common/network/packet/CommandRequestPacket.h>
#include <sdk/common/network/packet/ModalFormRequestPacket.h>
#include <client/script/class/impl/game/JsBlock.h>
#include <client/script/class/impl/JsVec3.h>
#include "sdk/common/network/MinecraftPackets.h"
Expand All @@ -44,6 +45,7 @@ void GameScriptingObject::initialize(JsContextRef ctx, JsValueRef parentObj) {
Chakra::DefineFunc(object, captureCursor, XW("captureCursor"));
Chakra::DefineFunc(object, releaseCursor, XW("releaseCursor"));
Chakra::DefineFunc(object, isKeyDown, XW("isKeyDown"));
Chakra::DefineFunc(object, openModalForm, XW("openModalForm"));
}

void GameScriptingObject::createWorldObject() {
Expand Down Expand Up @@ -194,6 +196,34 @@ JsValueRef GameScriptingObject::dimensionGetBlock(JsValueRef callee, bool isCons
return scr->getClass<JsBlock>()->construct(block, false);
}

JsValueRef GameScriptingObject::openModalForm(JsValueRef callee, bool isConstructor, JsValueRef* arguments, unsigned short argCount, void* callbackState) {
if (!Chakra::VerifyArgCount(argCount, 3)) return JS_INVALID_REFERENCE;
if (!Chakra::VerifyParameters({ {arguments[1], JsValueType::JsNumber} , {arguments[2], JsValueType::JsObject} })) return JS_INVALID_REFERENCE;

JsValueRef JSON = Chakra::GetProperty(Chakra::GetGlobalObject(), L"JSON");
JsValueRef stringify = Chakra::GetProperty(JSON, L"stringify");

JsValueRef stringifyArgs[2] = { JSON, arguments[2] };
JsValueRef result;

Chakra::CallFunction(stringify, stringifyArgs, 2, &result);

int packetId = Chakra::GetInt(arguments[1]);
std::string json = util::WStrToStr(Chakra::GetString(result));

using MFRP = SDK::ModalFormRequestPacket;

std::shared_ptr<MFRP> packet = std::static_pointer_cast<MFRP>(SDK::MinecraftPackets::createPacket(SDK::PacketID::MODAL_FORM_REQUEST));

packet->Id = packetId;
packet->Json = json;

memory::callVirtual<void>(packet->handler, 1, (void*)Latite::getNetId(), (void*)Latite::getNetEv(), (std::shared_ptr<MFRP>&)packet);

return Chakra::GetUndefined();
}


JsValueRef GameScriptingObject::getMousePosCallback(JsValueRef callee, bool isConstructor, JsValueRef* arguments, unsigned short argCount, void* callbackState) {
JsScript* script = JsScript::getThis();

Expand Down
2 changes: 2 additions & 0 deletions src/client/script/objects/GameScriptingObject.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class GameScriptingObject : public ScriptingObject {
JsValueRef* arguments, unsigned short argCount, void* callbackState);
static JsValueRef CALLBACK isKeyDown(JsValueRef callee, bool isConstructor,
JsValueRef* arguments, unsigned short argCount, void* callbackState);
static JsValueRef CALLBACK openModalForm(JsValueRef callee, bool isConstructor,
JsValueRef* arguments, unsigned short argCount, void* callbackState);
public:
inline static int objectID = -1;
GameScriptingObject(int id) : ScriptingObject(id, L"game") { GameScriptingObject::objectID = id; }
Expand Down
2 changes: 2 additions & 0 deletions src/sdk/common/network/Packet.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ namespace SDK {
COMMAND_REQUEST = 0x4D,
TOAST_REQUEST = 0xBA,
SET_SCORE = 0x6c,
MODAL_FORM_REQUEST = 0x64,
MODAL_FORM_RESPONSE = 0x65,
COUNT,
};

Expand Down
11 changes: 11 additions & 0 deletions src/sdk/common/network/packet/ModalFormRequestPacket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#pragma once
#include "../Packet.h"
#include "sdk/String.h"

namespace SDK {
class ModalFormRequestPacket : public Packet {
public:
unsigned int Id;
std::string Json;
};
}
81 changes: 81 additions & 0 deletions src/sdk/common/network/packet/ModalFormResponsePacket.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#pragma once
#include "../Packet.h"
#include "sdk/String.h"

namespace SDK {

class ModalFormResponsePacket : public Packet {
public:

class Value {
public:
class CZString {
public:
char const* cstr_;
};

enum class Type : int {
Null = 0x0,
Int = 0x1,
Uint = 0x2,
Real = 0x3,
String = 0x4,
Boolean = 0x5,
Array = 0x6,
Object = 0x7,
};

union {
int64_t int_;
uint64_t uint_;
double real_;
bool bool_;
char* str_;
std::map<CZString, Value>* map_;
} value_;

Type type_ : 8;

// Function to serialize the Value to JSON
friend void to_json(nlohmann::json& result, const Value& v) {
result = nullptr;
switch (v.type_) {
case Type::Int:
result = v.value_.int_;
break;
case Type::Uint:
result = v.value_.uint_;
break;
case Type::Real:
result = v.value_.real_;
break;
case Type::String:
result = v.value_.str_;
break;
case Type::Boolean:
result = v.value_.bool_;
break;
case Type::Array:
// result = nlohmann::json::array();
// TODO: Implement array parsing
break;
case Type::Object:
// result = nlohmann::json::object();
// TODO: Implement object parsing
break;
}
};
};

enum class Reason : signed char {
UserClosed,
UserBusy
};

unsigned int Id;
std::optional<Value> Json;
std::optional<Reason> CancelReason;

};

}

0 comments on commit 07b9c8d

Please sign in to comment.