feat: ✨ Add the progress TimeBasedProgressAtVariableSpeed
dev
| @@ -327,7 +327,7 @@ namespace GameClass.GameObj | |||
| case PlayerStateType.OpeningTheDoorway: | |||
| if (value == PlayerStateType.Rescued) return -1; | |||
| Doorway doorway = (Doorway)lastObj!; | |||
| doorway.StopOpenning(); | |||
| doorway.ProgressOfDoorway.TryStop(); | |||
| return ChangePlayerState(runningState, value, gameObj); | |||
| case PlayerStateType.OpeningTheDoor: | |||
| if (value == PlayerStateType.Rescued) return -1; | |||
| @@ -17,70 +17,18 @@ namespace GameClass.GameObj | |||
| public override ShapeType Shape => ShapeType.Square; | |||
| public override bool IgnoreCollideExecutor(IGameObj targetObj) | |||
| { | |||
| if (!IsOpen()) return false; | |||
| if (!ProgressOfDoorway.IsFinished()) return false; | |||
| if (targetObj.Type != GameObjType.Character) | |||
| return true; // 非玩家不碰撞 | |||
| return false; | |||
| } | |||
| public AtomicBool PowerSupply { get; } = new(false); | |||
| private long openStartTime = 0; | |||
| public long OpenStartTime | |||
| { | |||
| get | |||
| { | |||
| lock (gameObjLock) | |||
| return openStartTime; | |||
| } | |||
| } | |||
| public TimeBasedProgressAtVariableSpeed ProgressOfDoorway { get; } = new(GameData.degreeOfOpenedDoorway, 1); | |||
| public bool TryToOpen() | |||
| { | |||
| if (!PowerSupply) return false; | |||
| lock (gameObjLock) | |||
| { | |||
| if (openStartTime > 0) return false; | |||
| openStartTime = Environment.TickCount64; | |||
| return true; | |||
| } | |||
| return ProgressOfDoorway.Start(); | |||
| } | |||
| public bool StopOpenning() | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| if (Environment.TickCount64 - openStartTime + openDegree >= GameData.degreeOfOpenedDoorway) | |||
| { | |||
| openDegree = GameData.degreeOfOpenedDoorway; | |||
| return true; | |||
| } | |||
| else | |||
| { | |||
| openDegree = (int)(Environment.TickCount64 - openStartTime) + openDegree; | |||
| openStartTime = 0; | |||
| return false; | |||
| } | |||
| } | |||
| } | |||
| public void FinishOpenning() | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| openDegree = GameData.degreeOfOpenedDoorway; | |||
| } | |||
| } | |||
| private int openDegree = 0; | |||
| public int OpenDegree | |||
| { | |||
| get | |||
| { | |||
| lock (gameObjLock) | |||
| return openDegree; | |||
| } | |||
| } | |||
| public bool IsOpen() => (OpenDegree == GameData.degreeOfOpenedDoorway); | |||
| } | |||
| } | |||
| @@ -24,7 +24,7 @@ namespace GameClass.GameObj | |||
| GameObjLockDict[GameObjType.EmergencyExit].EnterReadLock(); | |||
| try | |||
| { | |||
| Random r = new Random(Environment.TickCount); | |||
| Random r = new(Environment.TickCount); | |||
| EmergencyExit emergencyExit = (EmergencyExit)(GameObjDict[GameObjType.EmergencyExit][r.Next(0, GameObjDict[GameObjType.EmergencyExit].Count)]); | |||
| emergencyExit.CanOpen.SetReturnOri(true); | |||
| Preparation.Utility.Debugger.Output(emergencyExit, emergencyExit.Position.ToString()); | |||
| @@ -2,6 +2,7 @@ | |||
| using System.Threading; | |||
| using GameClass.GameObj; | |||
| using GameEngine; | |||
| using Preparation.Interface; | |||
| using Preparation.Utility; | |||
| using Timothy.FrameRateTask; | |||
| @@ -148,11 +149,11 @@ namespace Gaming | |||
| player.ThreadNum.Release(); | |||
| return; | |||
| } | |||
| Thread.Sleep(GameData.degreeOfOpenedDoorway - doorwayToOpen.OpenDegree); | |||
| Thread.Sleep(GameData.degreeOfOpenedDoorway - (int)doorwayToOpen.ProgressOfDoorway.GetProgressNow()); | |||
| if (player.ResetPlayerState(stateNum)) | |||
| { | |||
| doorwayToOpen.FinishOpenning(); | |||
| doorwayToOpen.ProgressOfDoorway.Finish(); | |||
| player.ThreadNum.Release(); | |||
| } | |||
| } | |||
| @@ -168,7 +169,7 @@ namespace Gaming | |||
| return false; | |||
| Doorway? doorwayForEscape = (Doorway?)gameMap.OneForInteract(player.Position, GameObjType.Doorway); | |||
| if (doorwayForEscape != null && doorwayForEscape.IsOpen()) | |||
| if (doorwayForEscape != null && doorwayForEscape.ProgressOfDoorway.IsProgressing()) | |||
| { | |||
| if (!player.TryToRemoveFromGame(PlayerStateType.Escaped)) return false; | |||
| player.AddScore(GameData.StudentScoreEscape); | |||
| @@ -4,9 +4,6 @@ namespace Preparation.Interface | |||
| { | |||
| public interface IDoorway : IGameObj | |||
| { | |||
| public long OpenStartTime { get; } | |||
| public int OpenDegree { get; } | |||
| public bool StopOpenning(); | |||
| public bool TryToOpen(); | |||
| public TimeBasedProgressAtVariableSpeed ProgressOfDoorway { get; } | |||
| } | |||
| } | |||
| @@ -1,4 +1,5 @@ | |||
| using System; | |||
| using Google.Protobuf.WellKnownTypes; | |||
| using System; | |||
| using System.Threading; | |||
| namespace Preparation.Utility | |||
| @@ -10,7 +11,7 @@ namespace Preparation.Utility | |||
| public class AtomicInt : Atomic | |||
| { | |||
| private int v; | |||
| protected int v; | |||
| public AtomicInt(int x) | |||
| { | |||
| v = x; | |||
| @@ -19,33 +20,239 @@ namespace Preparation.Utility | |||
| public int Get() => Interlocked.CompareExchange(ref v, -1, -1); | |||
| public static implicit operator int(AtomicInt aint) => Interlocked.CompareExchange(ref aint.v, -1, -1); | |||
| /// <returns>返回操作前的值</returns> | |||
| public int SetReturnOri(int value) => Interlocked.Exchange(ref v, value); | |||
| public int Add(int x) => Interlocked.Add(ref v, x); | |||
| public int Sub(int x) => Interlocked.Add(ref v, -x); | |||
| public int Inc() => Interlocked.Increment(ref v); | |||
| public int Dec() => Interlocked.Decrement(ref v); | |||
| public virtual int SetReturnOri(int value) => Interlocked.Exchange(ref v, value); | |||
| public virtual int Add(int x) => Interlocked.Add(ref v, x); | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public virtual int AddPositive(int x) => Interlocked.Add(ref v, x); | |||
| public virtual int Sub(int x) => Interlocked.Add(ref v, -x); | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public virtual int SubPositive(int x) => Interlocked.Add(ref v, -x); | |||
| public virtual int Inc() => Interlocked.Increment(ref v); | |||
| public virtual int Dec() => Interlocked.Decrement(ref v); | |||
| /// <returns>返回操作前的值</returns> | |||
| public int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); | |||
| public virtual int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); | |||
| } | |||
| /// <summary> | |||
| /// 参数要求倍率speed(默认1)以及AtomicInt类的Score, | |||
| /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed取整。 | |||
| /// 注意:AtomicIntOnlyAddScore本身为AtomicInt,提供的Score可能构成环而死锁。 | |||
| /// </summary> | |||
| public class AtomicIntOnlyAddScore : AtomicInt | |||
| { | |||
| public AtomicInt Score { get; set; } | |||
| public AtomicDouble speed; | |||
| public AtomicIntOnlyAddScore(int x, AtomicInt Score, double speed = 1.0) : base(x) | |||
| { | |||
| this.Score = Score; | |||
| this.speed = new(speed); | |||
| } | |||
| /// <returns>返回操作前的值</returns> | |||
| public override int SetReturnOri(int value) | |||
| { | |||
| int previousV = Interlocked.Exchange(ref v, value); | |||
| if (value - previousV > 0) | |||
| Score.AddPositive((int)(speed * (value - previousV))); | |||
| return previousV; | |||
| } | |||
| public override int Add(int x) | |||
| { | |||
| if (x > 0) Score.AddPositive((int)(speed * x)); | |||
| return Interlocked.Add(ref v, x); | |||
| } | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public override int AddPositive(int x) | |||
| { | |||
| Score.AddPositive((int)(speed * x)); | |||
| return Interlocked.Add(ref v, x); | |||
| } | |||
| public override int Sub(int x) | |||
| { | |||
| if (x < 0) Score.AddPositive((int)(speed * -x)); | |||
| return Interlocked.Add(ref v, -x); | |||
| } | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public override int SubPositive(int x) | |||
| { | |||
| return Interlocked.Add(ref v, -x); | |||
| } | |||
| public override int Inc() | |||
| { | |||
| Score.AddPositive((int)(speed)); | |||
| return Interlocked.Increment(ref v); | |||
| } | |||
| /// <returns>返回操作前的值</returns> | |||
| public override int CompareExReturnOri(int newV, int compareTo) | |||
| { | |||
| int previousV = Interlocked.CompareExchange(ref v, newV, compareTo); | |||
| if (newV - previousV > 0) | |||
| Score.AddPositive((int)(speed * (newV - previousV))); | |||
| return previousV; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 参数要求倍率speed(默认1)以及AtomicInt类的Score, | |||
| /// 在发生变化时,自动给Score加上变化的差乘以speed取整。 | |||
| /// 注意:AtomicIntChangeAffectScore本身为AtomicInt,提供的Score可能构成环而死锁。 | |||
| /// </summary> | |||
| public class AtomicIntChangeAffectScore : AtomicInt | |||
| { | |||
| public AtomicInt Score { get; set; } | |||
| public AtomicDouble speed; | |||
| public AtomicIntChangeAffectScore(int x, AtomicInt Score, double speed = 1.0) : base(x) | |||
| { | |||
| this.Score = Score; | |||
| this.speed = new(speed); | |||
| } | |||
| /// <returns>返回操作前的值</returns> | |||
| public override int SetReturnOri(int value) | |||
| { | |||
| int previousV = Interlocked.Exchange(ref v, value); | |||
| Score.Add((int)(speed * (value - previousV))); | |||
| return previousV; | |||
| } | |||
| public override int Add(int x) | |||
| { | |||
| Score.Add((int)(speed * x)); | |||
| return Interlocked.Add(ref v, x); | |||
| } | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public override int AddPositive(int x) | |||
| { | |||
| Score.AddPositive((int)(speed * x)); | |||
| return Interlocked.Add(ref v, x); | |||
| } | |||
| public override int Sub(int x) | |||
| { | |||
| Score.Sub((int)(speed * x)); | |||
| return Interlocked.Add(ref v, -x); | |||
| } | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public override int SubPositive(int x) | |||
| { | |||
| Score.SubPositive((int)(speed * x)); | |||
| return Interlocked.Add(ref v, -x); | |||
| } | |||
| public override int Inc() | |||
| { | |||
| Score.AddPositive((int)(speed)); | |||
| return Interlocked.Increment(ref v); | |||
| } | |||
| public override int Dec() | |||
| { | |||
| Score.SubPositive((int)(speed)); | |||
| return Interlocked.Decrement(ref v); | |||
| } | |||
| /// <returns>返回操作前的值</returns> | |||
| public override int CompareExReturnOri(int newV, int compareTo) | |||
| { | |||
| int previousV = Interlocked.CompareExchange(ref v, newV, compareTo); | |||
| Score.Add((int)(speed * (newV - previousV))); | |||
| return previousV; | |||
| } | |||
| } | |||
| public class AtomicLong : Atomic | |||
| { | |||
| private long v; | |||
| protected long v; | |||
| public AtomicLong(long x) | |||
| { | |||
| v = x; | |||
| } | |||
| public override string ToString() => Interlocked.Read(ref v).ToString(); | |||
| public long Get() => Interlocked.Read(ref v); | |||
| public static implicit operator long(AtomicLong along) => Interlocked.Read(ref along.v); | |||
| public override string ToString() => Interlocked.CompareExchange(ref v, -1, -1).ToString(); | |||
| public long Get() => Interlocked.CompareExchange(ref v, -1, -1); | |||
| public static implicit operator long(AtomicLong along) => Interlocked.CompareExchange(ref along.v, -1, -1); | |||
| /// <returns>返回操作前的值</returns> | |||
| public long SetReturnOri(long value) => Interlocked.Exchange(ref v, value); | |||
| public long Add(long x) => Interlocked.Add(ref v, x); | |||
| public long Sub(long x) => Interlocked.Add(ref v, -x); | |||
| public long Inc() => Interlocked.Increment(ref v); | |||
| public long Dec() => Interlocked.Decrement(ref v); | |||
| public virtual long SetReturnOri(long value) => Interlocked.Exchange(ref v, value); | |||
| public virtual long Add(long x) => Interlocked.Add(ref v, x); | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public virtual long AddPositive(long x) => Interlocked.Add(ref v, x); | |||
| public virtual long Sub(long x) => Interlocked.Add(ref v, -x); | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public virtual long SubPositive(long x) => Interlocked.Add(ref v, -x); | |||
| public virtual long Inc() => Interlocked.Increment(ref v); | |||
| public virtual long Dec() => Interlocked.Decrement(ref v); | |||
| /// <returns>返回操作前的值</returns> | |||
| public long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); | |||
| public virtual long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); | |||
| } | |||
| /// <summary> | |||
| /// 参数要求倍率speed(默认1)以及AtomicLong类的Score, | |||
| /// 在发生正向的变化时,自动给Score加上正向变化的差乘以speed取整。 | |||
| /// 注意:AtomicLongOnlyAddScore本身为AtomicLong,提供的Score可能构成环而死锁。 | |||
| /// </summary> | |||
| public class AtomicLongOnlyAddScore : AtomicLong | |||
| { | |||
| public AtomicLong Score { get; set; } | |||
| public AtomicDouble speed; | |||
| public AtomicLongOnlyAddScore(long x, AtomicLong score, double speed = 1.0) : base(x) | |||
| { | |||
| this.Score = score; | |||
| this.speed = new(speed); | |||
| } | |||
| /// <returns>返回操作前的值</returns> | |||
| public override long SetReturnOri(long value) | |||
| { | |||
| long previousV = Interlocked.Exchange(ref v, value); | |||
| if (value - previousV > 0) | |||
| Score.AddPositive((long)(speed * (value - previousV))); | |||
| return previousV; | |||
| } | |||
| public override long Add(long x) | |||
| { | |||
| if (x > 0) Score.AddPositive((long)(speed * x)); | |||
| return Interlocked.Add(ref v, x); | |||
| } | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public override long AddPositive(long x) | |||
| { | |||
| Score.AddPositive((long)(speed * x)); | |||
| return Interlocked.Add(ref v, x); | |||
| } | |||
| public override long Sub(long x) | |||
| { | |||
| if (x < 0) Score.AddPositive((long)(speed * -x)); | |||
| return Interlocked.Add(ref v, -x); | |||
| } | |||
| /// <summary> | |||
| /// 注意:确保参数为非负数 | |||
| /// </summary> | |||
| public override long SubPositive(long x) | |||
| { | |||
| return Interlocked.Add(ref v, -x); | |||
| } | |||
| public override long Inc() | |||
| { | |||
| Score.AddPositive((long)(speed)); | |||
| return Interlocked.Increment(ref v); | |||
| } | |||
| /// <returns>返回操作前的值</returns> | |||
| public override long CompareExReturnOri(long newV, long compareTo) | |||
| { | |||
| long previousV = Interlocked.CompareExchange(ref v, newV, compareTo); | |||
| if (newV - previousV > 0) | |||
| Score.AddPositive((long)(speed * (newV - previousV))); | |||
| return previousV; | |||
| } | |||
| } | |||
| public class AtomicDouble : Atomic | |||
| @@ -24,8 +24,8 @@ namespace Preparation.Utility | |||
| /// </summary> | |||
| public class IntInTheVariableRange : InTheVariableRange | |||
| { | |||
| private int v; | |||
| private int maxV; | |||
| protected int v; | |||
| protected int maxV; | |||
| #region 构造与读取 | |||
| public IntInTheVariableRange(int value, int maxValue) : base() | |||
| { | |||
| @@ -157,6 +157,13 @@ namespace Preparation.Utility | |||
| return true; | |||
| } | |||
| } | |||
| public void SetVToMaxV() | |||
| { | |||
| lock (vLock) | |||
| { | |||
| v = maxV; | |||
| } | |||
| } | |||
| public bool Set0IfNotMaxor0() | |||
| { | |||
| lock (vLock) | |||
| @@ -397,6 +404,32 @@ namespace Preparation.Utility | |||
| return v - previousV; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue | |||
| /// 如果无法加到maxValue则清零 | |||
| /// </summary> | |||
| /// <returns>返回是否清零</returns> | |||
| public bool Set0IfNotAddToMaxV(StartTime startTime, double speed = 1.0) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| if (v == maxV) return false; | |||
| int addV = (int)(startTime.StopIfPassing(maxV - v) * speed); | |||
| if (addV < 0) | |||
| { | |||
| v = 0; | |||
| return true; | |||
| } | |||
| if (maxV - v < addV) | |||
| { | |||
| v = maxV; | |||
| return false; | |||
| } | |||
| v = 0; | |||
| return false; | |||
| } | |||
| } | |||
| #endregion | |||
| } | |||
| @@ -405,8 +438,8 @@ namespace Preparation.Utility | |||
| /// </summary> | |||
| public class LongInTheVariableRange : InTheVariableRange | |||
| { | |||
| private long v; | |||
| private long maxV; | |||
| protected long v; | |||
| protected long maxV; | |||
| #region 构造与读取 | |||
| public LongInTheVariableRange(long value, long maxValue) : base() | |||
| { | |||
| @@ -455,23 +488,6 @@ namespace Preparation.Utility | |||
| } | |||
| #endregion | |||
| #region 内嵌读取(在锁的情况下读取内容同时读取其他更基本的外部数据) | |||
| public (long, long) GetValue(StartTime startTime) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| return (v, startTime.Get()); | |||
| } | |||
| } | |||
| public (long, long, long) GetValueAndMaxV(StartTime startTime) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| return (v, maxV, startTime.Get()); | |||
| } | |||
| } | |||
| #endregion | |||
| #region 普通设置MaxV与Value的值的方法 | |||
| /// <summary> | |||
| /// 若maxValue<=0则maxValue设为0并返回False | |||
| @@ -645,6 +661,13 @@ namespace Preparation.Utility | |||
| return true; | |||
| } | |||
| } | |||
| public void SetVToMaxV() | |||
| { | |||
| lock (vLock) | |||
| { | |||
| v = maxV; | |||
| } | |||
| } | |||
| public bool Set0IfNotMax() | |||
| { | |||
| @@ -709,22 +732,6 @@ namespace Preparation.Utility | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 增加量为时间差*速度,并将startTime变为long.MaxValue | |||
| /// </summary> | |||
| /// <returns>返回实际改变量</returns> | |||
| public long AddV(StartTime startTime, double speed = 1.0) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| long previousV = v; | |||
| long addV = (Environment.TickCount64 - startTime.Stop()); | |||
| if (addV < 0) v += (long)(addV * speed); | |||
| else return 0; | |||
| if (v > maxV) v = maxV; | |||
| return v - previousV; | |||
| } | |||
| } | |||
| #endregion | |||
| } | |||
| @@ -733,8 +740,8 @@ namespace Preparation.Utility | |||
| /// </summary> | |||
| public class DoubleInTheVariableRange : InTheVariableRange | |||
| { | |||
| private double v; | |||
| private double maxV; | |||
| protected double v; | |||
| protected double maxV; | |||
| #region 构造与读取 | |||
| public DoubleInTheVariableRange(double value, double maxValue) : base() | |||
| { | |||
| @@ -783,23 +790,6 @@ namespace Preparation.Utility | |||
| } | |||
| #endregion | |||
| #region 内嵌读取(在锁的情况下读取内容同时读取其他更基本的外部数据) | |||
| public (double, long) GetValue(StartTime startTime) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| return (v, startTime.Get()); | |||
| } | |||
| } | |||
| public (double, double, long) GetValueAndMaxValue(StartTime startTime) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| return (v, maxV, startTime.Get()); | |||
| } | |||
| } | |||
| #endregion | |||
| #region 普通设置MaxV与Value的值的方法 | |||
| /// <summary> | |||
| /// 若maxValue<=0则maxValue设为0并返回False | |||
| @@ -949,6 +939,13 @@ namespace Preparation.Utility | |||
| return true; | |||
| } | |||
| } | |||
| public void SetVToMaxV() | |||
| { | |||
| lock (vLock) | |||
| { | |||
| v = maxV; | |||
| } | |||
| } | |||
| public bool Set0IfNotMax() | |||
| { | |||
| @@ -35,6 +35,197 @@ namespace Preparation.Utility | |||
| } | |||
| } | |||
| public class LongInTheVariableRangeWithStartTime : LongInTheVariableRange | |||
| { | |||
| public StartTime startTime = new(); | |||
| public LongInTheVariableRangeWithStartTime(long value, long maxValue) : base(value, maxValue) { } | |||
| /// <summary> | |||
| /// 默认使Value=maxValue | |||
| /// </summary> | |||
| public LongInTheVariableRangeWithStartTime(long maxValue) : base(maxValue) { } | |||
| public LongInTheVariableRangeWithStartTime() : base() { } | |||
| #region 读取 | |||
| public (long, long) GetValueWithStartTime() | |||
| { | |||
| lock (vLock) | |||
| { | |||
| return (v, startTime.Get()); | |||
| } | |||
| } | |||
| public (long, long, long) GetValueAndMaxVWithStartTime() | |||
| { | |||
| lock (vLock) | |||
| { | |||
| return (v, maxV, startTime.Get()); | |||
| } | |||
| } | |||
| #endregion | |||
| /// <summary> | |||
| /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上并使startTime变为long.MaxValue | |||
| /// 如果无法加到maxValue则不加 | |||
| /// </summary> | |||
| /// <returns>返回试图加到的值与最大值</returns> | |||
| public (long, long, long) AddStartTimeToMaxV(double speed = 1.0) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| long addV = (long)(startTime.StopIfPassing(maxV - v) * speed); | |||
| if (addV < 0) return (v, maxV, startTime.Get()); | |||
| if (maxV - v < addV) return (v = maxV, maxV, startTime.Get()); | |||
| return (v + addV, maxV, startTime.Get()); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 增加量为时间差*速度,并将startTime变为long.MaxValue | |||
| /// </summary> | |||
| /// <returns>返回实际改变量</returns> | |||
| public long AddStartTime(double speed = 1.0) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| long previousV = v; | |||
| long addV = (Environment.TickCount64 - startTime.Stop()); | |||
| if (addV < 0) v += (long)(addV * speed); | |||
| else return 0; | |||
| if (v > maxV) v = maxV; | |||
| return v - previousV; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 试图加到满,如果加上时间差*速度可以达到MaxV,则加上 | |||
| /// 如果无法加到maxValue则清零 | |||
| /// 无论如何startTime变为long.MaxValue | |||
| /// </summary> | |||
| /// <returns>返回是否清零</returns> | |||
| public bool Set0IfNotAddStartTimeToMaxV(double speed = 1.0) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| if (v == maxV) return false; | |||
| long addV = (long)(startTime.Stop() * speed); | |||
| if (addV < 0) | |||
| { | |||
| v = 0; | |||
| return true; | |||
| } | |||
| if (maxV - v < addV) | |||
| { | |||
| v = maxV; | |||
| return false; | |||
| } | |||
| v = 0; | |||
| return false; | |||
| } | |||
| } | |||
| public void SetAndStop(long value = 0) | |||
| { | |||
| lock (vLock) | |||
| { | |||
| this.v = value; | |||
| startTime.Stop(); | |||
| } | |||
| } | |||
| } | |||
| public class TimeBasedProgressAtVariableSpeed | |||
| { | |||
| private LongInTheVariableRangeWithStartTime progress; | |||
| public AtomicDouble speed; | |||
| #region 构造 | |||
| public TimeBasedProgressAtVariableSpeed(long needProgress, double speed = 1.0) | |||
| { | |||
| progress = new LongInTheVariableRangeWithStartTime(0, needProgress); | |||
| if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0."); | |||
| this.speed = new(speed); | |||
| } | |||
| public TimeBasedProgressAtVariableSpeed() | |||
| { | |||
| progress = new LongInTheVariableRangeWithStartTime(0, 0); | |||
| this.speed = new(1.0); | |||
| } | |||
| #endregion | |||
| #region 读取 | |||
| public override string ToString() | |||
| { | |||
| long progressStored, lastStartTime; | |||
| (progressStored, lastStartTime) = progress.GetValueWithStartTime(); | |||
| return "ProgressStored: " + progressStored.ToString() | |||
| + " ; LastStartTime: " + lastStartTime.ToString() + "ms" | |||
| + " ; Speed: " + speed.ToString(); | |||
| } | |||
| public long GetProgressNow() => progress.AddStartTimeToMaxV((double)speed).Item1; | |||
| public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.AddStartTimeToMaxV((double)speed); | |||
| public long GetProgressStored() => progress.GetValue(); | |||
| public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV(); | |||
| public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxVWithStartTime(); | |||
| public bool IsFinished() | |||
| { | |||
| long progressNow, needTime; | |||
| (progressNow, needTime, _) = progress.AddStartTimeToMaxV((double)speed); | |||
| return progressNow == needTime; | |||
| } | |||
| public bool IsProgressing() | |||
| { | |||
| long progressNow, needTime, startT; | |||
| (progressNow, needTime, startT) = progress.AddStartTimeToMaxV((double)speed); | |||
| return (startT != long.MaxValue && progressNow != needTime); | |||
| } | |||
| #endregion | |||
| public bool Start(long needTime) | |||
| { | |||
| if (needTime <= 2) | |||
| { | |||
| Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0."); | |||
| return false; | |||
| } | |||
| if (progress.startTime.Start() != long.MaxValue) return false; | |||
| progress.SetMaxV(needTime); | |||
| return true; | |||
| } | |||
| public bool Start() | |||
| { | |||
| return progress.startTime.Start() == long.MaxValue; | |||
| } | |||
| /// <summary> | |||
| /// 使进度条强制终止清零 | |||
| /// </summary> | |||
| public void Set0() | |||
| { | |||
| progress.SetAndStop(); | |||
| } | |||
| /// <summary> | |||
| /// 如果进度条加上时间差不能为满,使进度条强制终止清零 | |||
| /// </summary> | |||
| public void TryStop() | |||
| { | |||
| progress.Set0IfNotAddStartTimeToMaxV(speed); | |||
| } | |||
| /// <summary> | |||
| /// 使进度条暂停 | |||
| /// </summary> | |||
| public bool Pause() | |||
| { | |||
| return progress.AddStartTime((double)speed) != 0; | |||
| } | |||
| /// <summary> | |||
| /// 使进度条进度为满 | |||
| /// </summary> | |||
| public void Finish() | |||
| { | |||
| progress.SetVToMaxV(); | |||
| progress.startTime.Stop(); | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 根据时间推算Start后完成多少进度的进度条(long)。 | |||
| /// 只允许Start(清零状态的进度条才可以Start)时修改needTime(请确保大于0); | |||
| @@ -158,85 +349,6 @@ namespace Preparation.Utility | |||
| //增加其他新的写操作可能导致不安全 | |||
| } | |||
| public class TimeBasedProgressAtVariableSpeed | |||
| { | |||
| public LongInTheVariableRange progress; | |||
| public StartTime startTime = new(); | |||
| public AtomicDouble speed; | |||
| #region 构造 | |||
| public TimeBasedProgressAtVariableSpeed(long needProgress, double speed) | |||
| { | |||
| if (needProgress <= 0) Debugger.Output("Bug:TimeBasedProgressAtVariableSpeed.needProgress (" + needProgress.ToString() + ") is less than 0."); | |||
| this.progress = new(0, needProgress); | |||
| this.speed = new(speed); | |||
| } | |||
| public TimeBasedProgressAtVariableSpeed() | |||
| { | |||
| this.progress = new(0, 0); | |||
| this.speed = new(1.0); | |||
| } | |||
| #endregion | |||
| #region 读取 | |||
| public override string ToString() | |||
| { | |||
| return "ProgressStored: " + progress.ToString() | |||
| + " ; LastStartTime: " + startTime.ToString() + "ms" | |||
| + " ; Speed: " + speed.ToString(); | |||
| } | |||
| public long GetProgressNow() => progress.TryAddToMaxV(startTime, (double)speed).Item1; | |||
| public (long, long, long) GetProgressNowAndNeedTimeAndLastStartTime() => progress.TryAddToMaxV(startTime, (double)speed); | |||
| public long GetProgressStored() => progress.GetValue(); | |||
| public (long, long) GetProgressStoredAndNeedTime() => progress.GetValueAndMaxV(); | |||
| public (long, long, long) GetProgressStoredAndNeedTimeAndLastStartTime() => progress.GetValueAndMaxV(startTime); | |||
| public bool IsFinished() | |||
| { | |||
| long progressNow, needTime; | |||
| (progressNow, needTime, _) = progress.TryAddToMaxV(startTime); | |||
| return progressNow == needTime; | |||
| } | |||
| public bool IsProgressing() | |||
| { | |||
| long progressNow, needTime, startT; | |||
| (progressNow, needTime, startT) = progress.TryAddToMaxV(startTime); | |||
| return (startT != long.MaxValue && progressNow != needTime); | |||
| } | |||
| #endregion | |||
| public bool Start(long needTime) | |||
| { | |||
| if (needTime <= 2) | |||
| { | |||
| Debugger.Output("Warning:Start TimeBasedProgressAtVariableSpeed with the needProgress (" + needTime.ToString() + ") which is less than 0."); | |||
| return false; | |||
| } | |||
| if (startTime.Start() != long.MaxValue) return false; | |||
| progress.SetMaxV(needTime); | |||
| return true; | |||
| } | |||
| public bool Start() | |||
| { | |||
| return startTime.Start() == long.MaxValue; | |||
| } | |||
| /// <summary> | |||
| /// 使进度条强制终止清零 | |||
| /// </summary> | |||
| public void Set0() | |||
| { | |||
| startTime.Stop(); | |||
| progress.SetPositiveV(0); | |||
| } | |||
| /// <summary> | |||
| /// 使进度条暂停 | |||
| /// </summary> | |||
| public bool Pause() | |||
| { | |||
| return progress.AddV(startTime, (double)speed) != 0; | |||
| } | |||
| } | |||
| /// <summary> | |||
| /// 冷却时间为可变的CDms的bool,不支持查看当前进度,初始为True | |||
| /// </summary> | |||
| @@ -232,8 +232,7 @@ namespace Server | |||
| Y = doorway.Position.y | |||
| } | |||
| }; | |||
| int progress = ((doorway.OpenStartTime > 0) ? ((int)(time - doorway.OpenStartTime)) : 0) + doorway.OpenDegree; | |||
| msg.GateMessage.Progress = (progress > GameData.degreeOfOpenedDoorway) ? GameData.degreeOfOpenedDoorway : progress; | |||
| msg.GateMessage.Progress = (int)doorway.ProgressOfDoorway.GetProgressNow(); | |||
| return msg; | |||
| } | |||
| private static MessageOfObj HiddenGate(EmergencyExit Exit) | |||