diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index bd5add1..3f3ee33 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -72,16 +72,16 @@ jobs: dist/WowPresence.zip if-no-files-found: error - - name: Create GitHub Release v1.2 - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && github.event.head_commit.message == '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.3' }} uses: softprops/action-gh-release@v3 with: - tag_name: v1.2 + tag_name: v1.3 target_commitish: ${{ github.sha }} files: | dist/WowPresence.zip fail_on_unmatched_files: true - name: "WowPresence v1.2" + name: "WowPresence v1.3" body_path: RELEASE_NOTES.md generate_release_notes: false make_latest: true diff --git a/README.md b/README.md index 2895251..392049f 100644 --- a/README.md +++ b/README.md @@ -162,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. -## 🔒 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 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 | | ---: | --- | -| 1 | Name | +| 1 | Character Name | | 2 | Guild | | 4 | Faction | | 8 | Class | | 16 | Level | | 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 diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 40be3c9..d194519 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,29 +1,22 @@ -# WowPresence v1.2 +# WowPresence v1.3 -## Changes +## What's New -- Reworked zone detection to use the player's real AreaTable ID. -- Zone names are now resolved from `AreaTable.dbc` instead of selecting the first plausible string from several client addresses. -- Prevents internal map/area tokens such as `H32D` and `HLVA` from being published as Discord zone names. -- Uses the client's active localized AreaTable name when available, with a safe populated-locale fallback. -- Keeps WowPresence fully standalone; ClassicAPI is not required. -- Modernization Tool installations continue to use `.modernization_tool\WowPresence\` automatically. -- Improved WoW process detection logging with a generic `WoW process detected.` message. -- Manual/debug process fallback now supports both `WoW_Modernized.exe` and `WoW.exe`. -- Documented the OctoWoW Discord Application ID for standalone configuration. +- Added independent privacy control for: + - Character Name + - Guild + - Race + - Faction + - 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 - `WowPresence.zip` — ready-to-install package containing `WowPresence.dll`, `WowPresence.exe`, and the WowPresence configuration folder. - -## Commits - -- [`f261c3b`](https://github.com/Dusk-92/WowPresence/commit/f261c3be298d56bc025671e22a348555157f94b3) Resolve zones through AreaTable -- [`0994fe4`](https://github.com/Dusk-92/WowPresence/commit/0994fe4e08b03ec17b09d09eb51a2e7c2b0b2db1) Document AreaTable zone resolution -- [`3c76de9`](https://github.com/Dusk-92/WowPresence/commit/3c76de9bdbcb19a45543bd09b03bbd75a2d65d8f) Document ClassicAPI technical reference -- [`8048e80`](https://github.com/Dusk-92/WowPresence/commit/8048e804f6629c75cc3b1d81f835aaa1c1f8a423) Prepare WowPresence v1.2 release -- [`4576605`](https://github.com/Dusk-92/WowPresence/commit/4576605dce59702d8f90d542e7db3dae4789e1ed) Document OctoWoW Discord Application ID -- [`fdb3126`](https://github.com/Dusk-92/WowPresence/commit/fdb3126d1fc6c09392c21d07327c21084aeeb112) Improve WoW process detection logging -- [`05dc409`](https://github.com/Dusk-92/WowPresence/commit/05dc4094a0f326699c72176ad516d3341e7be33f) Publish only the WowPresence ZIP release asset - -**Full Changelog**: [v1.1...v1.2](https://github.com/Dusk-92/WowPresence/compare/v1.1...v1.2) diff --git a/config/discord_broadcast_flags b/config/discord_broadcast_flags index 4b9026d..c75acbe 100644 --- a/config/discord_broadcast_flags +++ b/config/discord_broadcast_flags @@ -1 +1 @@ -63 +127 diff --git a/src/WowPresence.c b/src/WowPresence.c index 91431ec..48bcfbe 100644 --- a/src/WowPresence.c +++ b/src/WowPresence.c @@ -75,7 +75,8 @@ #define SHARE_CLASS 8u #define SHARE_LEVEL 16u #define SHARE_ZONE 32u -#define SHARE_ALL 63u +#define SHARE_RACE 64u +#define SHARE_ALL 127u static const uintptr_t kPlayerNameLocations[] = { 0x00C27FC8u, 0x00C27D88u, 0x00C27FD8u, 0 @@ -751,7 +752,8 @@ static void publish_character_snapshot(void) { collect_character_snapshot(&snapshot); 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)) ? label_for_id(kClassLabels, snapshot.class_id) : ""; faction_text = (snapshot.in_world && (mask & SHARE_FACTION)) diff --git a/src/WowPresenceLauncher.c b/src/WowPresenceLauncher.c index 7284939..285bc07 100644 --- a/src/WowPresenceLauncher.c +++ b/src/WowPresenceLauncher.c @@ -293,7 +293,9 @@ static int load_status(Status *status) { json_string(json, "class", status->class_name, sizeof(status->class_name)); json_string(json, "race", status->race, sizeof(status->race)); 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) { @@ -402,9 +404,26 @@ static void format_activity(const Status *s, char *out, size_t out_size, long lo lstrcpynA(details, extra, sizeof(details)); } - _snprintf(out, out_size, - "{\"details\":\"%s\",\"state\":\"%s\",\"timestamps\":{\"start\":%lld}}", - details, s->zone, session_start); + /* Discord rejects empty string values for Rich Presence text fields. + * Omit a field entirely when the user did not choose anything that maps + * 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; }