Last active
June 17, 2024 00:13
-
-
Save MCJack123/e3a6b8dfc5cb0e1525252e8e5cd5fa8e to your computer and use it in GitHub Desktop.
Counter-Strike Source Discord RPC program (probably VAC safe, Linux only)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <discord.h> | |
#include <iostream> | |
#include <fstream> | |
#include <string> | |
#include <filesystem> | |
#include <thread> | |
#include <chrono> | |
namespace fs = std::filesystem; | |
static discord::Core* core{}; | |
static discord::Activity activity; | |
static bool connected = true; | |
static int64_t client_id = // ID HERE | |
template<typename T> | |
T getMem_(std::ifstream& handle, uint32_t offset) { | |
T retval; | |
handle.seekg(offset, std::ios::cur); | |
handle.read((char*)&retval, sizeof(T)); | |
//std::cout << "\n"; | |
return retval; | |
} | |
template<> | |
std::string getMem_<std::string>(std::ifstream& handle, uint32_t offset) { | |
std::string retval; | |
handle.seekg(offset, std::ios::cur); | |
std::getline(handle, retval, '\0'); | |
//std::cout << "\n"; | |
return retval; | |
} | |
template<typename T, typename... Args> | |
T getMem_(std::ifstream& handle, uint32_t offset, Args... args) { | |
uint32_t addr = 0; | |
handle.seekg(offset, std::ios::cur); | |
handle.read((char*)&addr, 4); | |
//std::cout << addr << " "; | |
handle.seekg(addr, std::ios::beg); | |
return getMem_<T>(handle, args...); | |
} | |
template<typename T, typename... Args> | |
T getMem(std::ifstream& handle, uint32_t start, Args... args) { | |
handle.seekg(start, std::ios::beg); | |
//std::cout << start << " "; | |
return getMem_<T>(handle, args...); | |
} | |
int main() { | |
std::cout << "Looking for CS: Source...\n"; | |
int pid = 0; | |
fs::path proc("/proc"), pdir; | |
while (!pid) { | |
for (const auto& dir : fs::directory_iterator(proc)) { | |
if (dir.is_directory()) { | |
std::ifstream in(dir.path() / "cmdline"); | |
if (!in) continue; | |
std::string name; | |
std::getline(in, name); | |
in.close(); | |
if (name.find("hl2_linux") != std::string::npos) { | |
pid = std::stoi(dir.path().filename()); | |
pdir = dir; | |
std::cout << "Found PID: " << pid << "\n"; | |
break; | |
} | |
} | |
} | |
if (!pid) std::this_thread::sleep_for(std::chrono::seconds(1)); | |
} | |
std::cout << "Connecting to Discord...\n"; | |
discord::Result result; | |
if ((result = discord::Core::Create(client_id, DiscordCreateFlags_Default, &core)) != discord::Result::Ok) { | |
connected = false; | |
std::cerr << "Could not connect to Discord: " << (int)result << "\n"; | |
return (int)result; | |
} | |
std::cout << "Connected.\n"; | |
activity.SetApplicationId(client_id); | |
activity.SetName("Counter-Strike Source"); | |
activity.SetType(discord::ActivityType::Playing); | |
activity.SetState("Initializing"); | |
activity.GetAssets().SetLargeImage("de_dust"); | |
activity.GetAssets().SetSmallImage("game"); | |
bool ready = false; | |
core->ActivityManager().UpdateActivity(activity, [&ready](discord::Result res){ready = true;}); | |
while (!ready) core->RunCallbacks(); | |
uint32_t GameUI = 0, ServerBrowser = 0, server = 0, client = 0, engine = 0; | |
std::ifstream maps(pdir / "maps"); | |
if (!maps) { | |
std::cerr << "Could not open memory map\n"; | |
return 3; | |
} | |
while (!maps.eof()) { | |
std::string line; | |
std::getline(maps, line); | |
if (line.find("/bin/GameUI.so") != std::string::npos && line.find("r-xp") != std::string::npos) { | |
GameUI = std::stoul(line.substr(0, 8), NULL, 16); | |
std::cout << "GameUI is at " << GameUI << "\n"; | |
} else if (line.find("/bin/ServerBrowser.so") != std::string::npos && line.find("r-xp") != std::string::npos) { | |
ServerBrowser = std::stoul(line.substr(0, 8), NULL, 16); | |
std::cout << "ServerBrowser is at " << ServerBrowser << "\n"; | |
} else if (line.find("/bin/client.so") != std::string::npos && line.find("r-xp") != std::string::npos) { | |
client = std::stoul(line.substr(0, 8), NULL, 16); | |
std::cout << "client is at " << client << "\n"; | |
} else if (line.find("/bin/server.so") != std::string::npos && line.find("r-xp") != std::string::npos) { | |
server = std::stoul(line.substr(0, 8), NULL, 16); | |
std::cout << "server is at " << server << "\n"; | |
} else if (line.find("/bin/engine.so") != std::string::npos && line.find("r-xp") != std::string::npos) { | |
engine = std::stoul(line.substr(0, 8), NULL, 16); | |
std::cout << "engine is at " << engine << "\n"; | |
} | |
} | |
maps.close(); | |
if (GameUI == 0 || ServerBrowser == 0 || server == 0 || client == 0 || engine == 0) { | |
std::cerr << "Could not find required pointers\n"; | |
return 2; | |
} | |
std::ifstream mem(pdir / "mem"); | |
if (!mem) { | |
std::cerr << "Could not open memory\n"; | |
return 3; | |
} | |
while (fs::exists(pdir)) { | |
mem.clear(); | |
std::string serverName = getMem<std::string>(mem, engine, 0x371312, 0x8, 0x0); | |
std::string mapName = getMem<std::string>(mem, engine, 0x2ad692, 0x24, 0x0); | |
std::cout << serverName << " - " << mapName << "\n"; | |
float gameTime = getMem<float>(mem, server, 0x25896b, 0x0, 0x3c, 0x2ac); | |
float roundTime = getMem<float>(mem, server, 0x25934e, 0x2c); | |
uint16_t ctScore = getMem<uint16_t>(mem, server, 0x25896b, 0x0, 0x3c, 0x290); | |
uint16_t tScore = getMem<uint16_t>(mem, server, 0x25896b, 0x0, 0x3c, 0x292); | |
uint32_t health = getMem<uint32_t>(mem, client, 0xbea61c, 0x54, 0x1ac); | |
uint32_t money = getMem<uint32_t>(mem, server, 0xad5a5c, 0x14, 0x1190); | |
std::string team = getMem<std::string>(mem, server, 0x3b34ac, 0x0); | |
std::string state = "Playing as " + team + " (" + std::to_string(ctScore) + "-" + std::to_string(tScore) + ")"; | |
std::string healthstr = std::to_string(health) + " HP - $" + std::to_string(money); | |
activity.GetAssets().SetLargeImage(mapName.c_str()); | |
activity.GetAssets().SetLargeText(mapName.c_str()); | |
activity.GetAssets().SetSmallText(healthstr.c_str()); | |
activity.SetState(state.c_str()); | |
activity.GetTimestamps().SetStart(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - (int64_t)(gameTime * 1000)); | |
activity.GetTimestamps().SetEnd(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - (int64_t)(gameTime * 1000) + (int64_t)(roundTime * 60000)); | |
bool ready = false; | |
core->ActivityManager().UpdateActivity(activity, [&ready](discord::Result res){ | |
if (res == discord::Result::NotRunning) { | |
fprintf(stderr, "Discord disconnected. Restart CraftOS-PC to reconnect.\n"); | |
connected = false; | |
} | |
ready = true; | |
}); | |
while (!ready) core->RunCallbacks(); | |
//std::cout << serverName << " " << mapName << "\n"; | |
std::this_thread::sleep_for(std::chrono::seconds(1)); | |
} | |
return 0; | |
} | |
nvm i found it, it's the Discord Game SDK, you have to download it, and get the cpp files and the dynamic library in it, and build it with those files
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
i'm trying to build this, but i don't know where to find
discord.h