/**
* @file Sets up an Express backend server for examples, serving static files,
* replacing HTML strings, and enabling a game socket service.
* The behavior adapts based on the environment mode (NODE_ENV) inject in process.env with cross-env package.
* See {@link https://nodejs.org/api/process.html#processenv-env}, {@link https://www.npmjs.com/package/cross-env}
*
* requires {@link https://www.npmjs.com/package/@ud-viz/game_node}
* requires {@link https://www.npmjs.com/package/@ud-viz/utils_shared}
* requires {@link https://www.npmjs.com/package/reload}
* requires {@link https://www.npmjs.com/package/string-replace-middleware}
*/
const udvizVersion = require('../package.json').version;
const path = require('path');
const { MESSAGE, RELOAD_PORT, DEFAULT_PORT } = require('./constant');
const reload = require('reload');
const { stringReplace } = require('string-replace-middleware');
const express = require('express');
const { SocketService } = require('@ud-viz/game_node');
const {
NoteManager,
DomElement3DCubeManager,
} = require('@ud-viz/game_node_template');
const { Object3D } = require('@ud-viz/game_shared');
const {
NativeCommandManager,
constant,
} = require('@ud-viz/game_shared_template');
/**
* The environment mode.
*
* @type {string}
*/
const NODE_ENV = process.env.NODE_ENV || 'development';
console.log('Back-end starting in', NODE_ENV, 'mode');
/**
* Express application instance.
*
* @type {object}
*/
const app = new express();
// Apply string replacements for different values in HTML responses
app.use(
stringReplace(
{
RUN_MODE: NODE_ENV,
},
{
contentTypeFilterRegexp: /text\/html/,
}
)
);
app.use(
stringReplace(
{
SCRIPT_TAG_RELOAD:
NODE_ENV == 'development'
? '<script src="/reload/reload.js"></script>'
: '',
},
{
contentTypeFilterRegexp: /text\/html/,
}
)
);
app.use(
stringReplace(
{
UDVIZ_VERSION: udvizVersion,
},
{
contentTypeFilterRegexp: /text\/html/,
}
)
);
// Serve static files
app.use(express.static(path.resolve(__dirname, '../')));
/**
* @type {number}
*/
const PORT = process.env.PORT || DEFAULT_PORT;
/**
* The HTTP server instance.
*
* @type {object}
*/
const httpServer = app.listen(PORT, (err) => {
if (err) {
console.error('Server could not start');
return;
}
console.log('Http server listening on port', PORT);
});
// Initialize examples game socket service
const gameSocketService = new SocketService(httpServer);
gameSocketService
.loadGameThreads(
[
// Define the game thread
new Object3D({
name: 'Note game',
static: true,
matrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1844753.5, 5174961, 0, 1],
components: {
GameScript: {
scriptParams: [
{ id: NoteManager.ID_SCRIPT },
{ id: NativeCommandManager.ID_SCRIPT },
],
},
ExternalScript: {
scriptParams: [
{ id: constant.ID_SCRIPT.NOTE_UI },
{ id: constant.ID_SCRIPT.CAMERA_MANAGER },
],
},
},
}),
new Object3D({
uuid: 'dom_element_3d_cube_game_uuid',
name: 'DomElement 3D cube game',
static: true,
matrix: [1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1844753.5, 5174961, 0, 1],
components: {
GameScript: {
scriptParams: [
{ id: DomElement3DCubeManager.ID_SCRIPT },
{ id: NativeCommandManager.ID_SCRIPT },
],
variables: {
idRenderData: 'cube',
domElement3D: {
position: { x: 0, y: 0.52, z: 0.5 },
rotation: { x: Math.PI * 0.5, y: Math.PI, z: 0 },
scale: { x: 1, y: 1, z: 1 },
},
defaultSpeedTranslate: 0.5,
defaultSpeedRotate: 0.001,
},
},
ExternalScript: {
scriptParams: [
{ id: constant.ID_SCRIPT.CONTROLLER_NATIVE_COMMAND_MANAGER },
],
},
},
}),
],
'./bin/gameThreadChild.js'
)
.then(() => {
console.log('Game SocketService initialized');
// Notify parent process if possible
if (process.send) {
process.send(MESSAGE.READY);
}
if (NODE_ENV == 'development') reload(app, { port: RELOAD_PORT }); // client should have script tag reload
});