Hectozar commited on
Commit
ba31cc8
Β·
verified Β·
1 Parent(s): 17e039e

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +39 -79
index.html CHANGED
@@ -1,3 +1,5 @@
 
 
1
  <!DOCTYPE html>
2
  <html lang="en">
3
  <head>
@@ -3821,10 +3823,6 @@ let onlineBallSpawnTimer = 0;
3821
  let onlineSearchStartTime = 0;
3822
  let onlineBotMatchTimeout = null;
3823
  let onlineBotElo = parseInt(localStorage.getItem("onlineBotElo")) || 1500;
3824
- // ONLINE BOT HARD LOCK: these are set when the bot match starts and the bot is
3825
- // forced back to these exact coordinates every simulation tick.
3826
- let onlineBotFixedX = null;
3827
- let onlineBotFixedY = null;
3828
  let onlineSimTick = 0;
3829
  let onlineMatchStamp = 0;
3830
  let onlineRound = 0, postUnsub = null, rematchSent = false, lastPostChat = 0;
@@ -3864,23 +3862,6 @@ const NET_SMOOTH = {
3864
 
3865
  // Gemeinsame Paket-Verarbeitung fΓΌr Online-Gegner UND Online TV (identisch sauber)
3866
  function feedNetPlayer(pl, st, stopMs) {
3867
- // In an Online-vs-Bot match the bot is local, not a network-controlled player.
3868
- // Ignore network position packets completely so smoothing/extrapolation cannot move it.
3869
- if (mode === "online" && onlineVsBot && pl && pl.name !== myPlayName()) {
3870
- if (onlineBotFixedX == null) onlineBotFixedX = pl.x;
3871
- if (onlineBotFixedY == null) onlineBotFixedY = pl.y;
3872
- pl.x = onlineBotFixedX;
3873
- pl.y = onlineBotFixedY;
3874
- pl.tx = onlineBotFixedX;
3875
- pl.ty = onlineBotFixedY;
3876
- pl.baseTx = onlineBotFixedX;
3877
- pl.baseTy = onlineBotFixedY;
3878
- pl.netVX = 0;
3879
- pl.netVY = 0;
3880
- pl.alive = st.alive !== false;
3881
- pl.lastPacketAt = Date.now();
3882
- return;
3883
- }
3884
  const now = Date.now();
3885
  // Jedes Match-Update (Ball, anderer Spieler ...) liefert den Spielerstand erneut.
3886
  // UnverΓ€nderte Daten sind KEIN neues Paket -> ignorieren (sonst Geschwindigkeit=0 / Zittern).
@@ -4828,22 +4809,6 @@ function makeLCG(seed) {
4828
  // ═══════════════════════════════════════════════
4829
  // ONLINE GAME
4830
  // ═══════════════════════════════════════════════
4831
- function lockOnlineBotPosition(bot) {
4832
- if (!onlineVsBot || !bot) return;
4833
- if (onlineBotFixedX == null) onlineBotFixedX = bot.x;
4834
- if (onlineBotFixedY == null) onlineBotFixedY = bot.y;
4835
- bot.x = onlineBotFixedX;
4836
- bot.y = onlineBotFixedY;
4837
- bot.tx = onlineBotFixedX;
4838
- bot.ty = onlineBotFixedY;
4839
- bot.baseTx = onlineBotFixedX;
4840
- bot.baseTy = onlineBotFixedY;
4841
- bot.netVX = 0;
4842
- bot.netVY = 0;
4843
- bot.vx = 0;
4844
- bot.vy = 0;
4845
- }
4846
-
4847
  function startOnlineGame(matchData) {
4848
  setOnlineAspect(matchData && matchData.arena);
4849
  hideAllScreensForGame();
@@ -4891,10 +4856,6 @@ function startOnlineGame(matchData) {
4891
  const mePlayer = createPlayer(meX, py, myColor, myName);
4892
  const oppPlayer = createPlayer(oppX, py, oppColor, oppName);
4893
 
4894
- // HARD LOCK the Online Bot to its spawn point.
4895
- onlineBotFixedX = onlineVsBot ? oppX : null;
4896
- onlineBotFixedY = onlineVsBot ? py : null;
4897
-
4898
  oppPlayer.tx = oppX;
4899
  oppPlayer.ty = py;
4900
  // NEW: network-smoothing bookkeeping for the opponent's reconstructed
@@ -4916,7 +4877,6 @@ function startOnlineGame(matchData) {
4916
  }
4917
 
4918
  players.push(mePlayer, oppPlayer);
4919
- lockOnlineBotPosition(oppPlayer);
4920
 
4921
  document.getElementById("onlineNameMe").textContent = dn(myName);
4922
  document.getElementById("onlineNameOpp").textContent = dn(oppName);
@@ -4979,14 +4939,12 @@ function startOnlineGame(matchData) {
4979
  const oppRole = onlineRole === "p1" ? "p2" : "p1";
4980
 
4981
  const oppState = data[oppRole + "State"];
4982
- if (oppState && !onlineVsBot) {
4983
  const op = players.find(p => p.name !== myName);
4984
  if (op) {
4985
  feedNetPlayer(op, oppState);
4986
  }
4987
  }
4988
- // Online-vs-Bot is 100% local for the bot. Firebase must NEVER be
4989
- // allowed to provide a bot position/state that can move it.
4990
 
4991
  if (!onlineIsHost && data.ballState) {
4992
  try {
@@ -5186,11 +5144,7 @@ async function handleOnlineResult(winnerName, change) {
5186
  document.getElementById("onlineHUD").style.display = "none";
5187
 
5188
  const won = winnerName === onlineAccount.name;
5189
- // Online-vs-Bot is a practice/reward match: the user's ELO NEVER drops.
5190
- // Every completed bot match awards exactly +30 ELO, regardless of who was
5191
- // hit first. Real online matches keep the normal result calculation.
5192
- const botReward = onlineVsBot ? 30 : clampEloChange(Math.round(change));
5193
- const eloChange = onlineVsBot ? 30 : botReward;
5194
  const oppName = onlineOpponent ? onlineOpponent.name : "Online Bot";
5195
  const oppUid = onlineOpponent ? onlineOpponent.uid : ONLINE_BOT_UID;
5196
 
@@ -5235,19 +5189,7 @@ async function handleOnlineResult(winnerName, change) {
5235
 
5236
  onlineAccount = sanitizeAccount(onlineAccount);
5237
 
5238
- if (onlineVsBot) {
5239
- onlineAccount.elo += 30;
5240
- onlineAccount.wins++;
5241
- onlineAccount.currentStreak++;
5242
- onlineAccount.totalEloGained += 30;
5243
- if (onlineAccount.currentStreak > onlineAccount.bestStreak) {
5244
- onlineAccount.bestStreak = onlineAccount.currentStreak;
5245
- }
5246
- if (onlineAccount.elo > onlineAccount.highestElo) {
5247
- onlineAccount.highestElo = onlineAccount.elo;
5248
- }
5249
- // Deliberately NO loss/elo subtraction path for bot matches.
5250
- } else if (won) {
5251
  onlineAccount.elo += eloChange;
5252
  onlineAccount.wins++;
5253
  onlineAccount.currentStreak++;
@@ -5286,11 +5228,32 @@ async function handleOnlineResult(winnerName, change) {
5286
  saveAccountLocal();
5287
  updateAccountBtn();
5288
  lastLeagueNote = "";
5289
- if (fbReady) await pushAccountToFirebase(); // writes ONLY players/{myUid}
5290
- if (won && fbReady) leagueRecordWin().catch(e => console.warn("league win failed", e));
5291
 
5292
- showEloAnimation(onlineVsBot ? 30 : (won ? eloChange : -eloChange));
5293
- setTimeout(() => showWinnerOverlay(winnerName, onlineVsBot ? 30 : (won ? eloChange : -eloChange)), 2600);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5294
 
5295
  // Bot stats: written to players/{ONLINE_BOT_UID}. This is the ONE
5296
  // place a client writes to a uid that isn't its own β€” acceptable
@@ -5344,7 +5307,8 @@ async function handleOnlineResult(winnerName, change) {
5344
  localStorage.setItem("onlineBotElo", onlineBotElo);
5345
 
5346
  if (fbReady) {
5347
- await dbSetBotPlayer({
 
5348
  uid: ONLINE_BOT_UID,
5349
  name: "Online Bot",
5350
  elo: onlineBotElo,
@@ -5361,7 +5325,7 @@ async function handleOnlineResult(winnerName, change) {
5361
  worstLossChange: onlineOpponent.worstLossChange ?? 0,
5362
  worstLossOpp: onlineOpponent.worstLossOpp ?? "",
5363
  updatedAt: Date.now()
5364
- });
5365
  }
5366
  }
5367
 
@@ -6289,13 +6253,9 @@ function update() {
6289
 
6290
  if (onlineVsBot) {
6291
  const bot = players.find(p => p.name !== myPlayName());
6292
- if (bot) {
6293
- // HARD LOCK: the online bot has exactly ONE legal position.
6294
- // This runs every simulation tick, so AI, Firebase, smoothing,
6295
- // velocity, or any other code cannot move the bot.
6296
- lockOnlineBotPosition(bot);
6297
  checkBotCollision(bot);
6298
- lockOnlineBotPosition(bot);
6299
  }
6300
  } else {
6301
  // CHANGED (network smoothing): replaced the fixed-rate nudge
@@ -6382,7 +6342,7 @@ function update() {
6382
  for (const p of players) {
6383
  if (!p.alive) continue;
6384
  const humanNames = ["Player","Player 1","Player 2","YOU"];
6385
- if (!humanNames.includes(p.name) && !(mode === "online" && onlineVsBot && p.name !== myPlayName())) updateAI(p, balls);
6386
  }
6387
 
6388
  for (const p of players) {
@@ -6437,7 +6397,7 @@ function checkOnlineCollision(me) {
6437
  if (onlineVsBot) {
6438
  const oppElo = onlineOpponent?.elo || 1500;
6439
  const diff = onlineAccount.elo - oppElo;
6440
- const change = onlineVsBot ? 30 : Math.max(1, Math.min(15, Math.round(5 + diff / 100)));
6441
 
6442
  handleOnlineResult(opp ? opp.name : "", change);
6443
  } else {
@@ -6460,7 +6420,7 @@ function checkBotCollision(bot) {
6460
  const oppElo = onlineOpponent?.elo || 1500;
6461
 
6462
  const diff = oppElo - onlineAccount.elo;
6463
- const change = onlineVsBot ? 30 : Math.max(1, Math.min(15, Math.round(5 + diff / 100)));
6464
 
6465
  handleOnlineResult(me.name, change);
6466
  }
@@ -6565,7 +6525,7 @@ async function reportOnlineResult(winnerName, loserName) {
6565
  const loserElo = (loserName === me.name) ? me.elo : opp.elo;
6566
 
6567
  const diff = loserElo - winnerElo;
6568
- const change = onlineVsBot ? 30 : clampEloChange(Math.max(1, Math.min(15, Math.round(5 + diff / 100))));
6569
 
6570
  // Bot-Match: es gibt keinen Match-Listener, der "done" verarbeitet -> Ergebnis direkt behandeln
6571
  // (sonst laeuft das Spiel nach der Camping-Disqualifikation einfach weiter)
 
1
+ // DARKONBALLS FREEZE FIX β€” POST-GAME FIREBASE IS NON-BLOCKING β€” 2026-10-06
2
+
3
  <!DOCTYPE html>
4
  <html lang="en">
5
  <head>
 
3823
  let onlineSearchStartTime = 0;
3824
  let onlineBotMatchTimeout = null;
3825
  let onlineBotElo = parseInt(localStorage.getItem("onlineBotElo")) || 1500;
 
 
 
 
3826
  let onlineSimTick = 0;
3827
  let onlineMatchStamp = 0;
3828
  let onlineRound = 0, postUnsub = null, rematchSent = false, lastPostChat = 0;
 
3862
 
3863
  // Gemeinsame Paket-Verarbeitung fΓΌr Online-Gegner UND Online TV (identisch sauber)
3864
  function feedNetPlayer(pl, st, stopMs) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3865
  const now = Date.now();
3866
  // Jedes Match-Update (Ball, anderer Spieler ...) liefert den Spielerstand erneut.
3867
  // UnverΓ€nderte Daten sind KEIN neues Paket -> ignorieren (sonst Geschwindigkeit=0 / Zittern).
 
4809
  // ═══════════════════════════════════════════════
4810
  // ONLINE GAME
4811
  // ═══════════════════════════════════════════════
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4812
  function startOnlineGame(matchData) {
4813
  setOnlineAspect(matchData && matchData.arena);
4814
  hideAllScreensForGame();
 
4856
  const mePlayer = createPlayer(meX, py, myColor, myName);
4857
  const oppPlayer = createPlayer(oppX, py, oppColor, oppName);
4858
 
 
 
 
 
4859
  oppPlayer.tx = oppX;
4860
  oppPlayer.ty = py;
4861
  // NEW: network-smoothing bookkeeping for the opponent's reconstructed
 
4877
  }
4878
 
4879
  players.push(mePlayer, oppPlayer);
 
4880
 
4881
  document.getElementById("onlineNameMe").textContent = dn(myName);
4882
  document.getElementById("onlineNameOpp").textContent = dn(oppName);
 
4939
  const oppRole = onlineRole === "p1" ? "p2" : "p1";
4940
 
4941
  const oppState = data[oppRole + "State"];
4942
+ if (oppState) {
4943
  const op = players.find(p => p.name !== myName);
4944
  if (op) {
4945
  feedNetPlayer(op, oppState);
4946
  }
4947
  }
 
 
4948
 
4949
  if (!onlineIsHost && data.ballState) {
4950
  try {
 
5144
  document.getElementById("onlineHUD").style.display = "none";
5145
 
5146
  const won = winnerName === onlineAccount.name;
5147
+ const eloChange = clampEloChange(Math.round(change));
 
 
 
 
5148
  const oppName = onlineOpponent ? onlineOpponent.name : "Online Bot";
5149
  const oppUid = onlineOpponent ? onlineOpponent.uid : ONLINE_BOT_UID;
5150
 
 
5189
 
5190
  onlineAccount = sanitizeAccount(onlineAccount);
5191
 
5192
+ if (won) {
 
 
 
 
 
 
 
 
 
 
 
 
5193
  onlineAccount.elo += eloChange;
5194
  onlineAccount.wins++;
5195
  onlineAccount.currentStreak++;
 
5228
  saveAccountLocal();
5229
  updateAccountBtn();
5230
  lastLeagueNote = "";
 
 
5231
 
5232
+ // IMPORTANT: never wait for Firebase before showing the result screen.
5233
+ // A slow/hung Firebase connection used to make the completed game look frozen.
5234
+ // Persist everything in the background instead.
5235
+ if (fbReady) {
5236
+ try {
5237
+ Promise.resolve(pushAccountToFirebase()).catch(e =>
5238
+ console.warn("post-match account save failed:", e)
5239
+ );
5240
+ } catch (e) {
5241
+ console.warn("post-match account save failed:", e);
5242
+ }
5243
+ }
5244
+ if (won && fbReady) {
5245
+ try {
5246
+ Promise.resolve(leagueRecordWin()).catch(e =>
5247
+ console.warn("league win failed:", e)
5248
+ );
5249
+ } catch (e) {
5250
+ console.warn("league win failed:", e);
5251
+ }
5252
+ }
5253
+
5254
+ // Show the result immediately. Do not make the UI wait on network operations.
5255
+ showEloAnimation(won ? eloChange : -eloChange);
5256
+ setTimeout(() => showWinnerOverlay(winnerName, won ? eloChange : -eloChange), 500);
5257
 
5258
  // Bot stats: written to players/{ONLINE_BOT_UID}. This is the ONE
5259
  // place a client writes to a uid that isn't its own β€” acceptable
 
5307
  localStorage.setItem("onlineBotElo", onlineBotElo);
5308
 
5309
  if (fbReady) {
5310
+ // Fire-and-forget: bot-stat Firebase writes must NEVER block the result screen.
5311
+ Promise.resolve().then(() => dbSetBotPlayer({
5312
  uid: ONLINE_BOT_UID,
5313
  name: "Online Bot",
5314
  elo: onlineBotElo,
 
5325
  worstLossChange: onlineOpponent.worstLossChange ?? 0,
5326
  worstLossOpp: onlineOpponent.worstLossOpp ?? "",
5327
  updatedAt: Date.now()
5328
+ })).catch(e => console.warn("bot stat save failed:", e));
5329
  }
5330
  }
5331
 
 
6253
 
6254
  if (onlineVsBot) {
6255
  const bot = players.find(p => p.name !== myPlayName());
6256
+ if (bot && bot.alive) {
6257
+ updateAI(bot, balls);
 
 
 
6258
  checkBotCollision(bot);
 
6259
  }
6260
  } else {
6261
  // CHANGED (network smoothing): replaced the fixed-rate nudge
 
6342
  for (const p of players) {
6343
  if (!p.alive) continue;
6344
  const humanNames = ["Player","Player 1","Player 2","YOU"];
6345
+ if (!humanNames.includes(p.name)) updateAI(p, balls);
6346
  }
6347
 
6348
  for (const p of players) {
 
6397
  if (onlineVsBot) {
6398
  const oppElo = onlineOpponent?.elo || 1500;
6399
  const diff = onlineAccount.elo - oppElo;
6400
+ const change = Math.max(1, Math.min(15, Math.round(5 + diff / 100)));
6401
 
6402
  handleOnlineResult(opp ? opp.name : "", change);
6403
  } else {
 
6420
  const oppElo = onlineOpponent?.elo || 1500;
6421
 
6422
  const diff = oppElo - onlineAccount.elo;
6423
+ const change = Math.max(1, Math.min(15, Math.round(5 + diff / 100)));
6424
 
6425
  handleOnlineResult(me.name, change);
6426
  }
 
6525
  const loserElo = (loserName === me.name) ? me.elo : opp.elo;
6526
 
6527
  const diff = loserElo - winnerElo;
6528
+ const change = clampEloChange(Math.max(1, Math.min(15, Math.round(5 + diff / 100))));
6529
 
6530
  // Bot-Match: es gibt keinen Match-Listener, der "done" verarbeitet -> Ergebnis direkt behandeln
6531
  // (sonst laeuft das Spiel nach der Camping-Disqualifikation einfach weiter)