Servername aus dem Spiel und ein Schloss fuer Passwort oder Whitelist
Der Name im Panel ist der, den DU vergibst — wie der Server sich im Spiel nennt, stand nirgends. Steht jetzt darunter, aber nur wenn es etwas anderes ist als der eingetragene Name; sonst haette dieselbe Zeile zweimal dagestanden. Beim Schloss war die Frage, wie viel die Abfrage ueberhaupt hergibt. Nachgesehen statt geraten: 31 der 358 gamedig-Protokolle melden ein Passwort. valve gehoert dazu, deckt also CS2, Rust, ARK, Squad, 7DTD, Zomboid, Gmod und DayZ ab. Minecraft nicht, Farming Simulator auch nicht — im LS-XML kommt das Wort Passwort kein einziges Mal vor. Und eine Whitelist meldet grundsaetzlich kein Spiel, die steht in einer Datei auf dem Server. Also beides: automatisch, wo es geht, und eine Einstellung, die es schlaegt. Wer "Whitelist" eintraegt, bekommt sie angezeigt, auch wenn der Server schweigt. Wichtig dabei ist der dritte Zustand. "Sagt nichts" ist nicht "offen" — deshalb `null` und kein `false`. Ein Schloss, das bei jedem schweigenden Server fehlt, waere eine Aussage, die wir nicht belegen koennen; umgekehrt waere ein Schloss ohne Grundlage eine Luege. Bei unbekannt steht schlicht nichts da. Geprueft: Einstellung schlaegt Messung in allen vier Faellen, automatisch mit true/false/null, fehlender Server, unbekannter Wert faellt auf automatisch zurueck statt zu sperren, Schloss im Embed-Titel nur wenn belegt, Spielname nur bei echtem Unterschied (auch mit Leerzeichen drumherum). Panel und /server-Seite im laufenden Frontend angesehen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { apiGet } from '../api.js';
|
||||
import { SkeletonCards } from '../components/Skeleton.jsx';
|
||||
import { IconGame, IconMapPin, IconClock, IconCheck, IconTeam, IconPackage, IconZap, IconDownload, IconArchive } from '../icons.jsx';
|
||||
import { IconGame, IconMapPin, IconClock, IconCheck, IconTeam, IconPackage, IconZap, IconDownload, IconArchive, IconLock } from '../icons.jsx';
|
||||
import { useT, useFmt } from '../i18n.jsx';
|
||||
import UptimeTrack from '../components/UptimeTrack.jsx';
|
||||
|
||||
@@ -100,7 +100,15 @@ function ServerCard({ s }) {
|
||||
? <img className="srv-logo" src={s.image_url} alt="" loading="lazy" />
|
||||
: <span className="srv-logo srv-logo-emoji">{s.icon}</span>}
|
||||
<div className="srv-title">
|
||||
<span className="srv-name">{s.name}</span>
|
||||
<span className="srv-name">
|
||||
{s.name}
|
||||
{s.zugang?.zu && (
|
||||
<IconLock size={15} className="srv-schloss" aria-label={s.zugang.grund ?? ''} />
|
||||
)}
|
||||
</span>
|
||||
{/* Wie der Server sich im Spiel nennt — nur wenn es etwas
|
||||
anderes ist als der Name hier, sonst doppelt es sich. */}
|
||||
{s.spielname && <span className="srv-spielname">{s.spielname}</span>}
|
||||
<span className={`srv-status ${s.online ? 'on' : s.online === false ? 'off' : ''}`}>
|
||||
{s.online === null
|
||||
? <><IconClock size={13} /> {t('server.waiting')}</>
|
||||
@@ -126,7 +134,7 @@ function ServerCard({ s }) {
|
||||
)}
|
||||
|
||||
{/* Was der Server über sich verrät — nur, was auch da ist */}
|
||||
{s.online && (s.map || s.ping != null || s.version) && (
|
||||
{s.online && (s.map || s.ping != null || s.version || s.zugang?.grund) && (
|
||||
<div className="srv-chips">
|
||||
{s.map && <span className="srv-chip"><IconMapPin size={12} /> {s.map}</span>}
|
||||
{s.version && <span className="srv-chip"><IconPackage size={12} /> {s.version}</span>}
|
||||
@@ -134,6 +142,7 @@ function ServerCard({ s }) {
|
||||
sähen die beiden Chips wie zusammengehörig aus. */}
|
||||
{s.mods > 0 && <span className="srv-chip"><IconArchive size={12} /> {t('server.mods', s.mods)}</span>}
|
||||
{s.ping != null && <span className="srv-chip"><IconZap size={12} /> {s.ping} ms</span>}
|
||||
{s.zugang?.grund && <span className="srv-chip zu"><IconLock size={12} /> {s.zugang.grund}</span>}
|
||||
</div>
|
||||
)}
|
||||
|
||||
|
||||
@@ -406,7 +406,7 @@ export default function Settings({ me }) {
|
||||
const [triggers, setTriggers] = useState([]);
|
||||
const [triggerDraft, setTriggerDraft] = useState({ keyword: '', reply: '' });
|
||||
// Game-Server — die Spielliste kommt aus gamedig (siehe /api/gamedig-games)
|
||||
const emptyServer = { id: null, name: '', type: 'fivem', query_url: '', address: '', host: '', port: '', connect_url: '', image_url: '', token: '', mods_url: '', links: [] };
|
||||
const emptyServer = { id: null, name: '', type: 'fivem', query_url: '', address: '', host: '', port: '', connect_url: '', image_url: '', token: '', mods_url: '', links: [], zugang: 'auto' };
|
||||
const [servers, setServers] = useState([]);
|
||||
const [games, setGames] = useState([]);
|
||||
const [serverDraft, setServerDraft] = useState(emptyServer);
|
||||
@@ -3354,7 +3354,7 @@ export default function Settings({ me }) {
|
||||
id: s.id, name: s.name, type: s.type, query_url: s.query_url ?? '',
|
||||
address: s.address ?? '', host: s.host ?? '', port: s.port ?? '', connect_url: s.connect_url ?? '',
|
||||
image_url: s.image_url ?? '', token: s.token ?? '', mods_url: s.mods_url ?? '',
|
||||
links: s.links ?? [],
|
||||
links: s.links ?? [], zugang: s.zugang ?? 'auto',
|
||||
})}>Bearbeiten</button>
|
||||
<button className="card-delete" title="Server + Embed entfernen" onClick={() => removeServer(s.id)}>✕</button>
|
||||
</div>
|
||||
@@ -3415,7 +3415,23 @@ export default function Settings({ me }) {
|
||||
</div>
|
||||
)}
|
||||
<div className="field">
|
||||
<label>Connect-Link + Anzeige-Adresse <span className="field-hint">https wird zum Knopf; steam:// / fivem:// stehen als Codeblock zum Kopieren. Adresse ebenfalls als Copy-Paste-Block</span></label>
|
||||
<label>
|
||||
Zugang <span className="field-hint">
|
||||
zeigt ein 🔒 im Embed und auf der /server-Seite. „Automatisch" nimmt, was die
|
||||
Abfrage sagt — das können aber nur wenige Spiele, und eine Whitelist meldet nie jemand.
|
||||
</span>
|
||||
</label>
|
||||
<select
|
||||
value={serverDraft.zugang}
|
||||
onChange={(e) => setServerDraft({ ...serverDraft, zugang: e.target.value })}
|
||||
>
|
||||
<option value="auto">Automatisch — was der Server meldet</option>
|
||||
<option value="offen">Offen für alle</option>
|
||||
<option value="passwort">🔒 Passwort</option>
|
||||
<option value="whitelist">🔒 Whitelist</option>
|
||||
</select>
|
||||
|
||||
<label style={{ marginTop: '.9rem' }}>Connect-Link + Anzeige-Adresse <span className="field-hint">https wird zum Knopf; steam:// / fivem:// stehen als Codeblock zum Kopieren. Adresse ebenfalls als Copy-Paste-Block</span></label>
|
||||
<div className="field-row">
|
||||
<input type="text" placeholder="https://cfx.re/join/abc123" value={serverDraft.connect_url} onChange={(e) => setServerDraft({ ...serverDraft, connect_url: e.target.value })} />
|
||||
<input type="text" placeholder="connect play.d4rkst3r.de" value={serverDraft.address} onChange={(e) => setServerDraft({ ...serverDraft, address: e.target.value })} />
|
||||
|
||||
Reference in New Issue
Block a user