Ajoute un ping serveur régulier comme troisième couche d'anti-triche sur Icare et la Corne
Build and deploy / deploy (push) Successful in 36s
Build and deploy / deploy (push) Successful in 36s
duration_ms/actions/merges restaient entièrement déclaratifs (calculés et envoyés par le client en une fois à la fin), donc falsifiables par un appel RPC direct. Le client envoie maintenant un ping toutes les 5s pendant la partie (ping_game_run), horodaté par le serveur, jamais par le client. submit_icarus_score/submit_melon_score corrèlent le nombre de pings et leur écart réel avec la durée annoncée (parties ≥ 15s uniquement) et signalent toute incohérence dans game_cheat_flags (missing_pings, ping_span_mismatch) — toujours en signalement silencieux, jamais de blocage, comme pour le reste de l'anti-triche. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -39,9 +39,11 @@ export type MelonRunTelemetry = {
|
||||
|
||||
export function MelonGame({
|
||||
citizens,
|
||||
onStart,
|
||||
onFinish,
|
||||
}: {
|
||||
citizens: MemberRow[];
|
||||
onStart: () => void;
|
||||
onFinish: (score: number, run: MelonRunTelemetry) => void;
|
||||
}) {
|
||||
const containerRef = useRef<HTMLDivElement | null>(null);
|
||||
@@ -67,6 +69,11 @@ export function MelonGame({
|
||||
// viser), pour voir venir deux coups à l'avance au lieu d'un seul.
|
||||
const [secondTier, setSecondTier] = useState(() => randomTier(DROP_MIN_TIER, dropMaxTier));
|
||||
|
||||
const onStartRef = useRef(onStart);
|
||||
useEffect(() => {
|
||||
onStartRef.current = onStart;
|
||||
}, [onStart]);
|
||||
|
||||
const onFinishRef = useRef(onFinish);
|
||||
useEffect(() => {
|
||||
onFinishRef.current = onFinish;
|
||||
@@ -91,6 +98,7 @@ export function MelonGame({
|
||||
const runStartedAtRef = useRef(0);
|
||||
useEffect(() => {
|
||||
runStartedAtRef.current = Date.now();
|
||||
onStartRef.current();
|
||||
}, []);
|
||||
const dropCountRef = useRef(0);
|
||||
const mergeCountRef = useRef(0);
|
||||
@@ -152,6 +160,7 @@ export function MelonGame({
|
||||
mergingBodyIdsRef.current.clear();
|
||||
dangerSinceRef.current = null;
|
||||
runStartedAtRef.current = Date.now();
|
||||
onStartRef.current();
|
||||
dropCountRef.current = 0;
|
||||
mergeCountRef.current = 0;
|
||||
lastDropAtRef.current = -Infinity;
|
||||
|
||||
Reference in New Issue
Block a user