Skip to content

Instantly share code, notes, and snippets.

@scy
Last active September 20, 2022 15:08
Show Gist options
  • Save scy/f6fdca0481de564639a8b2bfbdcfa1b0 to your computer and use it in GitHub Desktop.
Save scy/f6fdca0481de564639a8b2bfbdcfa1b0 to your computer and use it in GitHub Desktop.
Example on how to access the Guild Wars 2 Mumble Link API on Windows using Go. Not supposed to be good Go code, but it works.
package main
import (
"fmt"
"log"
"syscall"
"time"
"unsafe"
"unicode/utf16"
"unicode/utf8"
"bytes"
)
type MumbleVector [3]float32
type WChar uint16
type MumbleIdentity [256]uint16
func (id MumbleIdentity) String() string {
buf := make([]byte, 4)
var ret bytes.Buffer
runes := utf16.Decode(id[:])
count := 0
for _, rune := range runes {
utf8.EncodeRune(buf, rune)
ret.WriteString(string(rune))
count++
}
return ret.String()
}
type MumblePosition struct {
Position MumbleVector
Front MumbleVector
Top MumbleVector
}
type MumbleData struct {
Version uint32
Tick uint32
Avatar MumblePosition
Name [256]WChar
Camera MumblePosition
Identity MumbleIdentity
ContextLength uint32
Context [256]byte
Description [2048]WChar
}
func main() {
file, _ := syscall.UTF16PtrFromString("MumbleLink")
size := 100000 // I’ve tried unsafe.Sizeof(MumbleData{}) but that didn’t work.
handle, err := syscall.CreateFileMapping(0, nil, syscall.PAGE_READWRITE, 0, uint32(size), file)
if err != nil {
log.Fatal(err)
}
defer syscall.CloseHandle(handle)
addr, err := syscall.MapViewOfFile(handle, syscall.FILE_MAP_READ, 0, 0, 0)
if err != nil {
log.Fatal(err)
}
for {
data := (*MumbleData)(unsafe.Pointer(addr))
time.Sleep(1 * time.Second)
fmt.Printf("ava %v cam %v id %v\n", data.Avatar.Position, data.Camera, data.Identity)
}
}
@scy
Copy link
Author

scy commented Jan 4, 2018

Please note that you have to run this before starting up GW2. The game won’t enable the API if no one is listening.

@scy
Copy link
Author

scy commented Jun 10, 2018

I've elaborated a bit on this in my knowledge base.

@json-m
Copy link

json-m commented Dec 15, 2021

this is great, thank you for sharing this.

@scy
Copy link
Author

scy commented Dec 15, 2021

@json-m Let me know when you’ve built something based on it ;)

@coderedart
Copy link

size := 100000 // I’ve tried unsafe.Sizeof(MumbleData{}) but that didn’t work.

I think the size needs to be atleast the size of a page (4096 bytes). it probably won't work for size of mumbleLink as it is only 1050 ish bytes.

quote from https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createfilemappinga :

The maximum size of the file mapping object must be a multiple of the minimum size of a large page returned by the GetLargePageMinimum function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment