From 439e4f388f9ccc74c23e6889b3f068fbe39048df Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Sat, 27 Sep 2025 21:24:23 +0700 Subject: [PATCH 01/10] as --- .../Modules/TotemCounter/TotemCounter.cpp | 102 ++++++++++++++++-- 1 file changed, 95 insertions(+), 7 deletions(-) diff --git a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp index 51cad938d..67c500d62 100644 --- a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp +++ b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp @@ -2,36 +2,51 @@ #include "Events/Game/TickEvent.hpp" - +#include "SDK/Client/Network/Packet/EntityEventPacket.hpp" +#include "Modules/ClickGUI/ClickGUI.hpp" void TotemCounter::onEnable() { Listen(this, TickEvent, &TotemCounter::onTick) Listen(this, RenderEvent, &TotemCounter::onRender) + Listen(this, PacketEvent, &TotemCounter::onPacketEvent) + + popsById.clear(); + Module::onEnable(); } void TotemCounter::onDisable() { Deafen(this, TickEvent, &TotemCounter::onTick) Deafen(this, RenderEvent, &TotemCounter::onRender) + Deafen(this, PacketEvent, &TotemCounter::onPacketEvent) Module::onDisable(); } void TotemCounter::defaultConfig() { setDef("text", (std::string)"Totems: {value}"); + setDef("textUsed", (std::string)"Pops: {value}"); setDef("onlyRenderWhenHoldingTotem", false); + setDef("mode", (std::string)"Current"); + setDef("notifyOnPop", false); + setDef("listenForOthers", false); Module::defaultConfig("all"); - } void TotemCounter::settingsRender(float settingsOffset) { initSettingsPage(); - addToggle("Only render when holding totem.", "", "onlyRenderWhenHoldingTotem"); + addDropdown("Mode", "Choose the working mode.", std::vector{"Current", "Pop", "Both"}, "mode", true); + addToggle("Text Label: Totem Held Only", "Only show the label text when holding a totem.", "onlyRenderWhenHoldingTotem"); defaultAddSettings("main"); extraPadding(); addHeader("Text"); - defaultAddSettings("text"); + addTextBox("Normal Format", "Use {value} for the value.", 0, "text"); + addTextBox("Pops Format", "Use {value} for the value.", 0, "textUsed"); + addSlider("Text Scale", "", "textscale", 2.0f); + addDropdown("Text Alignment", "", std::vector{"Left", "Center", "Right"}, "textalignment", true); + addToggle("Text Shadow", "Displays a shadow under the text", "textShadow"); + addConditionalSlider(getOps("textShadow"), "Shadow Offset", "How far the shadow will be.", "textShadowOffset", 0.02f, 0.001f); extraPadding(); addHeader("Colors"); @@ -41,6 +56,13 @@ void TotemCounter::settingsRender(float settingsOffset) { addHeader("Misc"); defaultAddSettings("misc"); + addHeader("Chat Notfications"); + addButton("Clear Stored Pops", "I'm keeping this here until I figure out a proper way for this.", "Click Here", [this](){popsById.clear();}); + addToggle("Notify on Pop", "Notifies in chat when a totem pop happens", "notifyOnPop"); + addConditionalToggle(getOps("notifyOnPop") ,"Notifier: Listen for Others", "Notifies in chat when other player(s) pop their totems as well.", "listenForOthers"); + extraPadding(); + + FlarialGUI::UnsetScrollView(); resetPadding(); } @@ -100,11 +122,77 @@ void TotemCounter::onTick(TickEvent& event) { totems = lastTotemCount; } + + if (SDK::getCurrentScreen() == "progress_screen") popsById.clear(); +} + +void TotemCounter::onPacketEvent(PacketEvent& event) +{ + auto eep = reinterpret_cast(event.getPacket()); + // is enabled, notification on, packet is actorevent, ID is talismanactivate, server is not the hive (is there even a minigame that actually uses it?) + if (!isEnabled() || !getOps("notifyOnPop") || eep->getId() != MinecraftPacketIds::ActorEvent || SDK::getServerIP() == "geo.hivebedrock.network") return; + + auto id = eep->RuntimeID; + auto actor = SDK::clientInstance->getLocalPlayer()->getLevel()->getRuntimeEntity(id, false); + if (!actor) return Logger::debug("what the skibidi toilet"); + + const std::string baseName = Utils::sanitizeName(actor->getNametag() ? *actor->getNametag() : std::string("blahaj")); + const std::string playerName = (id == SDK::clientInstance->getLocalPlayer()->getRuntimeIDComponent()->runtimeID) ? std::string("You") : baseName; + + if (eep->EventID == ActorEvent::TalismanActivate) + { + // Workaround until I figure out how to properly filter packets. + static std::unordered_map lastPopAt; + const auto now = std::chrono::steady_clock::now(); + auto& t = lastPopAt[id]; + if (now - t < std::chrono::milliseconds(100)) return; + t = now; + + int pops = ++popsById[id]; + + SDK::clientInstance->getGuiData()->displayClientMessage("[§bTo§dte§fm Co§dunt§ber§r] " + playerName + " popped §7" + std::to_string(pops) + "§r totem" + (pops > 1 ? "s" : "") + "."); + } else if (eep->EventID == ActorEvent::Death) + { + SDK::clientInstance->getGuiData()->displayClientMessage("[§bTo§dte§fm Co§dunt§ber§r] " + playerName + " died after popping §7" + std::to_string(popsById[id]) + "§r totems."); + popsById[id] = 0; + } } void TotemCounter::onRender(RenderEvent& event) { - if (!this->isEnabled() || !shouldRender) return; + if (!this->isEnabled() || !shouldRender || SDK::getCurrentScreen() != "hud_screen") return; + + // you wanted this + auto replaceValueToken = [](const std::string& tmpl, const std::string& val) -> std::string { + std::string upper; + upper.reserve(tmpl.size()); + for (char c: tmpl) upper += (char)std::toupper(c); + const std::string search = "{VALUE}"; + size_t pos = upper.find(search); + std::string out = tmpl; + if (pos != std::string::npos) out.replace(pos, search.length(), val); + return out; + }; + + std::string mode = "Current"; + if (this->settings.getSettingByName("mode") != nullptr) mode = getOps("mode"); + + std::string finalText; + + const std::string playerPops = SDK::clientInstance->getLocalPlayer() ? std::to_string(popsById[SDK::clientInstance->getLocalPlayer()->getRuntimeIDComponent()->runtimeID]) : "0"; + + if (mode == "Current") { + std::string tmpl = this->settings.getSettingByName("text") != nullptr ? getOps("text") : std::string(); + finalText = replaceValueToken(tmpl, FlarialGUI::cached_to_string(totems)); + } else if (mode == "Pop") { + std::string popsTmpl = this->settings.getSettingByName("textUsed") != nullptr ? getOps("textUsed") : std::string(); + finalText = replaceValueToken(popsTmpl, playerPops); + } else { // Both + std::string tmpl = this->settings.getSettingByName("text") != nullptr ? getOps("text") : std::string(); + std::string popsTmpl = this->settings.getSettingByName("textUsed") != nullptr ? getOps("textUsed") : std::string(); + finalText = replaceValueToken(tmpl, FlarialGUI::cached_to_string(totems)); + finalText += "\n"; // genius + finalText += replaceValueToken(popsTmpl, playerPops); + } - auto totemsStr = FlarialGUI::cached_to_string(totems); - this->normalRender(35, totemsStr); + normalRenderCore(35, finalText); } From 7ac1397bddaa39e8bb721dc63e51b07e5b67bdb7 Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Sat, 27 Sep 2025 21:25:38 +0700 Subject: [PATCH 02/10] dfjilskdjf' --- src/Client/Module/Modules/TotemCounter/TotemCounter.hpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp b/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp index 7c46e9fc4..0dfd775a2 100644 --- a/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp +++ b/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp @@ -1,8 +1,10 @@ #pragma once #include "../Module.hpp" +#include "Events/Game/HandleEntityEvent.hpp" #include "Events/Game/TickEvent.hpp" #include "Events/Render/RenderEvent.hpp" +#include "SDK/Client/Network/Packet/EntityEventPacket.hpp" class TotemCounter : public Module { @@ -13,6 +15,8 @@ class TotemCounter : public Module { int lastTotemCount = 0; int tickCounter = 0; + std::unordered_map popsById; + public: TotemCounter() : Module("Totem Counter", "Counts how many totems you have\nin your inventory.", @@ -31,4 +35,6 @@ class TotemCounter : public Module { void onTick(TickEvent& event); void onRender(RenderEvent& event); -}; \ No newline at end of file + + void onPacketEvent(PacketEvent& event); +}; From b04e2333451caf13580fb95914ac37e5ce0c0468 Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Sat, 27 Sep 2025 21:26:50 +0700 Subject: [PATCH 03/10] Update TotemCounter.cpp --- src/Client/Module/Modules/TotemCounter/TotemCounter.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp index 67c500d62..bc3144aab 100644 --- a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp +++ b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp @@ -150,10 +150,11 @@ void TotemCounter::onPacketEvent(PacketEvent& event) int pops = ++popsById[id]; - SDK::clientInstance->getGuiData()->displayClientMessage("[§bTo§dte§fm Co§dunt§ber§r] " + playerName + " popped §7" + std::to_string(pops) + "§r totem" + (pops > 1 ? "s" : "") + "."); + SDK::clientInstance->getGuiData()->displayClientMessage("[§cTotem Counter§r] " + playerName + " popped §7" + std::to_string(pops) + "§r totem" + (pops > 1 ? "s" : "") + "."); } else if (eep->EventID == ActorEvent::Death) { - SDK::clientInstance->getGuiData()->displayClientMessage("[§bTo§dte§fm Co§dunt§ber§r] " + playerName + " died after popping §7" + std::to_string(popsById[id]) + "§r totems."); + if (popsById[id] == 0 || (!getOps("listenForOthers") && id != SDK::clientInstance->getLocalPlayer()->getRuntimeIDComponent()->runtimeID)) return; + SDK::clientInstance->getGuiData()->displayClientMessage("[§cTotem Counter§r] " + playerName + " died after popping §7" + std::to_string(popsById[id]) + "§r totems."); popsById[id] = 0; } } From b7e0e490436fefc9470a22ae4fcf06364cadcd5d Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Sat, 27 Sep 2025 21:32:15 +0700 Subject: [PATCH 04/10] done --- src/Client/Module/Modules/TotemCounter/TotemCounter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp index bc3144aab..8d4f2c240 100644 --- a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp +++ b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp @@ -154,7 +154,7 @@ void TotemCounter::onPacketEvent(PacketEvent& event) } else if (eep->EventID == ActorEvent::Death) { if (popsById[id] == 0 || (!getOps("listenForOthers") && id != SDK::clientInstance->getLocalPlayer()->getRuntimeIDComponent()->runtimeID)) return; - SDK::clientInstance->getGuiData()->displayClientMessage("[§cTotem Counter§r] " + playerName + " died after popping §7" + std::to_string(popsById[id]) + "§r totems."); + SDK::clientInstance->getGuiData()->displayClientMessage("[§cTotem Counter§r] " + playerName + " died after popping §7" + std::to_string(popsById[id]) + "§r totem" + (popsById[id] > 1 ? "s" : "") + "."); popsById[id] = 0; } } From e96a81b13b1058f0cacaece07406db074d00b12f Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Sat, 27 Sep 2025 22:26:54 +0700 Subject: [PATCH 05/10] deleting this fork for good --- src/SDK/Client/Level/Level.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/SDK/Client/Level/Level.hpp b/src/SDK/Client/Level/Level.hpp index 55f7ec320..ac34114ef 100644 --- a/src/SDK/Client/Level/Level.hpp +++ b/src/SDK/Client/Level/Level.hpp @@ -144,4 +144,11 @@ class Level { std::string getWorldFolderName() { return hat::member_at(this, GET_OFFSET("Level::worldFolderName")); } std::vector getRuntimeActorList(); + + Actor* getRuntimeEntity(uint64_t actorId, bool getRemoved) + { + Logger::info("boobs"); + static auto off = GET_OFFSET("Level::getRuntimeEntity"); + return Memory::CallVFuncI(off, this, actorId, getRemoved); + } }; From 4c40744675c15cddd2dfed4a0eb3038c9dfd5444 Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Sat, 27 Sep 2025 22:29:43 +0700 Subject: [PATCH 06/10] not a good idea to spam logs --- src/SDK/Client/Level/Level.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SDK/Client/Level/Level.hpp b/src/SDK/Client/Level/Level.hpp index ac34114ef..418619494 100644 --- a/src/SDK/Client/Level/Level.hpp +++ b/src/SDK/Client/Level/Level.hpp @@ -147,7 +147,6 @@ class Level { Actor* getRuntimeEntity(uint64_t actorId, bool getRemoved) { - Logger::info("boobs"); static auto off = GET_OFFSET("Level::getRuntimeEntity"); return Memory::CallVFuncI(off, this, actorId, getRemoved); } From 6c2a734a1519f0aa9077c0d60aabf8233a572656 Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Sun, 28 Sep 2025 16:41:36 +0700 Subject: [PATCH 07/10] i wanna have hrt --- src/Client/Module/Modules/TotemCounter/TotemCounter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp index 8d4f2c240..d8cccdaf4 100644 --- a/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp +++ b/src/Client/Module/Modules/TotemCounter/TotemCounter.cpp @@ -2,7 +2,6 @@ #include "Events/Game/TickEvent.hpp" -#include "SDK/Client/Network/Packet/EntityEventPacket.hpp" #include "Modules/ClickGUI/ClickGUI.hpp" void TotemCounter::onEnable() { From e7e62e1c4b93efa5221deb724552e8f91449b640 Mon Sep 17 00:00:00 2001 From: prathfr <89528625+prathfr@users.noreply.github.com> Date: Sun, 28 Sep 2025 23:48:57 +0530 Subject: [PATCH 08/10] dude --- src/Client/Module/Modules/TotemCounter/TotemCounter.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp b/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp index 0dfd775a2..e0710b2f9 100644 --- a/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp +++ b/src/Client/Module/Modules/TotemCounter/TotemCounter.hpp @@ -1,7 +1,6 @@ #pragma once #include "../Module.hpp" -#include "Events/Game/HandleEntityEvent.hpp" #include "Events/Game/TickEvent.hpp" #include "Events/Render/RenderEvent.hpp" #include "SDK/Client/Network/Packet/EntityEventPacket.hpp" From 1f705613104c6ba4d7e361811e689a16f9af0529 Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Mon, 29 Sep 2025 07:25:47 +0700 Subject: [PATCH 09/10] getRuntimeEntity offset for .100 --- src/Utils/Memory/Game/Offset/OffsetInit.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Utils/Memory/Game/Offset/OffsetInit.cpp b/src/Utils/Memory/Game/Offset/OffsetInit.cpp index f1bd25c3a..296aac536 100644 --- a/src/Utils/Memory/Game/Offset/OffsetInit.cpp +++ b/src/Utils/Memory/Game/Offset/OffsetInit.cpp @@ -9,6 +9,7 @@ void OffsetInit::init21100() { ADD_OFFSET("Level::hitResult", 0x1E8); ADD_OFFSET("Level::getPlayerMap", 0x4E8); + ADD_OFFSET("Level::getRuntimeEntity", 60); ADD_OFFSET("NetworkSystem::remoteConnectorComposite", 0xF0); ADD_OFFSET("MinecraftGame::textureGroup", 0x758); From 6abecca92613cd93a4761f6ae6f29a3e633d5775 Mon Sep 17 00:00:00 2001 From: Anh Nguyen <94160753+AnhNguyenlost13@users.noreply.github.com> Date: Tue, 30 Sep 2025 08:29:07 +0700 Subject: [PATCH 10/10] Offsets down to 1.21.50 --- src/Utils/Memory/Game/Offset/OffsetInit.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Utils/Memory/Game/Offset/OffsetInit.cpp b/src/Utils/Memory/Game/Offset/OffsetInit.cpp index 296aac536..3331f8123 100644 --- a/src/Utils/Memory/Game/Offset/OffsetInit.cpp +++ b/src/Utils/Memory/Game/Offset/OffsetInit.cpp @@ -72,6 +72,7 @@ void OffsetInit::init2180() { ADD_OFFSET("Level::hitResult", 0x250); ADD_OFFSET("Level::getPlayerMap", 0x960); ADD_OFFSET("Level::worldFolderName", 0x2C0); + ADD_OFFSET("Level::getRuntimeEntity", 58); ADD_OFFSET("ChatScreenController::refreshChatMessages", 0xC80); } @@ -171,6 +172,8 @@ void OffsetInit::init2150() { ADD_OFFSET("Dimension::weather", 0x1D0); ADD_OFFSET("Weather::rainLevel", 0x38); ADD_OFFSET("Weather::lightningLevel", 0x40); + + ADD_OFFSET("Level::getRuntimeEntity", 57); } void OffsetInit::init2140() {