mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-27 00:54:36 +00:00
make server more efficient
This commit is contained in:
+1
-1
@@ -16,6 +16,6 @@ COPY . .
|
||||
# Build the client-side application
|
||||
RUN npm run build-prod
|
||||
# Expose the port the app runs on
|
||||
EXPOSE 3000
|
||||
EXPOSE 3000 9229
|
||||
# Define the command to run the app
|
||||
CMD ["npm", "run", "start:server"]
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
version: '3'
|
||||
version: "3"
|
||||
services:
|
||||
game-server:
|
||||
build: .
|
||||
ports:
|
||||
- "3000:3000"
|
||||
- "9229:9229"
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
nginx:
|
||||
@@ -15,4 +16,4 @@ services:
|
||||
- ./nginx.conf:/etc/nginx/nginx.conf
|
||||
- /etc/letsencrypt:/etc/letsencrypt
|
||||
depends_on:
|
||||
- game-server
|
||||
- game-server
|
||||
|
||||
+2
-2
@@ -5,12 +5,12 @@
|
||||
"build-dev": "webpack --config webpack.config.js --mode development",
|
||||
"build-prod": "webpack --config webpack.config.js --mode production",
|
||||
"start:client": "webpack serve --open --node-env development",
|
||||
"start:server": "node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
|
||||
"start:server": "node --inspect=0.0.0.0:9229 --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
|
||||
"start:server-dev": "GAME_ENV=dev node --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts",
|
||||
"dev": "GAME_ENV=dev concurrently \"npm run start:client\" \"npm run start:server-dev\"",
|
||||
"tunnel": "npm run build-prod && npm run start:server",
|
||||
"test": "jest",
|
||||
"tailwind": "tailwindcss build -i ./src/client/tailwind.css -o public/tailwind.css"
|
||||
"start:server-dev-profile": "GAME_ENV=dev node --inspect --trace-gc --loader ts-node/esm --experimental-specifier-resolution=node src/server/Server.ts"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
|
||||
Vendored
BIN
Binary file not shown.
@@ -35,7 +35,7 @@
|
||||
OpenFront.io
|
||||
</h1>
|
||||
<h2 class="text-3xl sm:text-4xl md:text-5xl lg:text-6xl mb-4">
|
||||
(v0.14.0)
|
||||
(v0.14.2)
|
||||
</h2>
|
||||
<div class="flex justify-center items-start">
|
||||
<div class="w-full max-w-3xl p-4 space-y-4">
|
||||
|
||||
@@ -1,4 +1,17 @@
|
||||
import { Difficulty, GameType, Gold, Player, PlayerID, PlayerInfo, TerraNullius, Tick, Tile, Unit, UnitInfo, UnitType } from "../game/Game";
|
||||
import {
|
||||
Difficulty,
|
||||
GameType,
|
||||
Gold,
|
||||
Player,
|
||||
PlayerID,
|
||||
PlayerInfo,
|
||||
TerraNullius,
|
||||
Tick,
|
||||
Tile,
|
||||
Unit,
|
||||
UnitInfo,
|
||||
UnitType,
|
||||
} from "../game/Game";
|
||||
import { Colord, colord } from "colord";
|
||||
import { preprodConfig } from "./PreprodConfig";
|
||||
import { prodConfig } from "./ProdConfig";
|
||||
@@ -8,100 +21,110 @@ import { DefaultConfig } from "./DefaultConfig";
|
||||
import { DevConfig, DevServerConfig } from "./DevConfig";
|
||||
|
||||
export enum GameEnv {
|
||||
Dev,
|
||||
Prod
|
||||
Dev,
|
||||
Prod,
|
||||
}
|
||||
export function getConfig(gameConfig: GameConfig): Config {
|
||||
const sc = getServerConfig()
|
||||
switch (process.env.GAME_ENV) {
|
||||
case 'dev':
|
||||
return new DevConfig(sc, gameConfig)
|
||||
case 'preprod':
|
||||
case 'prod':
|
||||
consolex.log('using prod config')
|
||||
return new DefaultConfig(sc, gameConfig)
|
||||
default:
|
||||
throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`)
|
||||
}
|
||||
const sc = getServerConfig();
|
||||
switch (process.env.GAME_ENV) {
|
||||
case "dev":
|
||||
return new DevConfig(sc, gameConfig);
|
||||
case "preprod":
|
||||
case "prod":
|
||||
consolex.log("using prod config");
|
||||
return new DefaultConfig(sc, gameConfig);
|
||||
default:
|
||||
throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`);
|
||||
}
|
||||
}
|
||||
|
||||
export function getServerConfig(): ServerConfig {
|
||||
switch (process.env.GAME_ENV) {
|
||||
case 'dev':
|
||||
consolex.log('using dev config')
|
||||
return new DevServerConfig()
|
||||
case 'preprod':
|
||||
consolex.log('using preprod config')
|
||||
return preprodConfig
|
||||
case 'prod':
|
||||
consolex.log('using prod config')
|
||||
return prodConfig
|
||||
default:
|
||||
throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`)
|
||||
}
|
||||
switch (process.env.GAME_ENV) {
|
||||
case "dev":
|
||||
consolex.log("using dev config");
|
||||
return new DevServerConfig();
|
||||
case "preprod":
|
||||
consolex.log("using preprod config");
|
||||
return preprodConfig;
|
||||
case "prod":
|
||||
default:
|
||||
consolex.log("using prod config");
|
||||
return prodConfig;
|
||||
// default:
|
||||
// throw Error(`unsupported server configuration: ${process.env.GAME_ENV}`)
|
||||
}
|
||||
}
|
||||
|
||||
export interface ServerConfig {
|
||||
turnIntervalMs(): number
|
||||
gameCreationRate(): number
|
||||
lobbyLifetime(): number
|
||||
turnIntervalMs(): number;
|
||||
gameCreationRate(): number;
|
||||
lobbyLifetime(): number;
|
||||
}
|
||||
|
||||
export interface Config {
|
||||
serverConfig(): ServerConfig
|
||||
gameConfig(): GameConfig
|
||||
theme(): Theme;
|
||||
percentageTilesOwnedToWin(): number
|
||||
numBots(): number
|
||||
spawnNPCs(): boolean
|
||||
numSpawnPhaseTurns(gameType: GameType): number
|
||||
serverConfig(): ServerConfig;
|
||||
gameConfig(): GameConfig;
|
||||
theme(): Theme;
|
||||
percentageTilesOwnedToWin(): number;
|
||||
numBots(): number;
|
||||
spawnNPCs(): boolean;
|
||||
numSpawnPhaseTurns(gameType: GameType): number;
|
||||
|
||||
startManpower(playerInfo: PlayerInfo): number
|
||||
populationIncreaseRate(player: Player): number
|
||||
goldAdditionRate(player: Player): number
|
||||
troopAdjustmentRate(player: Player): number
|
||||
attackTilesPerTick(attckTroops: number, attacker: Player, defender: Player | TerraNullius, numAdjacentTilesWithEnemy: number): number
|
||||
attackLogic(attackTroops: number, attacker: Player, defender: Player | TerraNullius, tileToConquer: Tile): {
|
||||
attackerTroopLoss: number,
|
||||
defenderTroopLoss: number,
|
||||
tilesPerTickUsed: number
|
||||
}
|
||||
attackAmount(attacker: Player, defender: Player | TerraNullius): number
|
||||
maxPopulation(player: Player): number
|
||||
cityPopulationIncrease(): number
|
||||
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number
|
||||
boatMaxDistance(): number
|
||||
boatMaxNumber(): number
|
||||
allianceDuration(): Tick
|
||||
allianceRequestCooldown(): Tick
|
||||
targetDuration(): Tick
|
||||
targetCooldown(): Tick
|
||||
emojiMessageCooldown(): Tick
|
||||
emojiMessageDuration(): Tick
|
||||
donateCooldown(): Tick
|
||||
defaultDonationAmount(sender: Player): number
|
||||
unitInfo(type: UnitType): UnitInfo
|
||||
tradeShipGold(src: Unit, dst: Unit): Gold
|
||||
tradeShipSpawnRate(): number
|
||||
defensePostRange(): number
|
||||
defensePostDefenseBonus(): number
|
||||
falloutDefenseModifier(): number
|
||||
difficultyModifier(difficulty: Difficulty): number
|
||||
startManpower(playerInfo: PlayerInfo): number;
|
||||
populationIncreaseRate(player: Player): number;
|
||||
goldAdditionRate(player: Player): number;
|
||||
troopAdjustmentRate(player: Player): number;
|
||||
attackTilesPerTick(
|
||||
attckTroops: number,
|
||||
attacker: Player,
|
||||
defender: Player | TerraNullius,
|
||||
numAdjacentTilesWithEnemy: number
|
||||
): number;
|
||||
attackLogic(
|
||||
attackTroops: number,
|
||||
attacker: Player,
|
||||
defender: Player | TerraNullius,
|
||||
tileToConquer: Tile
|
||||
): {
|
||||
attackerTroopLoss: number;
|
||||
defenderTroopLoss: number;
|
||||
tilesPerTickUsed: number;
|
||||
};
|
||||
attackAmount(attacker: Player, defender: Player | TerraNullius): number;
|
||||
maxPopulation(player: Player): number;
|
||||
cityPopulationIncrease(): number;
|
||||
boatAttackAmount(attacker: Player, defender: Player | TerraNullius): number;
|
||||
boatMaxDistance(): number;
|
||||
boatMaxNumber(): number;
|
||||
allianceDuration(): Tick;
|
||||
allianceRequestCooldown(): Tick;
|
||||
targetDuration(): Tick;
|
||||
targetCooldown(): Tick;
|
||||
emojiMessageCooldown(): Tick;
|
||||
emojiMessageDuration(): Tick;
|
||||
donateCooldown(): Tick;
|
||||
defaultDonationAmount(sender: Player): number;
|
||||
unitInfo(type: UnitType): UnitInfo;
|
||||
tradeShipGold(src: Unit, dst: Unit): Gold;
|
||||
tradeShipSpawnRate(): number;
|
||||
defensePostRange(): number;
|
||||
defensePostDefenseBonus(): number;
|
||||
falloutDefenseModifier(): number;
|
||||
difficultyModifier(difficulty: Difficulty): number;
|
||||
}
|
||||
|
||||
export interface Theme {
|
||||
playerInfoColor(id: PlayerID): Colord;
|
||||
territoryColor(playerInfo: PlayerInfo): Colord;
|
||||
borderColor(playerInfo: PlayerInfo): Colord;
|
||||
defendedBorderColor(playerInfo: PlayerInfo): Colord;
|
||||
terrainColor(tile: Tile): Colord;
|
||||
backgroundColor(): Colord;
|
||||
falloutColor(): Colord
|
||||
font(): string;
|
||||
// unit color for alternate view
|
||||
selfColor(): Colord
|
||||
allyColor(): Colord
|
||||
enemyColor(): Colord
|
||||
spawnHighlightColor(): Colord
|
||||
playerInfoColor(id: PlayerID): Colord;
|
||||
territoryColor(playerInfo: PlayerInfo): Colord;
|
||||
borderColor(playerInfo: PlayerInfo): Colord;
|
||||
defendedBorderColor(playerInfo: PlayerInfo): Colord;
|
||||
terrainColor(tile: Tile): Colord;
|
||||
backgroundColor(): Colord;
|
||||
falloutColor(): Colord;
|
||||
font(): string;
|
||||
// unit color for alternate view
|
||||
selfColor(): Colord;
|
||||
allyColor(): Colord;
|
||||
enemyColor(): Colord;
|
||||
spawnHighlightColor(): Colord;
|
||||
}
|
||||
|
||||
|
||||
+170
-150
@@ -1,17 +1,27 @@
|
||||
import express, { json } from 'express';
|
||||
import http from 'http';
|
||||
import { WebSocketServer } from 'ws';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import { GameManager } from './GameManager';
|
||||
import { ClientMessage, ClientMessageSchema, GameRecord, GameRecordSchema, LogSeverity } from '../core/Schemas';
|
||||
import { getConfig, getServerConfig } from '../core/configuration/Config';
|
||||
import { slog } from './StructuredLog';
|
||||
import { Client } from './Client';
|
||||
import { GamePhase, GameServer } from './GameServer';
|
||||
import { archive } from './Archive';
|
||||
import { DiscordBot } from './DiscordBot';
|
||||
import { sanitizeUsername, validateUsername } from "../core/validations/username";
|
||||
import express, { json } from "express";
|
||||
import http from "http";
|
||||
import { WebSocketServer } from "ws";
|
||||
import path from "path";
|
||||
import { fileURLToPath } from "url";
|
||||
import { GameManager } from "./GameManager";
|
||||
import {
|
||||
ClientMessage,
|
||||
ClientMessageSchema,
|
||||
GameRecord,
|
||||
GameRecordSchema,
|
||||
LogSeverity,
|
||||
} from "../core/Schemas";
|
||||
import { getConfig, getServerConfig } from "../core/configuration/Config";
|
||||
import { slog } from "./StructuredLog";
|
||||
import { Client } from "./Client";
|
||||
import { GamePhase, GameServer } from "./GameServer";
|
||||
import { archive } from "./Archive";
|
||||
import { DiscordBot } from "./DiscordBot";
|
||||
import {
|
||||
sanitizeUsername,
|
||||
validateUsername,
|
||||
} from "../core/validations/username";
|
||||
import { Request, Response } from "express";
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
@@ -21,170 +31,180 @@ const server = http.createServer(app);
|
||||
const wss = new WebSocketServer({ server });
|
||||
|
||||
// Serve static files from the 'out' directory
|
||||
app.use(express.static(path.join(__dirname, '../../out')));
|
||||
app.use(express.json())
|
||||
app.use(express.static(path.join(__dirname, "../../out")));
|
||||
app.use(express.json());
|
||||
|
||||
const gm = new GameManager(getServerConfig())
|
||||
const gm = new GameManager(getServerConfig());
|
||||
|
||||
const bot = new DiscordBot();
|
||||
try {
|
||||
await bot.start();
|
||||
await bot.start();
|
||||
} catch (error) {
|
||||
console.error('Failed to start bot:', error);
|
||||
console.error("Failed to start bot:", error);
|
||||
}
|
||||
|
||||
let lobbiesString = "";
|
||||
|
||||
// New GET endpoint to list lobbies
|
||||
app.get('/lobbies', (req, res) => {
|
||||
const now = Date.now()
|
||||
res.json({
|
||||
lobbies: gm.gamesByPhase(GamePhase.Lobby)
|
||||
.filter(g => g.isPublic)
|
||||
.map(g => ({ id: g.id, msUntilStart: g.startTime() - now, numClients: g.numClients() }))
|
||||
.sort((a, b) => a.msUntilStart - b.msUntilStart),
|
||||
});
|
||||
app.get("/lobbies", (req: Request, res: Response) => {
|
||||
res.send(lobbiesString);
|
||||
});
|
||||
|
||||
app.post('/private_lobby', (req, res) => {
|
||||
const id = gm.createPrivateGame()
|
||||
console.log('creating private lobby with id ${id}')
|
||||
res.json({
|
||||
id: id
|
||||
});
|
||||
app.post("/private_lobby", (req, res) => {
|
||||
const id = gm.createPrivateGame();
|
||||
console.log("creating private lobby with id ${id}");
|
||||
res.json({
|
||||
id: id,
|
||||
});
|
||||
});
|
||||
|
||||
app.post('/archive_singleplayer_game', (req, res) => {
|
||||
app.post("/archive_singleplayer_game", (req, res) => {
|
||||
try {
|
||||
const gameRecord: GameRecord = req.body;
|
||||
const clientIP = req.ip || req.socket.remoteAddress || "unknown"; // Added this line
|
||||
|
||||
if (!gameRecord) {
|
||||
console.log("game record not found in request");
|
||||
res.status(404).json({ error: "Game record not found" });
|
||||
return;
|
||||
}
|
||||
gameRecord.players.forEach((p) => (p.ip = clientIP));
|
||||
GameRecordSchema.parse(gameRecord);
|
||||
archive(gameRecord);
|
||||
res.json({
|
||||
success: true,
|
||||
});
|
||||
} catch (error) {
|
||||
slog({
|
||||
logKey: "complete_single_player_game_record",
|
||||
msg: `Failed to complete game record: ${error}`,
|
||||
severity: LogSeverity.Error,
|
||||
});
|
||||
res.status(400).json({ error: "Invalid game record format" });
|
||||
}
|
||||
});
|
||||
|
||||
app.post("/start_private_lobby/:id", (req, res) => {
|
||||
console.log(`starting private lobby with id ${req.params.id}`);
|
||||
gm.startPrivateGame(req.params.id);
|
||||
});
|
||||
|
||||
app.put("/private_lobby/:id", (req, res) => {
|
||||
const lobbyID = req.params.id;
|
||||
gm.updateGameConfig(lobbyID, {
|
||||
gameMap: req.body.gameMap,
|
||||
difficulty: req.body.difficulty,
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/lobby/:id/exists", (req, res) => {
|
||||
const lobbyId = req.params.id;
|
||||
console.log(`checking lobby ${lobbyId} exists`);
|
||||
const lobbyExists = gm.hasActiveGame(lobbyId);
|
||||
|
||||
res.json({
|
||||
exists: lobbyExists,
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/lobby/:id", (req, res) => {
|
||||
const game = gm.game(req.params.id);
|
||||
if (game == null) {
|
||||
console.log(`lobby ${req.params.id} not found`);
|
||||
return res.status(404).json({ error: "Game not found" });
|
||||
}
|
||||
res.json({
|
||||
players: game.activeClients.map((c) => ({
|
||||
username: c.username,
|
||||
clientID: c.clientID,
|
||||
})),
|
||||
});
|
||||
});
|
||||
|
||||
app.get("/private_lobby/:id", (req, res) => {
|
||||
res.json({
|
||||
hi: "5",
|
||||
});
|
||||
});
|
||||
|
||||
wss.on("connection", (ws, req) => {
|
||||
ws.on("message", (message: string) => {
|
||||
try {
|
||||
const gameRecord: GameRecord = req.body
|
||||
const clientIP = req.ip || req.socket.remoteAddress || 'unknown'; // Added this line
|
||||
|
||||
|
||||
if (!gameRecord) {
|
||||
console.log('game record not found in request')
|
||||
res.status(404).json({ error: 'Game record not found' });
|
||||
return;
|
||||
const clientMsg: ClientMessage = ClientMessageSchema.parse(
|
||||
JSON.parse(message)
|
||||
);
|
||||
if (clientMsg.type == "join") {
|
||||
const forwarded = req.headers["x-forwarded-for"];
|
||||
let ip = Array.isArray(forwarded)
|
||||
? forwarded[0] // Get the first IP if it's an array
|
||||
: forwarded || req.socket.remoteAddress;
|
||||
if (Array.isArray(ip)) {
|
||||
ip = ip[0];
|
||||
}
|
||||
gameRecord.players.forEach(p => p.ip = clientIP)
|
||||
GameRecordSchema.parse(gameRecord);
|
||||
archive(gameRecord)
|
||||
res.json({
|
||||
success: true,
|
||||
});
|
||||
} catch (error) {
|
||||
const { isValid, error } = validateUsername(clientMsg.username);
|
||||
if (!isValid) {
|
||||
console.log(
|
||||
`game ${clientMsg.gameID}, client ${clientMsg.clientID} received invalid username, ${error}`
|
||||
);
|
||||
return;
|
||||
}
|
||||
clientMsg.username = sanitizeUsername(clientMsg.username);
|
||||
gm.addClient(
|
||||
new Client(
|
||||
clientMsg.clientID,
|
||||
clientMsg.persistentID,
|
||||
ip,
|
||||
clientMsg.username,
|
||||
ws
|
||||
),
|
||||
clientMsg.gameID,
|
||||
clientMsg.lastTurn
|
||||
);
|
||||
}
|
||||
if (clientMsg.type == "log") {
|
||||
slog({
|
||||
logKey: 'complete_single_player_game_record',
|
||||
msg: `Failed to complete game record: ${error}`,
|
||||
severity: LogSeverity.Error,
|
||||
logKey: "client_console_log",
|
||||
msg: clientMsg.log,
|
||||
severity: clientMsg.severity,
|
||||
clientID: clientMsg.clientID,
|
||||
gameID: clientMsg.gameID,
|
||||
persistentID: clientMsg.persistentID,
|
||||
});
|
||||
res.status(400).json({ error: 'Invalid game record format' });
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`errror handling websocket message: ${error}`);
|
||||
}
|
||||
})
|
||||
|
||||
app.post('/start_private_lobby/:id', (req, res) => {
|
||||
console.log(`starting private lobby with id ${req.params.id}`)
|
||||
gm.startPrivateGame(req.params.id)
|
||||
});
|
||||
|
||||
app.put('/private_lobby/:id', (req, res) => {
|
||||
const lobbyID = req.params.id
|
||||
gm.updateGameConfig(lobbyID, { gameMap: req.body.gameMap, difficulty: req.body.difficulty })
|
||||
});
|
||||
|
||||
app.get('/lobby/:id/exists', (req, res) => {
|
||||
const lobbyId = req.params.id;
|
||||
console.log(`checking lobby ${lobbyId} exists`)
|
||||
const lobbyExists = gm.hasActiveGame(lobbyId);
|
||||
|
||||
res.json({
|
||||
exists: lobbyExists
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/lobby/:id', (req, res) => {
|
||||
const game = gm.game(req.params.id)
|
||||
if (game == null) {
|
||||
console.log(`lobby ${req.params.id} not found`)
|
||||
return res.status(404).json({ error: 'Game not found' });
|
||||
}
|
||||
res.json({
|
||||
players: game.activeClients.map(c => ({
|
||||
username: c.username,
|
||||
clientID: c.clientID
|
||||
}))
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
app.get('/private_lobby/:id', (req, res) => {
|
||||
res.json({
|
||||
hi: '5'
|
||||
});
|
||||
});
|
||||
|
||||
wss.on('connection', (ws, req) => {
|
||||
ws.on('message', (message: string) => {
|
||||
try {
|
||||
const clientMsg: ClientMessage = ClientMessageSchema.parse(JSON.parse(message))
|
||||
slog({
|
||||
logKey: 'websocket_msg',
|
||||
msg: 'server received websocket message',
|
||||
data: clientMsg,
|
||||
severity: LogSeverity.Debug
|
||||
})
|
||||
if (clientMsg.type == "join") {
|
||||
const forwarded = req.headers['x-forwarded-for']
|
||||
let ip = Array.isArray(forwarded)
|
||||
? forwarded[0] // Get the first IP if it's an array
|
||||
: forwarded || req.socket.remoteAddress;
|
||||
if (Array.isArray(ip)) {
|
||||
ip = ip[0]
|
||||
}
|
||||
const { isValid, error } = validateUsername(clientMsg.username);
|
||||
if (!isValid) {
|
||||
console.log(`game ${clientMsg.gameID}, client ${clientMsg.clientID} received invalid username, ${error}`)
|
||||
return;
|
||||
}
|
||||
clientMsg.username = sanitizeUsername(clientMsg.username)
|
||||
gm.addClient(
|
||||
new Client(
|
||||
clientMsg.clientID,
|
||||
clientMsg.persistentID,
|
||||
ip,
|
||||
clientMsg.username,
|
||||
ws
|
||||
),
|
||||
clientMsg.gameID,
|
||||
clientMsg.lastTurn
|
||||
)
|
||||
}
|
||||
if (clientMsg.type == "log") {
|
||||
slog({
|
||||
logKey: "client_console_log",
|
||||
msg: clientMsg.log,
|
||||
severity: clientMsg.severity,
|
||||
clientID: clientMsg.clientID,
|
||||
gameID: clientMsg.gameID,
|
||||
persistentID: clientMsg.persistentID,
|
||||
})
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(`errror handling websocket message: ${error}`)
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
function runGame() {
|
||||
setInterval(() => tick(), 1000);
|
||||
setInterval(() => tick(), 1000);
|
||||
setInterval(() => updateLobbies(), 100);
|
||||
}
|
||||
|
||||
function tick() {
|
||||
gm.tick()
|
||||
gm.tick();
|
||||
}
|
||||
|
||||
function updateLobbies() {
|
||||
lobbiesString = JSON.stringify({
|
||||
lobbies: gm
|
||||
.gamesByPhase(GamePhase.Lobby)
|
||||
.filter((g) => g.isPublic)
|
||||
.map((g) => ({
|
||||
id: g.id,
|
||||
msUntilStart: g.startTime() - Date.now(),
|
||||
numClients: g.numClients(),
|
||||
}))
|
||||
.sort((a, b) => a.msUntilStart - b.msUntilStart),
|
||||
});
|
||||
}
|
||||
|
||||
const PORT = process.env.PORT || 3000;
|
||||
console.log(`Server will try to run on http://localhost:${PORT}`);
|
||||
|
||||
server.listen(PORT, () => {
|
||||
console.log(`Server is running on http://localhost:${PORT}`);
|
||||
console.log(`Server is running on http://localhost:${PORT}`);
|
||||
});
|
||||
|
||||
runGame()
|
||||
runGame();
|
||||
|
||||
+4
-4
@@ -18,20 +18,20 @@ fi
|
||||
if [[ "$ENV" == "dev" ]]; then
|
||||
INSTANCE_NAME="openfrontio-dev-instance"
|
||||
TAG="dev"
|
||||
GAME_ENV="preprod" # Set game environment to preprod for dev
|
||||
GAME_ENV="preprod"
|
||||
echo "[DEV] Deploying to openfront.dev"
|
||||
else
|
||||
INSTANCE_NAME="openfrontio-instance"
|
||||
TAG="latest"
|
||||
GAME_ENV="prod" # Set game environment to prod for prod
|
||||
GAME_ENV="prod"
|
||||
echo "[PROD] Deploying to openfront.io"
|
||||
fi
|
||||
|
||||
# Ensure you're authenticated with Google Cloud
|
||||
gcloud auth configure-docker us-central1-docker.pkg.dev
|
||||
|
||||
# Build the new Docker image with GAME_ENV build argument
|
||||
docker build --build-arg GAME_ENV=$GAME_ENV -t openfrontio .
|
||||
# Build the new Docker image with platform specification and GAME_ENV build argument
|
||||
docker build --platform linux/amd64 --build-arg GAME_ENV=$GAME_ENV -t openfrontio .
|
||||
|
||||
# Tag the new image
|
||||
docker tag openfrontio us-central1-docker.pkg.dev/openfrontio/openfrontio/game-server:$TAG
|
||||
|
||||
Reference in New Issue
Block a user