Skip to content

Commit cd66263

Browse files
committed
Basic gameserver starting implementation
1 parent 8390b45 commit cd66263

4 files changed

Lines changed: 70 additions & 31 deletions

File tree

Site/src/routes/(main)/place/[id=asset]/[name]/+page.server.ts

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import { error, redirect } from "@sveltejs/kit"
22
import { authorise } from "$lib/server/auth"
33
import config from "$lib/server/config"
44
import formData from "$lib/server/formData"
5-
import { getGameserver } from "$lib/server/orbiter"
5+
import { getGameserver, startGameserver } from "$lib/server/orbiter"
6+
import ratelimit from "$lib/server/ratelimit"
67
import { db, findWhere, Record } from "$lib/server/surreal"
78
import { couldMatch, encode } from "$lib/urlName"
89
import findPlaceQuery from "./findPlace.surql"
@@ -83,13 +84,10 @@ export async function load({ locals, params, url }) {
8384
}
8485
}
8586

86-
export const actions: import("./$types").Actions = {}
87-
actions.join = async ({ locals, params, request }) => {
88-
const { user } = await authorise(locals)
87+
async function findPlace(request: Request, id: number, user: User) {
8988
const data = await formData(request)
9089
const privateTicket = data?.privateTicket
9190

92-
const id = +params.id
9391
const placeR = Record("place", id)
9492
const [[place]] = await db.query<FoundPlace[][]>(findPlaceQuery, {
9593
place: placeR,
@@ -103,13 +101,27 @@ actions.join = async ({ locals, params, request }) => {
103101
)
104102
error(404, "Place not found")
105103

104+
return placeR
105+
}
106+
107+
async function checkUser(locals: App.Locals) {
108+
const { user } = await authorise(locals)
109+
106110
const foundModerated = await findWhere(
107111
"moderation",
108112
"out = $user AND active = true",
109113
{ user: Record("user", user.id) }
110114
)
111115
if (foundModerated) error(403, "You cannot currently play games")
112116

117+
return user
118+
}
119+
120+
export const actions: import("./$types").Actions = {}
121+
actions.join = async ({ locals, params, request }) => {
122+
const user = await checkUser(locals)
123+
const placeR = await findPlace(request, +params.id, user)
124+
113125
// Invalidate all game sessions and create valid playing
114126
const [, [ticket]] = await db.query<string[][]>(invalidatePlayingQuery, {
115127
user: Record("user", user.id),
@@ -118,3 +130,21 @@ actions.join = async ({ locals, params, request }) => {
118130

119131
return { ticket }
120132
}
133+
134+
actions.start = async ({ locals, params, getClientAddress }) => {
135+
await checkUser(locals)
136+
137+
const limit = ratelimit(null, "serverstart", getClientAddress, 20)
138+
if (limit) return limit
139+
140+
const id = +params.id
141+
const res = await startGameserver(id)
142+
if (!res.ok) {
143+
console.error(
144+
"Failed to start dedicated gameserver for id",
145+
id,
146+
res.msg
147+
)
148+
error(500, "Failed to start dedicated server")
149+
}
150+
}

Site/src/routes/(main)/place/[id=asset]/[name]/+page.svelte

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
1919
let place = $state(data.place)
2020
let online = $derived(place.serverPing > Date.now() / 1000 - 35)
21+
let currentPath = $derived(`/place/${place.id}/${data.slug}`)
2122
2223
const statistics = $derived([
2324
// ["Activity", "0 visits"],
@@ -33,35 +34,42 @@
3334
let installed = $state(true)
3435
let success = $state(false)
3536
36-
const launch = (joinscripturl: () => string) => () => {
37-
success = false
38-
customProtocol(
39-
joinscripturl(),
40-
() => {
41-
success = true
42-
setTimeout(() => popover?.hidePopover(), 16000)
43-
},
44-
() => {
45-
installed = false
46-
}
47-
)
37+
function privateFetch() {
38+
const body = new FormData()
39+
body.append("privateTicket", place.privateTicket)
40+
return { method: "POST", body }
4841
}
4942
43+
// we don't want to start a server if the user is just opening studio to edit the place
44+
const launch =
45+
(joinscripturl: () => string, startServer = false) =>
46+
() => {
47+
success = false
48+
customProtocol(
49+
joinscripturl(),
50+
async () => {
51+
// this isn't a guarantee that the game has succeeded in launching, but it's a decent guess I guess??
52+
if (startServer)
53+
await fetch(`${currentPath}?/start`, privateFetch())
54+
55+
success = true
56+
setTimeout(() => popover?.hidePopover(), 16000)
57+
},
58+
() => {
59+
installed = false
60+
}
61+
)
62+
}
63+
5064
let loadCommand = $derived(
5165
`dofile "http://${data.domain}/game/host?ticket=${place.serverTicket}"`
5266
)
5367
5468
async function placeLauncher() {
5569
installed = true
5670
57-
const formdata = new FormData()
58-
formdata.append("privateTicket", place.privateTicket)
59-
6071
// Get the joinscript URL
61-
const response = await fetch(`/place/${place.id}/${data.slug}?/join`, {
62-
method: "POST",
63-
body: formdata
64-
})
72+
const response = await fetch(`${currentPath}?/join`, privateFetch())
6573
const joinScriptData = deserialize(await response.text()) as {
6674
status: number
6775
data: { ticket: string }
@@ -70,7 +78,7 @@
7078
7179
// JoinScript is my favourite programming language (-i mean scripting language)
7280
const joinUri = data.scheme + joinScriptData.data.ticket
73-
launch(() => joinUri)()
81+
launch(() => joinUri, true)()
7482
}
7583
7684
const tabs = ["Description", "Servers"]

Site/src/routes/(rbxclient)/game/join/+server.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ export async function GET({ url }) {
2525

2626
if (!clientTicket) error(400, "Invalid Request")
2727

28-
const playing = Record("playing", clientTicket)
29-
const [[gameSession]] = await db.query<Session[][]>(joinQuery, { playing })
30-
if (!gameSession) error(400, "Invalid Game Session")
31-
3228
const foundPrivatePlace = await findWhere(
3329
"place",
3430
"privateTicket = $privateServer",
@@ -37,7 +33,10 @@ export async function GET({ url }) {
3733
if (privateServer && !foundPrivatePlace)
3834
error(400, "Invalid Private Server")
3935

40-
await db.merge(playing, { valid: false })
36+
const playing = Record("playing", clientTicket)
37+
// also invalidates the session
38+
const [gameSession] = await db.query<Session[]>(joinQuery, { playing })
39+
if (!gameSession) error(400, "Invalid Game Session")
4140

4241
const placeId = gameSession.place.id
4342
const creatorUsername = gameSession.place.ownerUser?.username

Site/src/routes/(rbxclient)/game/join/join.surql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ SELECT
77
FROM ->place)[0] AS place,
88
(SELECT permissionLevel, username
99
FROM <-user)[0] AS user
10-
FROM $playing;
10+
FROM ONLY $playing;
11+
12+
UPDATE $playing SET valid = false;

0 commit comments

Comments
 (0)