Skip to content

Instantly share code, notes, and snippets.

@MCJack123
Last active June 17, 2024 00:13
Show Gist options
  • Save MCJack123/e3a6b8dfc5cb0e1525252e8e5cd5fa8e to your computer and use it in GitHub Desktop.
Save MCJack123/e3a6b8dfc5cb0e1525252e8e5cd5fa8e to your computer and use it in GitHub Desktop.
Counter-Strike Source Discord RPC program (probably VAC safe, Linux only)
#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;
}
@Inconn
Copy link

Inconn commented Jun 17, 2024

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