GameServer/GameServerStatusHistory/Issue/IssueComment models, a strategy-per-probe_type ServerProbe (tcp_connect/http_get/presence_inferred, mirroring script-library's game-server-registry-probe.py including the integer ConnectTimeout fix), the bundled verified registry seed (WoW, EQEmu, the Goldberg relay, Impostor, OpenDAoC), and full player+admin UI at /community/servers and /community/issues. Featured flag pins the persistent-world servers (WoW/EQEmu/OpenDAoC) to a compact status panel surfaced on the community landing page. Scheduled sweep respects a circuit-breaker backoff and never probes on page load; the relay is never network-probed, only liveness-checked over ssh.
230 lines
7.4 KiB
Vue
230 lines
7.4 KiB
Vue
<template>
|
|
<div class="flex flex-col gap-y-4">
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{ $t("common.name") }}</span>
|
|
<input
|
|
v-model="model.name"
|
|
type="text"
|
|
required
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
/>
|
|
</label>
|
|
|
|
<label class="flex items-center gap-x-2">
|
|
<input
|
|
v-model="model.featured"
|
|
type="checkbox"
|
|
class="rounded bg-zinc-800"
|
|
/>
|
|
<span class="text-sm text-zinc-300">{{
|
|
$t("community.servers.featured")
|
|
}}</span>
|
|
</label>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.kindLabel")
|
|
}}</span>
|
|
<select
|
|
v-model="model.kind"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
>
|
|
<option v-for="k in kinds" :key="k" :value="k">{{ k }}</option>
|
|
</select>
|
|
</label>
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.protocolLabel")
|
|
}}</span>
|
|
<select
|
|
v-model="model.protocol"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
>
|
|
<option value="tcp">tcp</option>
|
|
<option value="udp">udp</option>
|
|
<option value="http">http</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.hostLabel")
|
|
}}</span>
|
|
<input
|
|
v-model="model.host"
|
|
type="text"
|
|
required
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
/>
|
|
</label>
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.portLabel")
|
|
}}</span>
|
|
<input
|
|
v-model.number="model.port"
|
|
type="number"
|
|
min="1"
|
|
max="65535"
|
|
required
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
/>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.probeTypeLabel")
|
|
}}</span>
|
|
<select
|
|
v-model="model.probeType"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
>
|
|
<option value="none">none</option>
|
|
<option value="tcp_connect">tcp_connect</option>
|
|
<option value="http_get">http_get</option>
|
|
<option value="presence_inferred">presence_inferred</option>
|
|
<option value="spire_api">spire_api</option>
|
|
<option value="source_query">source_query</option>
|
|
</select>
|
|
</label>
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.probeIntervalLabel")
|
|
}}</span>
|
|
<input
|
|
v-model.number="model.probeIntervalSec"
|
|
type="number"
|
|
min="10"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
/>
|
|
</label>
|
|
</div>
|
|
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.probeConfigLabel")
|
|
}}</span>
|
|
<textarea
|
|
v-model="model.probeConfigJson"
|
|
rows="4"
|
|
placeholder="{}"
|
|
class="font-mono text-xs rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2"
|
|
/>
|
|
<span class="text-xs text-zinc-500">{{
|
|
$t("community.servers.probeConfigHint")
|
|
}}</span>
|
|
</label>
|
|
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.joinInstructionsLabel")
|
|
}}</span>
|
|
<textarea
|
|
v-model="model.joinInstructions"
|
|
rows="3"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
/>
|
|
</label>
|
|
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.deepLinkLabel")
|
|
}}</span>
|
|
<input
|
|
v-model="model.deepLink"
|
|
type="text"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
/>
|
|
</label>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.titlePlatformLabel")
|
|
}}</span>
|
|
<select
|
|
v-model="model.titlePlatform"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
>
|
|
<option value="none">none</option>
|
|
<option value="drop">drop</option>
|
|
<option value="romm">romm</option>
|
|
</select>
|
|
</label>
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.titleIdLabel")
|
|
}}</span>
|
|
<input
|
|
v-model="model.titleId"
|
|
type="text"
|
|
:disabled="model.titlePlatform === 'none'"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm disabled:opacity-50"
|
|
/>
|
|
</label>
|
|
</div>
|
|
|
|
<div class="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.registrationLabel")
|
|
}}</span>
|
|
<select
|
|
v-model="model.registration"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
>
|
|
<option value="manual">manual</option>
|
|
<option value="auto">auto</option>
|
|
</select>
|
|
</label>
|
|
<label class="flex flex-col gap-y-1">
|
|
<span class="text-sm text-zinc-400">{{
|
|
$t("community.servers.visibilityLabel")
|
|
}}</span>
|
|
<select
|
|
v-model="model.visibility"
|
|
class="rounded-md bg-zinc-800 border-0 text-zinc-100 focus:ring-2 focus:ring-blue-600 px-3 py-2 text-sm"
|
|
>
|
|
<option value="public">public</option>
|
|
<option value="private">private</option>
|
|
</select>
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
export interface ServerFormModel {
|
|
name: string;
|
|
featured: boolean;
|
|
kind: string;
|
|
host: string;
|
|
port: number;
|
|
protocol: string;
|
|
probeType: string;
|
|
probeIntervalSec: number;
|
|
probeConfigJson: string;
|
|
joinInstructions: string;
|
|
deepLink: string;
|
|
registration: string;
|
|
visibility: string;
|
|
titlePlatform: string;
|
|
titleId: string;
|
|
}
|
|
|
|
const model = defineModel<ServerFormModel>({ required: true });
|
|
|
|
const kinds = [
|
|
"eqemu",
|
|
"wow",
|
|
"goldberg_relay",
|
|
"minecraft",
|
|
"source",
|
|
"generic",
|
|
];
|
|
</script>
|