mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-06-21 23:51:55 +00:00
Merge branch 'main' into mac
This commit is contained in:
+7
-2
@@ -59,8 +59,13 @@ COPY supervisord.conf /etc/supervisor/conf.d/supervisord.conf
|
||||
COPY startup.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/startup.sh
|
||||
|
||||
RUN mkdir -p /tmp/.cloudflared && chmod 777 /tmp/.cloudflared
|
||||
ENV CF_CONFIG_DIR=/tmp/.cloudflared
|
||||
RUN mkdir -p /etc/cloudflared && \
|
||||
chown -R node:node /etc/cloudflared && \
|
||||
chmod -R 755 /etc/cloudflared
|
||||
|
||||
# Set Cloudflared config directory to a volume mount location
|
||||
ENV CF_CONFIG_PATH=/etc/cloudflared/config.yml
|
||||
ENV CF_CREDS_PATH=/etc/cloudflared/creds.json
|
||||
|
||||
# Use the startup script as the entrypoint
|
||||
ENTRYPOINT ["/usr/local/bin/startup.sh"]
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { LitElement, html } from "lit";
|
||||
import { customElement, query } from "lit/decorators.js";
|
||||
import { getEmojiKey, getModifierKey, translateText } from "../client/Utils";
|
||||
import { getAltKey, getModifierKey, translateText } from "../client/Utils";
|
||||
import "./components/Difficulties";
|
||||
import "./components/Maps";
|
||||
|
||||
@@ -67,7 +67,7 @@ export class HelpModal extends LitElement {
|
||||
<tr>
|
||||
<td>
|
||||
<div class="scroll-combo-horizontal">
|
||||
<span class="key">${getEmojiKey()}</span>
|
||||
<span class="key">${getAltKey()}</span>
|
||||
<span class="plus">+</span>
|
||||
<div class="mouse-shell alt-left-click">
|
||||
<div class="mouse-left-corner"></div>
|
||||
@@ -116,7 +116,8 @@ export class HelpModal extends LitElement {
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<span class="key">ALT</span> + <span class="key">R</span>
|
||||
<span class="key">${getAltKey()}</span> +
|
||||
<span class="key">R</span>
|
||||
</td>
|
||||
<td>${translateText("help_modal.action_reset_gfx")}</td>
|
||||
</tr>
|
||||
|
||||
@@ -129,7 +129,7 @@ export class InputHandler {
|
||||
attackRatioUp: "Digit2",
|
||||
boatAttack: "KeyB",
|
||||
modifierKey: "ControlLeft",
|
||||
emojiKey: "AltLeft",
|
||||
altKey: "AltLeft",
|
||||
...JSON.parse(localStorage.getItem("settings.keybinds") ?? "{}"),
|
||||
};
|
||||
|
||||
@@ -137,7 +137,6 @@ export class InputHandler {
|
||||
const isMac = /Mac/.test(navigator.userAgent);
|
||||
if (isMac) {
|
||||
this.keybinds.modifierKey = "MetaLeft"; // Use Command key on Mac
|
||||
this.keybinds.emojiKey = "AltLeft"; // Use Option key for emoji menu on Mac
|
||||
}
|
||||
|
||||
this.canvas.addEventListener("pointerdown", (e) => this.onPointerDown(e));
|
||||
@@ -312,7 +311,7 @@ export class InputHandler {
|
||||
this.eventBus.emit(new ShowBuildMenuEvent(event.clientX, event.clientY));
|
||||
return;
|
||||
}
|
||||
if (this.isEmojiKeyPressed(event)) {
|
||||
if (this.isAltKeyPressed(event)) {
|
||||
this.eventBus.emit(new ShowEmojiMenuEvent(event.clientX, event.clientY));
|
||||
return;
|
||||
}
|
||||
@@ -421,12 +420,12 @@ export class InputHandler {
|
||||
);
|
||||
}
|
||||
|
||||
isEmojiKeyPressed(event: PointerEvent): boolean {
|
||||
isAltKeyPressed(event: PointerEvent): boolean {
|
||||
return (
|
||||
(this.keybinds.emojiKey === "AltLeft" && event.altKey) ||
|
||||
(this.keybinds.emojiKey === "ControlLeft" && event.ctrlKey) ||
|
||||
(this.keybinds.emojiKey === "ShiftLeft" && event.shiftKey) ||
|
||||
(this.keybinds.emojiKey === "MetaLeft" && event.metaKey)
|
||||
(this.keybinds.altKey === "AltLeft" && event.altKey) ||
|
||||
(this.keybinds.altKey === "ControlLeft" && event.ctrlKey) ||
|
||||
(this.keybinds.altKey === "ShiftLeft" && event.shiftKey) ||
|
||||
(this.keybinds.altKey === "MetaLeft" && event.metaKey)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,6 +290,9 @@ class Client {
|
||||
() => {
|
||||
console.log("Closing modals");
|
||||
document.getElementById("settings-button")?.classList.add("hidden");
|
||||
document
|
||||
.getElementById("username-validation-error")
|
||||
?.classList.add("hidden");
|
||||
[
|
||||
"single-player-modal",
|
||||
"host-lobby-modal",
|
||||
|
||||
@@ -47,6 +47,7 @@ export class UsernameInput extends LitElement {
|
||||
/>
|
||||
${this.validationError
|
||||
? html`<div
|
||||
id="username-validation-error"
|
||||
class="absolute z-10 w-full mt-2 px-3 py-1 text-lg border rounded bg-white text-red-600 border-red-600 dark:bg-gray-700 dark:text-red-300 dark:border-red-300"
|
||||
>
|
||||
${this.validationError}
|
||||
|
||||
+2
-2
@@ -160,11 +160,11 @@ export function getModifierKey(): string {
|
||||
}
|
||||
}
|
||||
|
||||
export function getEmojiKey(): string {
|
||||
export function getAltKey(): string {
|
||||
const isMac = /Mac/.test(navigator.userAgent);
|
||||
if (isMac) {
|
||||
return "⌥"; // Option key
|
||||
} else {
|
||||
return "Ctrl";
|
||||
return "Alt";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,7 +63,6 @@ export class TeamStats extends LitElement implements Layer {
|
||||
let totalScoreSort = 0;
|
||||
|
||||
for (const p of teamPlayers) {
|
||||
totalGold += p.gold();
|
||||
if (p.isAlive()) {
|
||||
totalTroops += p.troops();
|
||||
totalGold += p.gold();
|
||||
|
||||
@@ -60,7 +60,8 @@ export interface ServerConfig {
|
||||
subdomain(): string;
|
||||
cloudflareAccountId(): string;
|
||||
cloudflareApiToken(): string;
|
||||
cloudflareConfigDir(): string;
|
||||
cloudflareConfigPath(): string;
|
||||
cloudflareCredsPath(): string;
|
||||
}
|
||||
|
||||
export interface NukeMagnitude {
|
||||
|
||||
@@ -78,9 +78,13 @@ export abstract class DefaultServerConfig implements ServerConfig {
|
||||
cloudflareApiToken(): string {
|
||||
return process.env.CF_API_TOKEN ?? "";
|
||||
}
|
||||
cloudflareConfigDir(): string {
|
||||
return process.env.CF_CONFIG_DIR ?? "";
|
||||
cloudflareConfigPath(): string {
|
||||
return process.env.CF_CONFIG_PATH ?? "";
|
||||
}
|
||||
cloudflareCredsPath(): string {
|
||||
return process.env.CF_CREDS_PATH ?? "";
|
||||
}
|
||||
|
||||
private publicKey: JWK;
|
||||
abstract jwtAudience(): string;
|
||||
jwtIssuer(): string {
|
||||
|
||||
@@ -470,6 +470,7 @@ export class FakeHumanExecution implements Execution {
|
||||
this.mg.isOceanShore(t),
|
||||
)
|
||||
: Array.from(this.player.tiles());
|
||||
if (tiles.length === 0) return null;
|
||||
return this.random.randElement(tiles);
|
||||
}
|
||||
|
||||
|
||||
+23
-20
@@ -1,7 +1,6 @@
|
||||
import { spawn } from "child_process";
|
||||
import { promises as fs } from "fs";
|
||||
import yaml from "js-yaml";
|
||||
import { join } from "path";
|
||||
import { logger } from "./Logger";
|
||||
|
||||
const log = logger.child({
|
||||
@@ -48,9 +47,11 @@ export class Cloudflare {
|
||||
constructor(
|
||||
private accountId: string,
|
||||
private apiToken: string,
|
||||
private configDir: string,
|
||||
private configPath: string,
|
||||
private credsPath: string,
|
||||
) {
|
||||
log.info(`Using config directory: ${this.configDir}`);
|
||||
log.info(`Using config: ${this.configPath}`);
|
||||
log.info(`Using credentials: ${this.credsPath}`);
|
||||
}
|
||||
|
||||
private async makeRequest<T>(
|
||||
@@ -77,11 +78,19 @@ export class Cloudflare {
|
||||
return response.json() as Promise<T>;
|
||||
}
|
||||
|
||||
public async configAlreadyExists(): Promise<boolean> {
|
||||
try {
|
||||
await fs.access(this.configPath);
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async createTunnel(config: TunnelConfig): Promise<{
|
||||
tunnelId: string;
|
||||
tunnelToken: string;
|
||||
tunnelUrl: string;
|
||||
configPath: string;
|
||||
}> {
|
||||
const { domain, subdomain, subdomainToService } = config;
|
||||
|
||||
@@ -108,7 +117,7 @@ export class Cloudflare {
|
||||
log.info(`Tunnel created with ID: ${tunnelId}`);
|
||||
|
||||
// Create local config file instead of using API configuration
|
||||
const configPath = await this.writeTunnelConfig(
|
||||
await this.writeTunnelConfig(
|
||||
tunnelId,
|
||||
tunnelToken,
|
||||
subdomain,
|
||||
@@ -136,7 +145,7 @@ export class Cloudflare {
|
||||
const tunnelUrl = `https://${subdomain}.${domain}`;
|
||||
log.info(`Tunnel is set up! Site will be available at: ${tunnelUrl}`);
|
||||
|
||||
return { tunnelId, tunnelToken, tunnelUrl, configPath };
|
||||
return { tunnelId, tunnelToken, tunnelUrl };
|
||||
}
|
||||
|
||||
private async writeTunnelConfig(
|
||||
@@ -146,12 +155,8 @@ export class Cloudflare {
|
||||
domain: string,
|
||||
subdomainToService: Map<string, string>,
|
||||
tunnelName: string,
|
||||
): Promise<string> {
|
||||
): Promise<void> {
|
||||
log.info(`Creating local config for tunnel ${subdomain}.${domain}...`);
|
||||
|
||||
const configPath = join(this.configDir, `${tunnelName}.yml`);
|
||||
const credentialsFile = join(this.configDir, `${tunnelId}.json`);
|
||||
|
||||
const tokenData = JSON.parse(
|
||||
Buffer.from(tunnelToken, "base64").toString("utf8"),
|
||||
);
|
||||
@@ -164,15 +169,15 @@ export class Cloudflare {
|
||||
};
|
||||
|
||||
await fs.writeFile(
|
||||
credentialsFile,
|
||||
this.credsPath,
|
||||
JSON.stringify(credentials, null, 2),
|
||||
"utf8",
|
||||
);
|
||||
log.info(`Created credentials file at: ${credentialsFile}`);
|
||||
log.info(`Created credentials file at: ${this.credsPath}`);
|
||||
|
||||
const tunnelConfig: CloudflaredConfig = {
|
||||
tunnel: tunnelId,
|
||||
"credentials-file": credentialsFile,
|
||||
"credentials-file": this.credsPath,
|
||||
ingress: [
|
||||
...Array.from(subdomainToService.entries()).map(
|
||||
([subdomain, service]) => ({
|
||||
@@ -187,10 +192,8 @@ export class Cloudflare {
|
||||
};
|
||||
|
||||
// Write config file
|
||||
await fs.writeFile(configPath, yaml.dump(tunnelConfig), "utf8");
|
||||
log.info(`Created config file at: ${configPath}`);
|
||||
|
||||
return configPath;
|
||||
await fs.writeFile(this.configPath, yaml.dump(tunnelConfig), "utf8");
|
||||
log.info(`Created config file at: ${this.configPath}`);
|
||||
}
|
||||
|
||||
private async updateDNSRecord(
|
||||
@@ -229,10 +232,10 @@ export class Cloudflare {
|
||||
}
|
||||
}
|
||||
|
||||
public async startCloudflared(configPath: string) {
|
||||
public async startCloudflared() {
|
||||
const cloudflared = spawn(
|
||||
"cloudflared",
|
||||
["tunnel", "--config", configPath, "--loglevel", "error", "run"],
|
||||
["tunnel", "--config", this.configPath, "--loglevel", "error", "run"],
|
||||
{
|
||||
detached: true,
|
||||
stdio: ["ignore", "pipe", "pipe"],
|
||||
|
||||
+12
-7
@@ -36,7 +36,8 @@ async function setupTunnels() {
|
||||
const cloudflare = new Cloudflare(
|
||||
config.cloudflareAccountId(),
|
||||
config.cloudflareApiToken(),
|
||||
config.cloudflareConfigDir(),
|
||||
config.cloudflareConfigPath(),
|
||||
config.cloudflareCredsPath(),
|
||||
);
|
||||
|
||||
const domainToService = new Map<string, string>().set(
|
||||
@@ -51,11 +52,15 @@ async function setupTunnels() {
|
||||
);
|
||||
}
|
||||
|
||||
const tunnel = await cloudflare.createTunnel({
|
||||
subdomain: config.subdomain(),
|
||||
domain: config.domain(),
|
||||
subdomainToService: domainToService,
|
||||
} as TunnelConfig);
|
||||
if (!(await cloudflare.configAlreadyExists())) {
|
||||
await cloudflare.createTunnel({
|
||||
subdomain: config.subdomain(),
|
||||
domain: config.domain(),
|
||||
subdomainToService: domainToService,
|
||||
} as TunnelConfig);
|
||||
} else {
|
||||
console.log("Config already exists, skipping tunnel creation");
|
||||
}
|
||||
|
||||
await cloudflare.startCloudflared(tunnel.configPath);
|
||||
await cloudflare.startCloudflared();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,10 @@ import { GameMapType } from "../../src/core/game/Game";
|
||||
import { GameID } from "../../src/core/Schemas";
|
||||
|
||||
export class TestServerConfig implements ServerConfig {
|
||||
cloudflareConfigDir(): string {
|
||||
cloudflareConfigPath(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
cloudflareCredsPath(): string {
|
||||
throw new Error("Method not implemented.");
|
||||
}
|
||||
domain(): string {
|
||||
|
||||
@@ -58,10 +58,15 @@ else
|
||||
fi
|
||||
|
||||
echo "Starting new container for ${HOST} environment..."
|
||||
|
||||
# Remove any existing volume for this container if it exists
|
||||
docker volume rm "cloudflared-${CONTAINER_NAME}" 2> /dev/null || true
|
||||
|
||||
docker run -d \
|
||||
--restart="${RESTART}" \
|
||||
--env-file "$ENV_FILE" \
|
||||
--name "${CONTAINER_NAME}" \
|
||||
-v "cloudflared-${CONTAINER_NAME}:/etc/cloudflared" \
|
||||
"${DOCKER_IMAGE}"
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
|
||||
Reference in New Issue
Block a user