先修复一下,错误的场景 删除不必要的钓场资产 修复into场景 update:更新meta文件,修复报错 update:修复资源 修复第一章节建造 修复建造第三章 update:删除多余内容 update:更新README.md update:还原图标 update:更新README update:更新配置
227 lines
5.1 KiB
C#
227 lines
5.1 KiB
C#
using System;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using asap.core;
|
|
using UniRx;
|
|
using UnityEngine;
|
|
|
|
public class HeartBeat
|
|
{
|
|
[Inject]
|
|
public IStageService stageService {get; set;}
|
|
|
|
[Inject]
|
|
public IConfig config {get; set;}
|
|
|
|
private CompositeDisposable disposables;
|
|
private CancellationTokenSource tokenSource;
|
|
private bool initialized;
|
|
private bool isPaused;
|
|
private bool hasPauseSnapshot;
|
|
private DateTime pauseTimeUtc;
|
|
private TimeSpan remainingDelayWhenPaused;
|
|
private DateTime nextHeartbeatTimeUtc;
|
|
|
|
public void Init()
|
|
{
|
|
if (initialized)
|
|
{
|
|
return;
|
|
}
|
|
|
|
initialized = true;
|
|
isPaused = true;
|
|
hasPauseSnapshot = false;
|
|
remainingDelayWhenPaused = TimeSpan.Zero;
|
|
disposables = new CompositeDisposable();
|
|
|
|
var stageLoadDisposable = GContext.OnEvent<StageLoadEvent>()
|
|
.Where(e => e.state == EStageLoadState.Loaded && e.stageId == "FishingStage")
|
|
.Take(1)
|
|
.Subscribe(OnFishingStageLoad);
|
|
disposables.Add(stageLoadDisposable);
|
|
|
|
var pauseDisposable = Observable.EveryApplicationPause()
|
|
.Subscribe(OnApplicationPauseChanged);
|
|
disposables.Add(pauseDisposable);
|
|
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
if (!initialized)
|
|
{
|
|
return;
|
|
}
|
|
|
|
initialized = false;
|
|
isPaused = true;
|
|
hasPauseSnapshot = false;
|
|
remainingDelayWhenPaused = TimeSpan.Zero;
|
|
disposables.Dispose();
|
|
disposables = null;
|
|
StopHeartBeatLoop();
|
|
}
|
|
|
|
private void OnApplicationPauseChanged(bool paused)
|
|
{
|
|
if (paused)
|
|
{
|
|
PauseHeartBeat();
|
|
}
|
|
else
|
|
{
|
|
ResumeHeartBeat();
|
|
}
|
|
}
|
|
|
|
private void OnFishingStageLoad(StageLoadEvent @event)
|
|
{
|
|
if (tokenSource != null || stageService.GetStage("FishingStage") == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
StartHeartBeatLoop(GetInterval());
|
|
}
|
|
|
|
private void PauseHeartBeat()
|
|
{
|
|
if (isPaused)
|
|
{
|
|
return;
|
|
}
|
|
|
|
isPaused = true;
|
|
pauseTimeUtc = DateTime.UtcNow;
|
|
hasPauseSnapshot = true;
|
|
|
|
if (nextHeartbeatTimeUtc > pauseTimeUtc)
|
|
{
|
|
remainingDelayWhenPaused = nextHeartbeatTimeUtc - pauseTimeUtc;
|
|
}
|
|
else
|
|
{
|
|
remainingDelayWhenPaused = TimeSpan.Zero;
|
|
}
|
|
|
|
StopHeartBeatLoop();
|
|
}
|
|
|
|
private void ResumeHeartBeat()
|
|
{
|
|
TimeSpan delay;
|
|
bool sendImmediately = false;
|
|
|
|
if (!isPaused)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var interval = GetInterval();
|
|
if (!hasPauseSnapshot)
|
|
{
|
|
delay = interval;
|
|
}
|
|
else
|
|
{
|
|
var bgElapsed = DateTime.UtcNow - pauseTimeUtc;
|
|
var remainingDelay = remainingDelayWhenPaused;
|
|
if (remainingDelay <= TimeSpan.Zero)
|
|
{
|
|
remainingDelay = interval;
|
|
}
|
|
|
|
if (bgElapsed >= remainingDelay)
|
|
{
|
|
sendImmediately = true;
|
|
delay = interval;
|
|
}
|
|
else
|
|
{
|
|
delay = remainingDelay - bgElapsed;
|
|
}
|
|
}
|
|
|
|
if (stageService.GetStage("FishingStage") == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (sendImmediately)
|
|
{
|
|
SendHeartBeat();
|
|
}
|
|
|
|
StartHeartBeatLoop(delay);
|
|
}
|
|
|
|
private void StartHeartBeatLoop(TimeSpan firstDelay)
|
|
{
|
|
if (tokenSource != null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
tokenSource = new CancellationTokenSource();
|
|
isPaused = false;
|
|
nextHeartbeatTimeUtc = DateTime.UtcNow + firstDelay;
|
|
StartHeartBeat(tokenSource.Token, firstDelay);
|
|
}
|
|
|
|
private void StopHeartBeatLoop()
|
|
{
|
|
if (tokenSource != null)
|
|
{
|
|
tokenSource.Cancel();
|
|
tokenSource.Dispose();
|
|
tokenSource = null;
|
|
}
|
|
}
|
|
|
|
private async void StartHeartBeat(CancellationToken token, TimeSpan firstDelay)
|
|
{
|
|
try
|
|
{
|
|
var delay = firstDelay;
|
|
while (!token.IsCancellationRequested)
|
|
{
|
|
if (delay > TimeSpan.Zero)
|
|
{
|
|
await Task.Delay(delay, token);
|
|
}
|
|
|
|
if (token.IsCancellationRequested || isPaused)
|
|
{
|
|
return;
|
|
}
|
|
|
|
SendHeartBeat();
|
|
delay = GetInterval();
|
|
}
|
|
}
|
|
catch (OperationCanceledException)
|
|
{
|
|
}
|
|
catch (Exception)
|
|
{
|
|
}
|
|
}
|
|
|
|
private void SendHeartBeat()
|
|
{
|
|
using (var e = GEvent.TackEvent("HeartBeat", gaSend: false))
|
|
{
|
|
e.AddContent("FPS", game.RootCtx.fps);
|
|
}
|
|
|
|
nextHeartbeatTimeUtc = DateTime.UtcNow + GetInterval();
|
|
}
|
|
|
|
private TimeSpan GetInterval()
|
|
{
|
|
var intervalSeconds = Mathf.Max(1, (int)config.GetFloat("HeartBeat", 300));
|
|
return TimeSpan.FromSeconds(intervalSeconds);
|
|
}
|
|
}
|