Initial commit: DeathWatch, an Elden Ring death counter for OBS
Reads the game's process memory read-only (AOB signature scanning, re-resolved every tick — never a cached pointer) and serves a live death counter as a browser-source overlay plus a status panel. Supports co-op: each player runs the program locally, one acts as hub. The peer link is authenticated (HMAC challenge/response, no token on the wire, constant-time compare) but not yet encrypted — see CLAUDE.md's TODO section for the planned TLS+pinning split. Zero external dependencies — including a hand-rolled WebSocket implementation — so the whole thing ships as one .exe.
This commit is contained in:
commit
e1f7e6f529
18 files changed
+3690
No files matched your search
@@ -0,0 +1,90 @@
|
||||
// looksLikeName decides whether text read from the game's memory looks
|
||||
// like a real character name, and not binary garbage decoded as if it
|
||||
// were UTF-16. It lives apart from main.go (which is Windows-only)
|
||||
// because it's pure string logic: it can be tested without a PC with the
|
||||
// game open.
|
||||
package main
|
||||
|
||||
import (
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// charNameMaxChars: from the Cheat Engine table, "GameDataMan
|
||||
// +0C +9C, unicode, length 19".
|
||||
const charNameMaxChars = 19
|
||||
|
||||
// script identifies the writing-system family of a character in the name.
|
||||
type script int
|
||||
|
||||
const (
|
||||
scriptNone script = iota
|
||||
scriptLatin
|
||||
scriptCyrillic
|
||||
scriptHangul
|
||||
scriptCJK // Han, Hiragana, and Katakana count as a single family
|
||||
)
|
||||
|
||||
func scriptOf(r rune) script {
|
||||
switch {
|
||||
case unicode.In(r, unicode.Latin):
|
||||
return scriptLatin
|
||||
case unicode.In(r, unicode.Cyrillic):
|
||||
return scriptCyrillic
|
||||
case unicode.In(r, unicode.Hangul):
|
||||
return scriptHangul
|
||||
case unicode.In(r, unicode.Han, unicode.Hiragana, unicode.Katakana):
|
||||
return scriptCJK
|
||||
default:
|
||||
return scriptNone
|
||||
}
|
||||
}
|
||||
|
||||
// looksLikeName guards against garbage. "Printable" isn't nearly enough:
|
||||
// a 64-bit pointer read as UTF-16 decodes into things like "ᾘ䱷翶", which
|
||||
// is printable and would pass a filter that only checked that.
|
||||
//
|
||||
// This used to require the Latin alphabet, which left out Chinese,
|
||||
// Korean, and Japanese names. Instead it requires SCRIPT COHERENCE: the
|
||||
// whole name has to come from a single family (Latin, Cyrillic, Hangul,
|
||||
// or Han+Hiragana+Katakana as one family, since Japanese mixes all three
|
||||
// in one name) plus digits/space/punctuation (which don't belong to any
|
||||
// particular family). Mixing families — like Greek + Han in "ᾘ䱷翶" — is
|
||||
// still rejected: that's exactly the signature of binary garbage.
|
||||
func looksLikeName(s string) bool {
|
||||
n := utf8.RuneCountInString(s)
|
||||
if n < 2 || n > charNameMaxChars {
|
||||
return false
|
||||
}
|
||||
|
||||
sc := scriptNone
|
||||
hadLetter := false
|
||||
|
||||
for i, r := range s {
|
||||
if r == utf8.RuneError || !unicode.IsPrint(r) {
|
||||
return false
|
||||
}
|
||||
if unicode.IsDigit(r) {
|
||||
continue
|
||||
}
|
||||
if r == ' ' || r == '-' || r == '_' || r == '.' || r == '\'' {
|
||||
if i == 0 {
|
||||
return false // a name doesn't start with punctuation
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
f := scriptOf(r)
|
||||
if f == scriptNone {
|
||||
return false // script not accepted
|
||||
}
|
||||
if sc == scriptNone {
|
||||
sc = f
|
||||
} else if sc != f {
|
||||
return false // mixed families: the signature of binary garbage
|
||||
}
|
||||
hadLetter = true
|
||||
}
|
||||
|
||||
return hadLetter
|
||||
}
|
||||
Reference in new issue
Block a user