Ники, общий рейтинг (топ-10 по картам), таблица Tab, сдача в гонке, таймер Parkour

- Ники: профиль user://profile.cfg (client_id + ник), панель при первом запуске и по N;
  Net.nick_of(id); ники над призраками, в HUD/итогах гонки и таблицах
- Рейтинг на сервере: лучшее время каждого игрока по картам race/parkour/metro, топ-10,
  user://leaderboard.json (атомарная запись, лимиты, проверка карты/комнаты/времени)
- Таблица лидеров по Tab, доски топ-3 над порталами в хабе, итоги гонки с общим рейтингом
- Гонка: сдача (G, удержание 1,5 с), RACE_GIVEUP; Parkour: таймер, финиш на вершине, R — перезапуск
- Новые RPC (submit_profile, recv_nick, submit_record, recv_record_result, request_leaderboard,
  recv_leaderboard): клиент и сервер выкладываются вместе
- Тесты: nicks_lb_test, race_giveup_test, parkour_run_test, nick_ui_test, ui_tour; README обновлён

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WxZo3ekR5m1af437Qzqwc1
This commit is contained in:
2026-10-29 12:09:33 +05:00
co-authored by Claude Sonnet 5.5
parent d38152ea97
commit 666bebfb60
31 changed files with 2014 additions and 44 deletions
+4 -4
View File
@@ -238,8 +238,8 @@ func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("ui_cancel"):
Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
if event is InputEventMouseButton and event.button_index == MOUSE_BUTTON_LEFT and not Net.input_blocked:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED # (панель ника открыта — мышь нужна на экране)
if is_dead:
return
@@ -250,7 +250,7 @@ func _unhandled_input(event: InputEvent) -> void:
head.rotate_x(-event.relative.y * MOUSE_SENSITIVITY * zoom_factor)
head.rotation.x = clamp(head.rotation.x, deg_to_rad(-80), deg_to_rad(80))
if input_frozen:
if input_frozen or Net.input_blocked:
return
if event.is_action_pressed("crouch"):
@@ -279,7 +279,7 @@ func _physics_process(delta: float) -> void:
_process_death(delta)
return
if input_frozen:
if input_frozen or Net.input_blocked: # input_blocked — открыта панель ника (core/overlay.gd), не зависит от гонки
# Стоим на месте (только падаем, если под ногами пусто)
velocity.x = 0.0
velocity.z = 0.0