21 Commits
Author SHA1 Message Date
Dusk-92 09d3d7f34b release v1.3 2026-09-02 15:54:32 +02:00
Dusk-92 86860a7fad Prepare WowPresence v1.3 release notes 2026-09-02 15:50:52 +02:00
Dusk-92 9dfe3679d7 Prepare WowPresence v1.3 workflow 2026-09-02 15:50:37 +02:00
Dusk-92 08e096a8b6 Document Discord privacy flag presets 2026-09-02 15:26:51 +02:00
Dusk-92 10e25cc25f Omit empty Discord activity fields 2026-09-02 15:20:04 +02:00
Dusk-92 d4c4f0eef3 Publish Discord details test prerelease 2026-09-02 15:07:51 +02:00
Dusk-92 c4d0d5fee6 Default test broadcast mask to all details 2026-09-02 15:07:29 +02:00
Dusk-92 f8886e15aa Accept any shared character detail 2026-09-02 15:07:20 +02:00
Dusk-92 35a94d6b49 Add independent Race broadcast flag 2026-09-02 15:07:07 +02:00
Dusk-92 9f50681798 Clarify Discord Application ID setup wording 2026-09-02 09:28:30 +02:00
Dusk-92 699b158fdf Move OctoWoW Application ID below example 2026-09-02 09:27:32 +02:00
Dusk-92 05376fabd2 Link Modernization Tool in README 2026-09-02 09:16:18 +02:00
Dusk-92 6f11db08d7 Clarify release asset in README 2026-09-02 09:13:36 +02:00
Dusk-92 ee71b4364c release v1.2 2026-09-02 09:10:52 +02:00
Dusk-92 f2623c33fd Use curated v1.2 release notes 2026-09-02 09:10:43 +02:00
Dusk-92 a63a7b5a48 release v1.2 2026-09-02 09:09:47 +02:00
Dusk-92 a4e0b7afcf Update v1.2 release notes 2026-09-02 09:09:38 +02:00
Dusk-92 05dc4094a0 Publish only the WowPresence ZIP release asset 2026-09-02 09:06:14 +02:00
Dusk-92 e27c7334bc release v1.2 2026-09-02 09:03:41 +02:00
Dusk-92 fdb3126d1f Improve WoW process detection logging 2026-09-02 09:00:56 +02:00
Dusk-92 4576605dce Document OctoWoW Discord Application ID 2026-09-01 20:10:15 +02:00
6 changed files with 118 additions and 41 deletions
+5 -9
View File
@@ -72,20 +72,18 @@ jobs:
dist/WowPresence.zip dist/WowPresence.zip
if-no-files-found: error if-no-files-found: error
- name: Create GitHub Release v1.2 - name: Create GitHub Release v1.3
if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.head_commit.message == 'release v1.2' }} if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.head_commit.message == 'release v1.3' }}
uses: softprops/action-gh-release@v3 uses: softprops/action-gh-release@v3
with: with:
tag_name: v1.2 tag_name: v1.3
target_commitish: ${{ github.sha }} target_commitish: ${{ github.sha }}
files: | files: |
dist/WowPresence.dll
dist/WowPresence.exe
dist/WowPresence.zip dist/WowPresence.zip
fail_on_unmatched_files: true fail_on_unmatched_files: true
name: "WowPresence v1.2" name: "WowPresence v1.3"
body_path: RELEASE_NOTES.md body_path: RELEASE_NOTES.md
generate_release_notes: true generate_release_notes: false
make_latest: true make_latest: true
- name: Create GitHub Release - name: Create GitHub Release
@@ -93,8 +91,6 @@ jobs:
uses: softprops/action-gh-release@v3 uses: softprops/action-gh-release@v3
with: with:
files: | files: |
dist/WowPresence.dll
dist/WowPresence.exe
dist/WowPresence.zip dist/WowPresence.zip
fail_on_unmatched_files: true fail_on_unmatched_files: true
name: "WowPresence ${{ github.ref_name }}" name: "WowPresence ${{ github.ref_name }}"
+64 -11
View File
@@ -44,7 +44,7 @@ After extraction, the relevant files should look like this:
The runtime JSON and log files are created automatically inside the same `WowPresence` folder. The runtime JSON and log files are created automatically inside the same `WowPresence` folder.
When WowPresence is installed through **Modernization Tool**, the same binaries automatically use: When WowPresence is installed through the **[Modernization Tool](https://github.com/Dusk-92/Modernization-Tool)**, the same binaries automatically use:
```text ```text
<WoW folder>\.modernization_tool\WowPresence\ <WoW folder>\.modernization_tool\WowPresence\
@@ -54,9 +54,8 @@ instead. No separate build is required.
## 🛰️ Discord Application ID ## 🛰️ Discord Application ID
WowPresence intentionally does **not** include a server-specific Discord Application ID. To configure your own Discord Application ID:
To create yours:
1. Open the **Discord Developer Portal**: https://discord.com/developers/applications 1. Open the **Discord Developer Portal**: https://discord.com/developers/applications
2. Create a **New Application**. 2. Create a **New Application**.
@@ -75,6 +74,14 @@ Example:
123456789012345678 123456789012345678
``` ```
For **OctoWoW**, you can use the preconfigured Discord Application ID:
```text
1544072796098011176
```
This is the same Application ID automatically configured by **Modernization Tool**.
No Discord Client Secret, bot token or bot account is used or required. No Discord Client Secret, bot token or bot account is used or required.
If `discord_application_id` is missing or invalid, Rich Presence remains disabled and the reason is written to `WowPresence\WowPresence.log`. If `discord_application_id` is missing or invalid, Rich Presence remains disabled and the reason is written to `WowPresence\WowPresence.log`.
@@ -155,29 +162,75 @@ Runtime files are kept together in one of these locations:
If the Modernization Tool managed folder exists, WowPresence automatically prefers it. Otherwise it uses the standalone `WowPresence` folder. If the Modernization Tool managed folder exists, WowPresence automatically prefers it. Otherwise it uses the standalone `WowPresence` folder.
## 🔒 Privacy flags ## 🔒 Discord Rich Presence privacy
The included file: WowPresence lets you choose exactly which character details are shown on Discord.
For a standalone installation, edit:
```text ```text
WowPresence\discord_broadcast_flags WowPresence\discord_broadcast_flags
``` ```
controls which character details are published to Discord. When WowPresence is installed through **Modernization Tool**, the equivalent file is stored in:
```text
.modernization_tool\WowPresence\discord_broadcast_flags
```
Modernization Tool provides checkboxes for these options, so manual bitmask editing is normally only needed for standalone WowPresence installations.
### Available fields
Each field has its own value:
| Value | Field | | Value | Field |
| ---: | --- | | ---: | --- |
| 1 | Name | | 1 | Character Name |
| 2 | Guild | | 2 | Guild |
| 4 | Faction | | 4 | Faction |
| 8 | Class | | 8 | Class |
| 16 | Level | | 16 | Level |
| 32 | Zone | | 32 | Zone |
| 63 | All fields | | 64 | Race |
The release package uses `63` by default. To display multiple fields, **add their values together** and put the result in `discord_broadcast_flags`.
If the file is deleted, WowPresence also defaults to all supported fields. ### Examples
| Display | Value |
| --- | ---: |
| Nothing | 0 |
| Character Name only | 1 |
| Faction + Class | 12 |
| Race only | 64 |
| Race + Faction + Class | 76 |
| Character Name + Level + Zone | 49 |
| All character details | 127 |
Example — to display **Race + Faction + Class**:
```text
Race = 64
Faction = 4
Class = 8
64 + 4 + 8 = 76
```
Then set:
```text
76
```
inside `discord_broadcast_flags`.
The default configuration uses `127`, which enables all supported character details.
WowPresence reads this setting while the game is running, so changes should normally appear on Discord automatically within a few seconds.
If the file is missing or contains an invalid value, WowPresence falls back to all supported fields.
## 🛡️ Administrator privileges ## 🛡️ Administrator privileges
@@ -206,7 +259,7 @@ GitHub Actions builds:
The ZIP includes the ready-to-edit `WowPresence` configuration folder. The ZIP includes the ready-to-edit `WowPresence` configuration folder.
Tags matching `v*` can publish these files as a GitHub Release. Tags matching `v*` publish `WowPresence.zip` as the GitHub Release asset.
## 📜 Project identity & licensing ## 📜 Project identity & licensing
+17 -11
View File
@@ -1,16 +1,22 @@
# WowPresence v1.2 # WowPresence v1.3
## Changes ## What's New
- Reworked zone detection to use the player's real AreaTable ID. - Added independent privacy control for:
- Zone names are now resolved from `AreaTable.dbc` instead of selecting the first plausible string from several client addresses. - Character Name
- Prevents internal map/area tokens such as `H32D` and `HLVA` from being published as Discord zone names. - Guild
- Uses the client's active localized AreaTable name when available, with a safe populated-locale fallback. - Race
- Keeps WowPresence fully standalone; ClassicAPI is not required. - Faction
- Modernization Tool installations continue to use `.modernization_tool\WowPresence\` automatically. - Class
- Level
- Zone
- Added a dedicated Race flag.
- Full detail mask is now `127`.
- Fixed Discord Rich Presence combinations that previously failed when Name, Zone or Level were not shared.
- Race is no longer always shown and can now be disabled independently.
- Improved handling of empty Discord Rich Presence fields.
- Updated README with standalone privacy configuration examples.
## Included ## Included
- `WowPresence.dll` - `WowPresence.zip` — ready-to-install package containing `WowPresence.dll`, `WowPresence.exe`, and the WowPresence configuration folder.
- `WowPresence.exe`
- `WowPresence.zip` ready-to-install standalone package
+1 -1
View File
@@ -1 +1 @@
63 127
+4 -2
View File
@@ -75,7 +75,8 @@
#define SHARE_CLASS 8u #define SHARE_CLASS 8u
#define SHARE_LEVEL 16u #define SHARE_LEVEL 16u
#define SHARE_ZONE 32u #define SHARE_ZONE 32u
#define SHARE_ALL 63u #define SHARE_RACE 64u
#define SHARE_ALL 127u
static const uintptr_t kPlayerNameLocations[] = { static const uintptr_t kPlayerNameLocations[] = {
0x00C27FC8u, 0x00C27D88u, 0x00C27FD8u, 0 0x00C27FC8u, 0x00C27D88u, 0x00C27FD8u, 0
@@ -751,7 +752,8 @@ static void publish_character_snapshot(void) {
collect_character_snapshot(&snapshot); collect_character_snapshot(&snapshot);
mask = load_share_mask(); mask = load_share_mask();
race_text = snapshot.in_world ? label_for_id(kRaceLabels, snapshot.race_id) : ""; race_text = (snapshot.in_world && (mask & SHARE_RACE))
? label_for_id(kRaceLabels, snapshot.race_id) : "";
class_text = (snapshot.in_world && (mask & SHARE_CLASS)) class_text = (snapshot.in_world && (mask & SHARE_CLASS))
? label_for_id(kClassLabels, snapshot.class_id) : ""; ? label_for_id(kClassLabels, snapshot.class_id) : "";
faction_text = (snapshot.in_world && (mask & SHARE_FACTION)) faction_text = (snapshot.in_world && (mask & SHARE_FACTION))
+27 -7
View File
@@ -5,7 +5,7 @@
* - is started automatically by WowPresence.dll after WoW is running * - is started automatically by WowPresence.dll after WoW is running
* - reads the standalone WowPresence folder or the Modernization Tool managed folder * - reads the standalone WowPresence folder or the Modernization Tool managed folder
* - publishes Discord Rich Presence over the local Discord IPC named pipe * - publishes Discord Rich Presence over the local Discord IPC named pipe
* - exits when WoW_Modernized.exe exits * - exits when the target WoW process exits
*/ */
#define WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN
#include <windows.h> #include <windows.h>
@@ -293,7 +293,9 @@ static int load_status(Status *status) {
json_string(json, "class", status->class_name, sizeof(status->class_name)); json_string(json, "class", status->class_name, sizeof(status->class_name));
json_string(json, "race", status->race, sizeof(status->race)); json_string(json, "race", status->race, sizeof(status->race));
json_int(json, "level", &status->level); json_int(json, "level", &status->level);
return status->name[0] || status->zone[0] || status->level > 0; return status->name[0] || status->zone[0] || status->level > 0 ||
status->guild[0] || status->faction[0] || status->class_name[0] ||
status->race[0];
} }
static int rpc_read_packet(HANDLE pipe, char *payload, size_t payload_size) { static int rpc_read_packet(HANDLE pipe, char *payload, size_t payload_size) {
@@ -402,9 +404,26 @@ static void format_activity(const Status *s, char *out, size_t out_size, long lo
lstrcpynA(details, extra, sizeof(details)); lstrcpynA(details, extra, sizeof(details));
} }
_snprintf(out, out_size, /* Discord rejects empty string values for Rich Presence text fields.
"{\"details\":\"%s\",\"state\":\"%s\",\"timestamps\":{\"start\":%lld}}", * Omit a field entirely when the user did not choose anything that maps
details, s->zone, session_start); * to it, so Race/Class/Faction/Guild-only and Zone-only combinations work. */
if (details[0] && s->zone[0]) {
_snprintf(out, out_size,
"{\"details\":\"%s\",\"state\":\"%s\",\"timestamps\":{\"start\":%lld}}",
details, s->zone, session_start);
} else if (details[0]) {
_snprintf(out, out_size,
"{\"details\":\"%s\",\"timestamps\":{\"start\":%lld}}",
details, session_start);
} else if (s->zone[0]) {
_snprintf(out, out_size,
"{\"state\":\"%s\",\"timestamps\":{\"start\":%lld}}",
s->zone, session_start);
} else {
_snprintf(out, out_size,
"{\"timestamps\":{\"start\":%lld}}",
session_start);
}
out[out_size - 1] = 0; out[out_size - 1] = 0;
} }
@@ -470,10 +489,11 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmdline, int show)
while (!pid && wait_loops++ < 25) { while (!pid && wait_loops++ < 25) {
pid = find_process("WoW_Modernized.exe"); pid = find_process("WoW_Modernized.exe");
if (!pid) pid = find_process("WoW.exe");
if (!pid) Sleep(200); if (!pid) Sleep(200);
} }
if (!pid) { if (!pid) {
log_line("No running WoW_Modernized.exe found; WowPresence exiting."); log_line("No running WoW process found; WowPresence exiting.");
return 0; return 0;
} }
@@ -483,7 +503,7 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE prev, LPSTR cmdline, int show)
return 0; return 0;
} }
log_line("WoW_Modernized.exe detected."); log_line("WoW process detected.");
/* Fixed for the lifetime of this WoW process. Text updates, character /* Fixed for the lifetime of this WoW process. Text updates, character
* changes and loading states reuse the same Discord elapsed-time origin. */ * changes and loading states reuse the same Discord elapsed-time origin. */
session_start = (long long)time(NULL); session_start = (long long)time(NULL);