Skip to content

Commit

Permalink
multiprefix, slight refactor (#355)
Browse files Browse the repository at this point in the history
* internal/state: new file - move to json, multi-prefix propagation

* config: drop global wineroot, multi-prefix propagation

* wine: add Version(), handle wineroot for Prefix

* internal/dirs: multi-prefix propagation

* cmd/vinegar: overhaul: multi-prefix addition

* internal/state: fix test

* config: verify wineroot for binary

* cmd/vinegar: remove old prefix always

* internal/netutil: go fmt

* cmd/vinegar: wrap all needed errors

* wine: fix wineroot

* switch to log/slog

* bloxstraprpc: minor doc changes

* roblox/bootstrapper: s/cdn/mirror, update mirror list

* roblox/api: handle no data

solves #349

* splash: dont make window if splash is disabled

* cmd/vinegar: make splash only in main, use log.Fatalf, const bin pfx dir

* cmd/vinegar: woopsies :3

* cmd/vinegar: minor sysinfo cmd change

* splash: fix dialog on splash disabled

* cmd/vinegar: make avx warning
  • Loading branch information
apprehensions authored Feb 5, 2024
1 parent 9d674b7 commit f58e955
Show file tree
Hide file tree
Showing 37 changed files with 640 additions and 616 deletions.
38 changes: 23 additions & 15 deletions bloxstraprpc/bloxstraprpc.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
// Package bloxstraprpc implements the BloxstrapRPC protocol.
//
// This package remains undocumented as it is modeled after Bloxstrap's
// implementation protocol.
// For more information regarding the protocol, view [Bloxstrap's BloxstrapRPC wiki page]
//
// [Bloxstrap's BloxstrapRPC wiki page]: https://github.com/pizzaboxer/bloxstrap/wiki/Integrating-Bloxstrap-functionality-into-your-game
package bloxstraprpc

import (
"fmt"
"log"
"log/slog"
"regexp"
"strings"
"time"
Expand Down Expand Up @@ -59,14 +60,16 @@ func New() Activity {
}
}

// HandleRobloxLog handles the given Roblox log entry, to set data
// and call functions based on the log entry, declared as *Entry(Pattern) constants.
func (a *Activity) HandleRobloxLog(line string) error {
entries := map[string]func(string) error{
// In order of which it should appear in log file
GameJoinRequestEntry: a.handleGameJoinRequest, // For game join type is private, reserved
GameJoiningEntry: a.handleGameJoining, // For JobID (server ID, to join from Discord)
GameJoinReportEntry: a.handleGameJoinReport, // For PlaceID and UniverseID
GameJoinedEntry: func(_ string) error { return a.handleGameJoined() }, // Sets presence and time
BloxstrapRPCEntry: a.handleGameMessage, // BloxstrapRPC
BloxstrapRPCEntry: a.handleBloxstrapRPC, // BloxstrapRPC
GameLeaveEntry: func(_ string) error { return a.handleGameLeave() }, // Clears presence and time
}

Expand All @@ -83,7 +86,7 @@ func (a *Activity) handleGameJoinRequest(line string) error {
m := GameJoinRequestEntryPattern.FindStringSubmatch(line)
// There are multiple outputs for makePlaceLauncherRequest
if len(m) != 3 {
return nil
return fmt.Errorf("log game join request entry is invalid")
}

if m[1] == "ForTeleport" {
Expand All @@ -99,60 +102,63 @@ func (a *Activity) handleGameJoinRequest(line string) error {
"join-play-together-game": Public,
}[m[2]]

log.Printf("Got Game type %d teleporting %t!", a.server, a.teleporting)
slog.Info("Handled GameJoinRequest", "server_type", a.server, "teleporting", a.teleporting)

return nil
}

func (a *Activity) handleGameJoining(line string) error {
m := GameJoiningEntryPattern.FindStringSubmatch(line)
if len(m) != 2 {
return fmt.Errorf("log game joining entry is invalid!")
return fmt.Errorf("log game joining entry is invalid")
}

a.jobID = m[1]

log.Printf("Got Job %s!", a.jobID)
slog.Info("Handled GameJoining", "jobid", a.jobID)

return nil
}

func (a *Activity) handleGameJoinReport(line string) error {
m := GameJoinReportEntryPattern.FindStringSubmatch(line)
if len(m) != 3 {
return fmt.Errorf("log game join report entry is invalid!")
return fmt.Errorf("log game join report entry is invalid")
}

a.placeID = m[1]
a.universeID = m[2]

log.Printf("Got Universe %s Place %s!", a.universeID, a.placeID)
slog.Info("Handled GameJoinReport", "universeid", a.universeID, "placeid", a.placeID)

return nil
}

func (a *Activity) handleGameJoined() error {
if !a.teleporting {
log.Println("Updating time!")
a.gameTime = time.Now()
}

a.teleporting = false

log.Println("Game Joined!")
slog.Info("Handled GameJoined", "time", a.gameTime)

return a.UpdateGamePresence(true)
}

func (a *Activity) handleGameMessage(line string) error {
func (a *Activity) handleBloxstrapRPC(line string) error {
m, err := NewMessage(line)
if err != nil {
return fmt.Errorf("parse bloxstraprpc message: %w", err)
}
m.ApplyRichPresence(&a.presence)

slog.Info("Handled BloxstrapRPC", "message", m)

return a.UpdateGamePresence(false)
}

func (a *Activity) handleGameLeave() error {
log.Println("Left game, clearing presence!")

a.presence = drpc.Activity{}
a.gameTime = time.Time{}
a.teleporting = false
Expand All @@ -161,5 +167,7 @@ func (a *Activity) handleGameLeave() error {
a.placeID = ""
a.jobID = ""

slog.Info("Handled GameLeave")

return a.client.SetActivity(a.presence)
}
18 changes: 8 additions & 10 deletions bloxstraprpc/discordrpc.go
Original file line number Diff line number Diff line change
@@ -1,31 +1,28 @@
package bloxstraprpc

import (
"log"
"log/slog"

"github.com/altfoxie/drpc"
"github.com/vinegarhq/vinegar/roblox/api"
)

func (a *Activity) Connect() error {
log.Println("Connecting to Discord RPC")
slog.Info("Connecting to Discord RPC")

return a.client.Connect()
}

func (a *Activity) Close() error {
log.Println("Closing Discord RPC")
slog.Info("Closing Discord RPC")

return a.client.Close()
}

// UpdateGamePresence sets the activity based on the current
// game information present in Activity. 'initial' is used
// to fetch game information required for rich presence.
func (a *Activity) UpdateGamePresence(initial bool) error {
if a.universeID == "" {
log.Println("Not in game, clearing presence!")

return a.client.SetActivity(a.presence)
}

a.presence.Buttons = []drpc.Button{{
Label: "See game page",
URL: "https://www.roblox.com/games/" + a.placeID,
Expand Down Expand Up @@ -94,6 +91,7 @@ func (a *Activity) UpdateGamePresence(initial bool) error {
}
}

log.Printf("Updating Discord presence: %#v", a.presence)
slog.Info("Updating Discord Rich Presence", "presence", a.presence)

return a.client.SetActivity(a.presence)
}
12 changes: 5 additions & 7 deletions bloxstraprpc/message.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,21 @@ package bloxstraprpc
import (
"encoding/json"
"errors"
"log"
"log/slog"
"strconv"
"strings"
"time"

"github.com/altfoxie/drpc"
)

// RichPresenceImage holds game image information sent
// from a BloxstrapRPC message
type RichPresenceImage struct {
AssetID *int64 `json:"assetId"`
HoverText *string `json:"hoverText"`
Clear bool `json:"clear"`
Reset bool `json:"reset"`
}

// Data holds game information sent from a BloxstrapRPC message
type Data struct {
Details *string `json:"details"`
State *string `json:"state"`
Expand All @@ -30,8 +27,6 @@ type Data struct {
LargeImage *RichPresenceImage `json:"largeImage"`
}

// Message is a representation of a BloxstrapRPC message sent
// from a Roblox game using the BloxstrapRPC SDK.
type Message struct {
Command string `json:"command"`
Data `json:"data"`
Expand Down Expand Up @@ -66,9 +61,12 @@ func NewMessage(line string) (Message, error) {

// ApplyRichPresence applies/appends Message's properties to the given
// [drpc.Activity] for use in Discord's Rich Presence.
//
// UpdateGamePresence should be called as some of the properties are specific
// to BloxstrapRPC.
func (m Message) ApplyRichPresence(p *drpc.Activity) {
if m.Command != "SetRichPresence" {
log.Printf("WARNING: Game sent invalid BloxstrapRPC command: %s", m.Command)
slog.Warn("Game sent invalid BloxstrapRPC command", "command", m.Command)
return
}

Expand Down
34 changes: 19 additions & 15 deletions cmd/robloxmutexer/robloxmutexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,36 +4,40 @@
package main

import (
"errors"
"log"
"os"
"log/slog"

"golang.org/x/sys/windows"
)

const mutex = "ROBLOX_singletonMutex"

func main() {
log.SetPrefix("robloxmutexer: ")
log.SetFlags(log.Lmsgprefix | log.LstdFlags)
if err := lock(); err != nil {
slog.Error(err.Error())
os.Exit(1)
}

slog.Info("Locked", "mutex", mutex)

_, _ = windows.WaitForSingleObject(windows.CurrentProcess(), windows.INFINITE)
}

name, err := windows.UTF16PtrFromString("ROBLOX_singletonMutex")
func lock() error {
name, err := windows.UTF16PtrFromString(mutex)
if err != nil {
log.Fatal(err)
return err
}

handle, err := windows.CreateMutex(nil, false, name)
if err != nil {
if errors.Is(err, windows.ERROR_ALREADY_EXISTS) {
log.Fatal("Roblox's Mutex is already locked!")
} else {
log.Fatal(err)
}
return err
}

_, err = windows.WaitForSingleObject(handle, 0)
if err != nil {
log.Fatal(err)
return err
}

log.Println("Locked Roblox singleton Mutex")

_, _ = windows.WaitForSingleObject(windows.CurrentProcess(), windows.INFINITE)
return nil
}
Loading

0 comments on commit f58e955

Please sign in to comment.