Skip to content

Commit

Permalink
saner clientMain.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
jeffomatic committed Dec 26, 2020
1 parent 2ad8ce5 commit 4dd55c3
Show file tree
Hide file tree
Showing 9 changed files with 162 additions and 122 deletions.
139 changes: 139 additions & 0 deletions src/client/Client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import { vec2 } from 'gl-matrix'

import { ClientSim } from '~/client/ClientSim'
import { ClientView } from '~/client/ClientView'
import { DebugDraw } from '~/DebugDraw'
import { GameState } from '~/Game'
import { DocumentEventKeyboard } from '~/input/DocumentEventKeyboard'
import { DocumentEventMouse } from '~/input/DocumentEventMouse'
import { IKeyboard, IMouse } from '~/input/interfaces'
import { createServerConnectionWs } from '~/network/ServerConnection'
import { Immutable } from '~/types/immutable'

export class Client {
document: Document
location: Location
viewportDimensions: vec2
canvas3d: HTMLCanvasElement
canvas2d: HTMLCanvasElement

// The following objects should get re-constructed on server restart
keyboard: IKeyboard
mouse: IMouse
debugDraw: DebugDraw
view: ClientView
sim: ClientSim

constructor(params: {
document: Document
location: Location
viewportDimensions: Immutable<vec2>
}) {
this.document = params.document
this.location = params.location
this.viewportDimensions = vec2.clone(params.viewportDimensions)

// disable right clicks
this.document.addEventListener('contextmenu', (e) => e.preventDefault())

this.canvas3d = this.document.createElement('canvas')
this.canvas3d.setAttribute(
'style',
'position: absolute; top: 0; left: 0; z-index: 0',
)
this.canvas3d.width = this.viewportDimensions[0]
this.canvas3d.height = this.viewportDimensions[1]
this.document.body.appendChild(this.canvas3d)

this.canvas2d = document.createElement('canvas')
this.canvas2d.setAttribute(
'style',
'position: absolute; top: 0; left: 0; z-index: 1',
)
this.canvas2d.width = this.viewportDimensions[0]
this.canvas2d.height = this.viewportDimensions[1]
this.document.body.appendChild(this.canvas2d)

this.keyboard = new DocumentEventKeyboard(this.document)
this.mouse = new DocumentEventMouse(this.document)
this.debugDraw = new DebugDraw()

this.view = new ClientView({
canvas3d: this.canvas3d,
canvas2d: this.canvas2d,
debugDraw: this.debugDraw,
})

this.sim = new ClientSim({
keyboard: this.keyboard,
mouse: this.mouse,
modelLoader: this.view.getModelLoader(),
debugDraw: this.debugDraw,
viewportDimensions: this.viewportDimensions,
})
}

update(): void {
this.sim.update()

if (this.keyboard.upKeys.has('Backquote')) {
this.debugDraw.setEnabled(!this.debugDraw.isEnabled())
}

// TODO: figure out a better way to prevent unloaded models from rendering.
// Maybe: getRenderables3d() should not return renderables for models that
// haven't been loaded yet!
if (this.sim.state !== GameState.Connecting) {
this.view.update({
world2ViewTransform: this.sim.camera.getWvTransform(),
renderables3d: this.sim.getRenderables3d(),
})
}

this.keyboard.update()
this.mouse.update()
this.debugDraw.update()
}

syncViewportDimensions(d: Immutable<vec2>): void {
vec2.copy(this.viewportDimensions, d)
this.canvas3d.width = this.canvas2d.width = this.viewportDimensions[0]
this.canvas3d.height = this.canvas2d.height = this.viewportDimensions[1]

this.sim.setViewportDimensions(this.viewportDimensions)
this.view.setViewportDimensions(this.viewportDimensions)
}

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

restartServer(): Promise<void> {
return fetch(
`${this.location.protocol}//${this.location.host}/api/restart`,
).then(() => {
this.keyboard = new DocumentEventKeyboard(this.document)
this.mouse = new DocumentEventMouse(this.document)
this.debugDraw = new DebugDraw()

this.view = new ClientView({
canvas3d: this.canvas3d,
canvas2d: this.canvas2d,
debugDraw: this.debugDraw,
})

this.sim = new ClientSim({
keyboard: this.keyboard,
mouse: this.mouse,
modelLoader: this.view.getModelLoader(),
debugDraw: this.debugDraw,
viewportDimensions: this.viewportDimensions,
})

return this.connectToServer()
})
}
}
2 changes: 1 addition & 1 deletion src/ClientSim.ts → src/client/ClientSim.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { quat, vec2, vec3, vec4 } from 'gl-matrix'

import { Camera3d } from '~/camera/Camera3d'
import { Renderable3d } from '~/ClientView'
import { Renderable3d } from '~/client/ClientView'
import {
MAX_PREDICTED_FRAMES,
SIMULATION_PERIOD_S,
Expand Down
File renamed without changes.
File renamed without changes.
135 changes: 18 additions & 117 deletions src/clientMain.ts
Original file line number Diff line number Diff line change
@@ -1,131 +1,34 @@
import { vec2 } from 'gl-matrix'

import * as clientHotReload from '~/clientHotReload'
import { ClientSim } from '~/ClientSim'
import { ClientView } from '~/ClientView'
import { DebugDraw } from '~/DebugDraw'
import { GameState } from '~/Game'
import { DocumentEventKeyboard } from '~/input/DocumentEventKeyboard'
import { DocumentEventMouse } from '~/input/DocumentEventMouse'
import { IKeyboard, IMouse } from '~/input/interfaces'
import { createServerConnectionWs } from '~/network/ServerConnection'
import { Client } from '~/client/Client'
import * as clientHotReload from '~/client/hotReload'

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

// disable right clicks
document.addEventListener('contextmenu', (e) => e.preventDefault())

const canvas3d = document.createElement('canvas')
canvas3d.setAttribute(
'style',
'position: absolute; top: 0; left: 0; z-index: 0',
)
canvas3d.width = window.innerWidth
canvas3d.height = window.innerHeight
document.body.appendChild(canvas3d)

const canvas2d = document.createElement('canvas')
canvas2d.setAttribute(
'style',
'position: absolute; top: 0; left: 0; z-index: 1',
)
canvas2d.width = window.innerWidth
canvas2d.height = window.innerHeight
document.body.appendChild(canvas2d)

// TODO: refactor this whole thing into a class...the way this currently works
// is gross
function makeClientObjects(): [
ClientSim,
ClientView,
IKeyboard,
IMouse,
DebugDraw,
] {
const keyboard = new DocumentEventKeyboard(document)
const mouse = new DocumentEventMouse(document)
const debugDraw = new DebugDraw()

const clientView = new ClientView({
canvas3d,
canvas2d,
debugDraw,
})

const client = new ClientSim({
keyboard,
mouse,
modelLoader: clientView.getModelLoader(),
debugDraw,
viewportDimensions: vec2.fromValues(window.innerWidth, window.innerHeight),
})

return [client, clientView, keyboard, mouse, debugDraw]
}

let [clientSim, clientView, keyboard, mouse, debugDraw] = makeClientObjects()

function syncViewportSize() {
const size = vec2.fromValues(window.innerWidth, window.innerHeight)
canvas3d.width = canvas2d.width = size[0]
canvas3d.height = canvas2d.height = size[1]

clientSim.setViewportDimensions(size)
clientView.setViewportDimensions(size)
}
const client = new Client({
document,
location,
viewportDimensions: vec2.fromValues(window.innerWidth, window.innerHeight),
})

window.addEventListener('resize', syncViewportSize)
window.addEventListener('resize', () => {
client.syncViewportDimensions(
vec2.fromValues(window.innerWidth, window.innerHeight),
)
})

function clientRenderLoop() {
requestAnimationFrame(clientRenderLoop)
clientSim.update()

if (keyboard.upKeys.has('Backquote')) {
debugDraw.setEnabled(!debugDraw.isEnabled())
}

// TODO: figure out a better way to prevent unloaded models from rendering.
// Maybe: getRenderables3d() should not return renderables for models that
// haven't been loaded yet!
if (clientSim.state !== GameState.Connecting) {
clientView.update({
world2ViewTransform: clientSim.camera.getWvTransform(),
renderables3d: clientSim.getRenderables3d(),
})
}

keyboard.update()
mouse.update()
debugDraw.update()
client.update()
}

clientRenderLoop()

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

connectToServer()

function restartServer(): Promise<void> {
return fetch(`${location.protocol}//${location.host}/api/restart`).then(
() => {
;[clientSim, clientView, keyboard, mouse, debugDraw] = makeClientObjects()
return connectToServer()
},
)
}
client.connectToServer()

// Add a debounced hotkey for restarting the server
let restartHotkeyTimeout: number | undefined = undefined
Expand All @@ -138,15 +41,13 @@ document.addEventListener('keyup', (event) => {
restartHotkeyTimeout = setTimeout(() => {
restartHotkeyTimeout = undefined
}, 500)
restartServer()

client.restartServer()
}
})

// Ensure auto-reloading for dev
clientHotReload.init({ enabled: true })

// Development-related globals
window.debug = {
client: clientSim,
restartServer,
}
window.client = client
2 changes: 1 addition & 1 deletion src/serverMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import koaSend from 'koa-send'
import * as WebSocket from 'ws'

import { buildkeyPath, clientBuildOutputPath } from '~/cli/build/common'
import { updateEntrypointHtmlForHotReload } from '~/clientHotReload'
import { updateEntrypointHtmlForHotReload } from '~/client/hotReload'
import { SIMULATION_PERIOD_S } from '~/constants'
import { ClientConnectionWs } from '~/network/ClientConnection'
import { Server as GameServer } from '~/Server'
Expand Down
2 changes: 1 addition & 1 deletion src/systems/client/playerInput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { vec2 } from 'gl-matrix'
import { vec4 } from 'gl-matrix'
import { vec3 } from 'gl-matrix'

import { ClientSim } from '~/ClientSim'
import { ClientSim } from '~/client/ClientSim'
import { DirectionMove } from '~/input/interfaces'
import { MouseButton } from '~/input/interfaces'
import { ClientMessageType } from '~/network/ClientMessage'
Expand Down
2 changes: 1 addition & 1 deletion src/systems/client/syncServerState.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ClientSim } from '~/ClientSim'
import { ClientSim } from '~/client/ClientSim'
import { mockDebugDraw } from '~/DebugDraw'
import { simulate } from '~/simulate'

Expand Down
2 changes: 1 addition & 1 deletion src/systems/hud/crosshair.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ClientSim } from '~/ClientSim'
import { ClientSim } from '~/client/ClientSim'
import { CursorMode } from '~/systems/client/playerInput'

export const update = (c: ClientSim): void => {
Expand Down

0 comments on commit 4dd55c3

Please sign in to comment.