Captures the uncommitted parallel-development work (increments 46-49) on the
40250 classic client port, folded into docs/CLIENT-GAP.md + CLIENT-GAP-FIX.md.
Increment 49 (W0 interface-freeze batch, Phase 1 prerequisite) lands the
cross-workflow shared-file scaffolding so the 4 Phase 1 workflows can run in
isolated worktrees without contention:
- entity_store.{h,cpp}: Entity gains empire/affect_flags/owner_vid/state_flags;
new mut_spawn_full() (single-shot two-packet merge, §2.3), mut_ownership()
(§2.5), mut_map_bgm() + take_bgm_dirty()/bgm_name()/bgm_volume() (§9.1),
drain_dirty() (§2.1/§2.5 bare-field-update queue); mut_char_info() now stores
empire; reset_for_map_change() clears m_dirty.
- m2_client.cpp: new bgm_changed(name, volume) signal; classic + m2dev pump
loops drain drain_dirty() -> entity_info and take_bgm_dirty() -> bgm_changed;
entity_dict() exposes the 4 new keys.
- classic/classic_parser.{h,cpp}: GC_MAIN_CHARACTER3_BGM /
GC_MAIN_CHARACTER4_BGM_VOL route bgm_name/bgm_volume to mut_map_bgm() (was
discarded); new m_pending_actor staging map (W1 fills §2.2 merge logic).
- project/bgm_director.gd (new) + game_scene.gd: BGM consumption split out of
net_world.gd so W2/W4 don't collide; §8.6/§4.8 keybind convergence (digits
1-4 -> quickslots 0-3, F1-F4 -> quickslots 4-7, Ctrl+1..9 -> _emote()).
Tests: cmake --build build clean; ctest 16/16; 15 GDScript regressions green
(netbridge, gamescene, netplay, p9, p10, p2b, p8, system_menu_ui, skill,
combat_fx, skill_fx, player_motion, char_status_ui, chat, inventory), no skips.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014yvAPqPivoY7vmBbzgqK4W
78 lines
2.9 KiB
GDScript
78 lines
2.9 KiB
GDScript
# WorldTime (P9) —— 昼夜循环:GC_TIME 的服务器时钟 → 太阳角度 + 光色 + 环境色。
|
|
#
|
|
# var wt := preload("res://world/world_time.gd").new()
|
|
# add_child(wt)
|
|
# wt.setup(m2client, sun_light, environment) # environment 可空
|
|
#
|
|
# GC_TIME 给的是 unix 秒。本地按 delta 累加,得到「日内秒」(0..86400)。
|
|
# 06:00 日出、12:00 正午、18:00 日落、0:00 午夜。太阳 pitch 随之走。
|
|
extends Node
|
|
|
|
const DAY := 86400.0
|
|
const CYCLE_SCALE := 1.0 # >1 加速昼夜(调试用)
|
|
|
|
var client: Node
|
|
var sun: DirectionalLight3D
|
|
var env: Environment
|
|
var _epoch := 0.0 # 最近一次 GC_TIME 的服务器 unix 秒
|
|
var _since := 0.0 # 收到后本地经过的秒
|
|
var _have_time := false
|
|
|
|
func setup(m2client: Node, sun_light: DirectionalLight3D, environment: Environment = null) -> void:
|
|
client = m2client
|
|
sun = sun_light
|
|
env = environment
|
|
if client and client.has_signal("time_changed"):
|
|
client.time_changed.connect(_on_time)
|
|
if client and client.has_method("get_server_time"):
|
|
var t: int = client.get_server_time()
|
|
if t > 0:
|
|
_on_time(t)
|
|
|
|
func set_lighting(sun_light: DirectionalLight3D, environment: Environment = null) -> void:
|
|
sun = sun_light
|
|
env = environment
|
|
|
|
func _on_time(server_epoch: int) -> void:
|
|
_epoch = float(server_epoch)
|
|
_since = 0.0
|
|
_have_time = true
|
|
|
|
# 当前日内秒(0..86400)。没有 GC_TIME 时固定用「正午」——不要跟着玩家的系统钟
|
|
# 走到半夜把整个场景变黑(那不是 m2dev-client-main 的行为)。
|
|
const DEFAULT_NOON := 43200.0
|
|
|
|
func seconds_of_day() -> float:
|
|
if not _have_time:
|
|
return DEFAULT_NOON
|
|
return fmod((_epoch + _since) * CYCLE_SCALE, DAY)
|
|
|
|
# 0 = 午夜, 0.25 = 日出, 0.5 = 正午, 0.75 = 日落
|
|
func day_fraction() -> float:
|
|
return seconds_of_day() / DAY
|
|
|
|
func _process(delta: float) -> void:
|
|
_since += delta
|
|
if sun == null:
|
|
return
|
|
var f := day_fraction()
|
|
# 太阳高度角:正午(0.5)最高 ~ -85°(朝下),午夜最低 ~ +85°(朝上,被地平线挡)
|
|
var elevation := sin((f - 0.25) * TAU) * 80.0 # -80..80
|
|
var azimuth := lerpf(40.0, 220.0, f)
|
|
sun.rotation = Vector3(deg_to_rad(-elevation), deg_to_rad(azimuth), 0.0)
|
|
# 光照强度 & 颜色:白天暖白,黄昏偏橙,夜里近黑冷蓝
|
|
var daylight := clampf(sin((f - 0.25) * TAU) * 1.4 + 0.3, 0.0, 1.0)
|
|
sun.light_energy = lerpf(0.03, 1.15, daylight)
|
|
var warm := Color(1.0, 0.55, 0.30)
|
|
var noon := Color(1.0, 0.97, 0.90)
|
|
var night := Color(0.35, 0.42, 0.65)
|
|
if daylight < 0.35:
|
|
sun.light_color = night.lerp(warm, daylight / 0.35)
|
|
else:
|
|
sun.light_color = warm.lerp(noon, (daylight - 0.35) / 0.65)
|
|
if env:
|
|
env.ambient_light_energy = lerpf(0.12, 0.6, daylight)
|
|
env.ambient_light_color = Color(0.16, 0.19, 0.30).lerp(Color(0.5, 0.55, 0.62), daylight)
|
|
if env.background_mode == Environment.BG_COLOR:
|
|
env.background_color = Color(0.03, 0.04, 0.09).lerp(Color(0.55, 0.62, 0.72), daylight)
|