Skip to content

Commit

Permalink
add ability to restart server from client
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffomatic committed Dec 22, 2020
1 parent 5d59a97 commit d36ad78
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 17 deletions.
4 changes: 4 additions & 0 deletions src/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,10 @@ export class Client {
this.registerParticleEmitter = this.registerParticleEmitter.bind(this)
}

shutdown(): void {
this.serverConnection?.close()
}

setViewportDimensions(d: vec2): void {
this.camera2d.setViewportDimensions(d)
this.renderer3d.setViewportDimensions(d)
Expand Down
20 changes: 20 additions & 0 deletions src/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export class Server {
// Common game state
state: GameState
nextState: GameState | undefined
shuttingDown: boolean

currentLevel: number

Expand All @@ -51,6 +52,7 @@ export class Server {

this.state = GameState.Connecting
this.nextState = undefined
this.shuttingDown = false

this.currentLevel = 0

Expand All @@ -66,7 +68,21 @@ export class Server {
this.simulationDurations = new RunningAverage(3 * 60)
}

shutdown(): void {
this.shuttingDown = true

// Terminate all client connections
for (const { conn } of this.clients) {
conn.close()
}
}

connectClient(conn: IClientConnection): void {
if (this.shuttingDown) {
conn.close()
return
}

if (this.clients.length === this.playerCount) {
console.log('already reached maximum player count') // TODO: close connection
return
Expand All @@ -84,6 +100,10 @@ export class Server {
}

update(dt: number): void {
if (this.shuttingDown) {
return
}

const now = time.current()
this.updateFrameDurations.sample(now - this.lastUpdateAt)
this.lastUpdateAt = now
Expand Down
58 changes: 48 additions & 10 deletions src/clientMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@ import { createServerConnectionWs } from '~/network/ServerConnection'

declare global {
interface Window {
client: Client
debug: {
client: Client
restartServer: () => Promise<void>
}
}
}

Expand All @@ -33,15 +36,13 @@ canvas2d.width = window.innerWidth
canvas2d.height = window.innerHeight
document.body.appendChild(canvas2d)

const client = new Client({
let client = new Client({
canvas3d,
canvas2d,
keyboard: new DocumentEventKeyboard(document),
mouse: new DocumentEventMouse(document),
})

// Development-related globals
window.client = client // expose game to console
clientHotReload.init({ enabled: true })

function syncViewportSize() {
Expand All @@ -62,9 +63,46 @@ function clientRenderLoop() {
clientRenderLoop()

// Connect to server
const schema = location.protocol === 'https:' ? 'wss' : 'ws'
createServerConnectionWs(`${schema}://${location.host}/api/connect`).then(
(conn) => {
client.connectServer(conn)
},
)
function connectToServer(): Promise<void> {
const schema = location.protocol === 'https:' ? 'wss' : 'ws'
return createServerConnectionWs(
`${schema}://${location.host}/api/connect`,
).then((conn) => client.connectServer(conn))
}

connectToServer()

function restartServer(): Promise<void> {
return fetch(`${location.protocol}//${location.host}/api/restart`).then(
() => {
client = new Client({
canvas3d,
canvas2d,
keyboard: new DocumentEventKeyboard(document),
mouse: new DocumentEventMouse(document),
})
return connectToServer()
},
)
}

// Add a debounced hotkey for restarting the server
let restartHotkeyTimeout: number | undefined = undefined
document.addEventListener('keyup', (event) => {
if (event.code === 'KeyR' && event.ctrlKey && event.shiftKey) {
if (restartHotkeyTimeout !== undefined) {
return
}

restartHotkeyTimeout = setTimeout(() => {
restartHotkeyTimeout = undefined
}, 500)
restartServer()
}
})

// Development-related globals
window.debug = {
client,
restartServer,
}
5 changes: 5 additions & 0 deletions src/network/ClientConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ServerMessage } from '~/network/ServerMessage'
export interface IClientConnection {
send(msg: ServerMessage): void
consume(): ClientMessage[]
close(): void
}

export class ClientConnectionWs implements IClientConnection {
Expand All @@ -34,4 +35,8 @@ export class ClientConnectionWs implements IClientConnection {
this.received = []
return msgs
}

close(): void {
this.socket.close()
}
}
5 changes: 5 additions & 0 deletions src/network/ServerConnection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ServerMessage } from '~/network/ServerMessage'
export interface IServerConnection {
send(msg: ClientMessage): void
consume(): ServerMessage[]
close(): void
}

export class ServerConnectionWs implements IServerConnection {
Expand All @@ -32,6 +33,10 @@ export class ServerConnectionWs implements IServerConnection {
this.received = []
return msgs
}

close(): void {
this.socket.close()
}
}

export function createServerConnectionWs(
Expand Down
18 changes: 11 additions & 7 deletions src/serverMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { Server as GameServer } from '~/Server'
const playerCount = 1
const clientBufferSize = 7

const gameServer = new GameServer({
let gameServer = new GameServer({
playerCount,
minFramesBehindClient: clientBufferSize,
})
Expand All @@ -42,6 +42,15 @@ const wsServer = new WebSocket.Server({ noServer: true })
const apiRouter = new KoaRouter()
apiRouter
.get('/buildkey', async (ctx) => (ctx.body = buildkey))
.get('/restart', async (ctx) => {
console.log('restarting game server')
gameServer.shutdown()
gameServer = new GameServer({
playerCount,
minFramesBehindClient: clientBufferSize,
})
ctx.body = 'ok'
})
.get('/connect', async (ctx) => {
if (ctx.get('Upgrade') !== 'websocket') {
ctx.throw(400, 'invalid websocket connection request')
Expand All @@ -50,12 +59,7 @@ apiRouter
ctx.respond = false

const socket = await new Promise((resolve: (ws: WebSocket) => void) => {
wsServer.handleUpgrade(
ctx.req,
ctx.request.socket,
Buffer.alloc(0),
resolve,
)
wsServer.handleUpgrade(ctx.req, ctx.req.socket, Buffer.alloc(0), resolve)
})

console.log(
Expand Down

0 comments on commit d36ad78

Please sign in to comment.