// Стройка и офлайн (решения 04.11): стройка, которая закончилась, пока игра была закрыта, вступает в силу // в тот момент офлайн-расчёта, когда время дошло до её конца. Тогда добыча здания (и его новый уровень) // считается ровно с момента завершения, а не с начала офлайна и не с момента входа в игру. // // Как: модуль Населения на каждом шаге расчёта сообщает, до какого момента дошёл (GameTimeSimulatedEvent). // Здесь завершаются стройки с концом не позже этого момента, и город сразу пересчитывается (CitySync) -- // следующий шаг добычи идёт уже с новым зданием. Пока расчёт не дошёл до конца стройки, BuildTimer сам её не // завершает (BuildTimer.MayComplete). Шаг расчёта -- 10 минут, поэтому добыча начинается не раньше конца // стройки и не позже чем через 10 минут после него: лишнего не начисляется никогда. public static class ConstructionClock { // До какого момента (мс) расчёт добычи уже дошёл. 0 -- ещё ни разу не считал (сразу после запуска) public static long SimulatedUntilMs { get; private set; } static bool subscribed; public static void Init() { SimulatedUntilMs = 0; BuildTimer.MayComplete = endMs => endMs <= SimulatedUntilMs; if (subscribed) return; subscribed = true; EventBus.Subscribe(OnSimulated); } static void OnSimulated(GameTimeSimulatedEvent e) { long ms = e.UnixNow * 1000; if (ms > SimulatedUntilMs) SimulatedUntilMs = ms; // время расчёта только растёт bool any = false; foreach (var timer in BuildTimer.All.ToArray()) { if (timer == null || timer.endMs > SimulatedUntilMs) continue; timer.Complete(); // уровень только растёт, второй раз не завершается any = true; } if (any && CitySync.Instance != null) CitySync.Instance.SyncNow(); } }