Skip to content

Commit

Permalink
Merge branch 'vinegarhq:master' into dgpu-prime
Browse files Browse the repository at this point in the history
  • Loading branch information
jrelvas-ipc authored Oct 24, 2023
2 parents 377fbd2 + 8b061c5 commit 083ebbb
Show file tree
Hide file tree
Showing 40 changed files with 1,318 additions and 264 deletions.
8 changes: 8 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,15 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- name: 'Setup Go'
uses: actions/setup-go@v4
with:
go-version: '^1.20'
- name: 'Checkout Repository'
uses: actions/checkout@v3
- name: 'Setup Go'
uses: actions/setup-go@v4
with:
go-version: '^1.21'
- name: 'Build Vinegar'
run: make VINEGAR_GOFLAGS="--tags nogui"
6 changes: 3 additions & 3 deletions .github/workflows/vendor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ jobs:
- name: 'Setup Go'
uses: actions/setup-go@v4
with:
go-version: '^1.20'
go-version: '^1.21'
- name: 'Make the vendor directory'
run: go mod vendor
- name: 'Package the source directory'
run: |
RELEASE="vinegar-${{ github.ref_name }}"
RELEASE="vinegar-${{ github.event.release.tag_name }}"
cd ..
cp -r vinegar $RELEASE
Expand All @@ -30,6 +30,6 @@ jobs:
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: "../vinegar-${{ github.ref_name }}.tar.xz"
file: "../vinegar-${{ github.event.release.tag_name }}.tar.xz"
overwrite: true
make_latest: false
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ An open-source, minimal, configurable, fast bootstrapper for running Roblox on L
+ Automatic DXVK Installer and uninstaller
+ Automatic Wineprefix killer when Roblox has quit
+ Automatic removal of outdated cached packages and versions of Roblox
+ Discord Rich Presence support
+ Roblox's logs appear within Vinegar
+ FPS Unlocking for Player by default, without rbxfpsunlocker
+ Browser launch via MIME
+ Custom execution of wine program within wineprefix
Expand All @@ -36,7 +38,7 @@ An open-source, minimal, configurable, fast bootstrapper for running Roblox on L
+ Faster Multi-threaded installation and extraction of Roblox
+ Multiple instances of Roblox open simultaneously
+ Loading window during setup
+ Logging for both Vinegar and Wine
+ Logging for both Vinegar, Wine and Roblox

# See Also
+ [Discord Server](https://discord.gg/dzdzZ6Pps2)
Expand Down
164 changes: 164 additions & 0 deletions bloxstraprpc/activity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
package bloxstraprpc

import (
"log"
"regexp"
"strings"
"time"

"github.com/hugolgst/rich-go/client"
)

const (
GameJoiningEntry = "[FLog::Output] ! Joining game"
GameJoiningPrivateServerEntry = "[FLog::GameJoinUtil] GameJoinUtil::joinGamePostPrivateServer"
GameJoiningReservedServerEntry = "[FLog::GameJoinUtil] GameJoinUtil::initiateTeleportToReservedServer"
GameJoiningUDMUXEntry = "[FLog::Network] UDMUX Address = "
GameJoinedEntry = "[FLog::Network] serverId:"
GameDisconnectedEntry = "[FLog::Network] Time to disconnect replication data:"
GameTeleportingEntry = "[FLog::SingleSurfaceApp] initiateTeleport"
GameMessageEntry = "[FLog::Output] [BloxstrapRPC]"
)

var (
GameJoiningEntryPattern = regexp.MustCompile(`! Joining game '([0-9a-f\-]{36})' place ([0-9]+) at ([0-9\.]+)`)
GameJoiningUDMUXPattern = regexp.MustCompile(`UDMUX Address = ([0-9\.]+), Port = [0-9]+ \| RCC Server Address = ([0-9\.]+), Port = [0-9]+`)
GameJoinedEntryPattern = regexp.MustCompile(`serverId: ([0-9\.]+)\|[0-9]+`)
)

type ServerType int

const (
Public ServerType = iota
Private
Reserved
)

type Activity struct {
presence client.Activity
timeStartedUniverse time.Time
currentUniverseID string

ingame bool
teleported bool
server ServerType
placeID string
jobID string
mac string

teleport bool
reservedteleport bool
}

func (a *Activity) HandleRobloxLog(line string) error {
if !a.ingame && a.placeID == "" {
if strings.Contains(line, GameJoiningPrivateServerEntry) {
a.server = Private
return nil
}

if strings.Contains(line, GameJoiningEntry) {
a.handleGameJoining(line)
return nil
}
}

if !a.ingame && a.placeID != "" {
if strings.Contains(line, GameJoiningUDMUXEntry) {
a.handleUDMUX(line)
return nil
}

if strings.Contains(line, GameJoinedEntry) {
a.handleGameJoined(line)
return a.SetCurrentGame()
}
}

if a.ingame && a.placeID != "" {
if strings.Contains(line, GameDisconnectedEntry) {
log.Printf("Disconnected From Game (%s/%s/%s)", a.placeID, a.jobID, a.mac)
a.Clear()
return a.SetCurrentGame()
}

if strings.Contains(line, GameTeleportingEntry) {
log.Printf("Teleporting to server (%s/%s/%s)", a.placeID, a.jobID, a.mac)
a.teleport = true
return nil
}

if a.teleport && strings.Contains(line, GameJoiningReservedServerEntry) {
log.Printf("Teleporting to reserved server")
a.reservedteleport = true
return nil
}

if strings.Contains(line, GameMessageEntry) {
m, err := ParseMessage(line)
if err != nil {
return err
}

a.ProcessMessage(&m)
return a.UpdatePresence()
}
}

return nil
}

func (a *Activity) handleUDMUX(line string) {
m := GameJoiningUDMUXPattern.FindStringSubmatch(line)
if len(m) != 3 || m[2] != a.mac {
return
}

a.mac = m[1]
log.Printf("Got game join UDMUX: %s", a.mac)
}

func (a *Activity) handleGameJoining(line string) {
m := GameJoiningEntryPattern.FindStringSubmatch(line)
if len(m) != 4 {
return
}

a.ingame = false
a.jobID = m[1]
a.placeID = m[2]
a.mac = m[3]

if a.teleport {
a.teleported = true
a.teleport = false
}

if a.reservedteleport {
a.server = Reserved
a.reservedteleport = false
}

log.Printf("Joining Game (%s/%s/%s)", a.jobID, a.placeID, a.mac)
}

func (a *Activity) handleGameJoined(line string) {
m := GameJoinedEntryPattern.FindStringSubmatch(line)
if len(m) != 2 || m[1] != a.mac {
return
}

a.ingame = true
log.Printf("Joined Game (%s/%s/%s)", a.placeID, a.jobID, a.mac)
// handle rpc
}

func (a *Activity) Clear() {
a.teleported = false
a.ingame = false
a.placeID = ""
a.jobID = ""
a.mac = ""
a.server = Public
a.presence = client.Activity{}
}
154 changes: 154 additions & 0 deletions bloxstraprpc/discordrpc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package bloxstraprpc

import (
"log"
"strconv"
"time"

"github.com/hugolgst/rich-go/client"
"github.com/vinegarhq/vinegar/roblox/api"
)

// This is Bloxstrap's Discord RPC application ID.
const RPCAppID = "1005469189907173486"

func Login() error {
log.Println("Authenticating Discord RPC")
return client.Login(RPCAppID)
}

func Logout() {
log.Println("Deauthenticating Discord RPC")
client.Logout()
}

func (a *Activity) SetCurrentGame() error {
if !a.ingame {
log.Println("Not in game, clearing presence")
a.presence = client.Activity{}
} else {
if err := a.SetPresence(); err != nil {
return err
}
}

return a.UpdatePresence()
}

func (a *Activity) SetPresence() error {
var status string
log.Printf("Setting presence for Place ID %s", a.placeID)

uid, err := api.GetUniverseID(a.placeID)
if err != nil {
return err
}
log.Printf("Got Universe ID as %s", uid)

if !a.teleported || uid != a.currentUniverseID {
a.timeStartedUniverse = time.Now()
}

a.currentUniverseID = uid

gd, err := api.GetGameDetails(uid)
if err != nil {
return err
}
log.Println("Got Game details")

tn, err := api.GetGameIcon(uid, "PlaceHolder", "512x512", "Png", false)
if err != nil {
return err
}
log.Printf("Got Universe thumbnail as %s", tn.ImageURL)

switch a.server {
case Public:
status = "by " + gd.Creator.Name
case Private:
status = "In a private server"
case Reserved:
status = "In a reserved server"
}

a.presence = client.Activity{
State: status,
Details: "Playing " + gd.Name,
LargeImage: tn.ImageURL,
LargeText: gd.Name,
SmallImage: "roblox",
SmallText: "Roblox",
Timestamps: &client.Timestamps{
Start: &a.timeStartedUniverse,
},
Buttons: []*client.Button{
{
Label: "See game page",
Url: "https://www.roblox.com/games/" + a.placeID,
},
},
}

return nil
}

func (a *Activity) ProcessMessage(m *Message) {
if m.Command != "SetRichPresence" {
return
}

if m.Data.Details != "" {
a.presence.Details = m.Data.Details
}

if m.Data.State != "" {
a.presence.State = m.Data.State
}

if a.presence.Timestamps != nil {
if m.TimestampStart == 0 {
a.presence.Timestamps.Start = nil
} else {
ts := time.UnixMilli(m.TimestampStart)
a.presence.Timestamps.Start = &ts
}
}

if a.presence.Timestamps != nil {
if m.TimestampEnd == 0 {
a.presence.Timestamps.End = nil
} else {
te := time.UnixMilli(m.TimestampEnd)
a.presence.Timestamps.End = &te
}
}

if m.SmallImage.Clear {
a.presence.SmallImage = ""
}

if m.SmallImage.AssetID != 0 {
a.presence.SmallImage = "https://assetdelivery.roblox.com/v1/asset/?id" +
strconv.FormatInt(m.SmallImage.AssetID, 10)
}

if m.LargeImage.Clear {
a.presence.LargeImage = ""
}

if m.LargeImage.AssetID != 0 {
a.presence.LargeImage = "https://assetdelivery.roblox.com/v1/asset/?id" +
strconv.FormatInt(m.LargeImage.AssetID, 10)
}
}

func (a *Activity) UpdatePresence() error {
// if a.presence == client.Activity{} {
// log.Println("Presence is empty, clearing")
// return ClearPresence()
// }

log.Printf("Updating presence: %+v", a.presence)
return client.SetActivity(a.presence)
}
Loading

0 comments on commit 083ebbb

Please sign in to comment.