diff --git a/logic/GameClass/GameObj/Character/Character.BuffManager.cs b/logic/GameClass/GameObj/Character/Character.BuffManager.cs index 4979e42e..cc6ffa83 100644 --- a/logic/GameClass/GameObj/Character/Character.BuffManager.cs +++ b/logic/GameClass/GameObj/Character/Character.BuffManager.cs @@ -177,19 +177,6 @@ public bool TryUseSpear() return false; } - public bool TryDeleteInvisible() - { - if (HasInvisible) - { - lock (buffListLock[(int)BuffType.Invisible]) - { - buffList[(int)BuffType.Invisible].RemoveFirst(); - } - return true; - } - return false; - } - public void AddClairaudience(int shieldTime) => AddBuff(0, shieldTime, BuffType.Clairaudience, () => { }); public bool HasClairaudience @@ -215,6 +202,18 @@ public bool HasInvisible } } } + public bool TryDeleteInvisible() + { + if (HasInvisible) + { + lock (buffListLock[(int)BuffType.Invisible]) + { + buffList[(int)BuffType.Invisible].RemoveFirst(); + } + return true; + } + return false; + } /// /// 清除所有buff diff --git a/logic/GameClass/GameObj/Character/Character.Student.cs b/logic/GameClass/GameObj/Character/Character.Student.cs index 1b52f08f..9be96200 100644 --- a/logic/GameClass/GameObj/Character/Character.Student.cs +++ b/logic/GameClass/GameObj/Character/Character.Student.cs @@ -7,106 +7,24 @@ namespace GameClass.GameObj { public class Student : Character { - private readonly object fixLock = new(); - protected int fixSpeed; - /// - /// 修理电机速度 - /// - public int FixSpeed - { - get - { - lock (fixLock) - return fixSpeed; - } - set - { - lock (fixLock) - { - fixSpeed = value; - } - } - } + public AtomicInt FixSpeed { get; } = new AtomicInt(0); /// /// 原初修理电机速度 /// protected readonly int orgFixSpeed; - private readonly object treatLock = new(); - protected int treatSpeed = GameData.basicTreatSpeed; - public int TreatSpeed - { - get - { - lock (treatLock) - return treatSpeed; - } - set - { - lock (treatLock) - { - treatSpeed = value; - } - } - } + public AtomicInt TreatSpeed { get; } = new AtomicInt(GameData.basicTreatSpeed); protected readonly int orgTreatSpeed; - private readonly object addictionLock = new(); - private int maxGamingAddiction; - public int MaxGamingAddiction - { - get - { - lock (addictionLock) - return maxGamingAddiction; - } - protected set - { - lock (addictionLock) - { - if (value < gamingAddiction) gamingAddiction = value; - maxGamingAddiction = value; - } - } - } - private int gamingAddiction; - public int GamingAddiction - { - get - { - lock (addictionLock) - return gamingAddiction; - } - set - { - if (value > 0) - lock (addictionLock) - gamingAddiction = value <= maxGamingAddiction ? value : maxGamingAddiction; - else - lock (addictionLock) - gamingAddiction = 0; - } - } + public IntInTheVariableRange GamingAddiction { get; } = new IntInTheVariableRange(0, 0); - private int timeOfRescue = 0; - public int TimeOfRescue - { - get => Interlocked.CompareExchange(ref timeOfRescue, -1, -1); - } - public bool AddTimeOfRescue(int value) - { - return Interlocked.Add(ref timeOfRescue, value) >= GameData.basicTimeOfRescue; - } - public void SetTimeOfRescue(int value) - { - Interlocked.Exchange(ref timeOfRescue, value); - } + public AtomicInt TimeOfRescue { get; } = new AtomicInt(0); public Student(XY initPos, int initRadius, CharacterType characterType) : base(initPos, initRadius, characterType) { - this.orgFixSpeed = this.fixSpeed = ((IStudentType)Occupation).FixSpeed; - this.TreatSpeed = this.orgTreatSpeed = ((IStudentType)Occupation).TreatSpeed; - this.MaxGamingAddiction = ((IStudentType)Occupation).MaxGamingAddiction; + this.FixSpeed.SetReturnOri(this.orgFixSpeed = ((IStudentType)Occupation).FixSpeed); + this.TreatSpeed.SetReturnOri(this.orgTreatSpeed = ((IStudentType)Occupation).TreatSpeed); + this.GamingAddiction.SetPositiveMaxV(((IStudentType)Occupation).MaxGamingAddiction); } } public class Golem : Student, IGolem diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs index 720171c3..2b6a9e18 100644 --- a/logic/GameClass/GameObj/Character/Character.cs +++ b/logic/GameClass/GameObj/Character/Character.cs @@ -10,7 +10,7 @@ public partial class Character : Moveable, ICharacter // 负责人LHR摆烂终 { #region 装弹、攻击相关的基本属性及方法 private readonly object attackLock = new(); - public IntNumUpdateByCD BulletNum { get; } = new IntNumUpdateByCD(); + public IntNumUpdateEachCD BulletNum { get; } = new IntNumUpdateEachCD(); private int orgCD; public int OrgCD { @@ -110,32 +110,9 @@ public void AddBgm(BgmType bgm, double value) public int SpeedOfOpenChest => speedOfOpenChest; #endregion #region 血量相关的基本属性及方法 - public LongWithVariableRange HP { get; } + public LongInTheVariableRange HP { get; } - private readonly object vampireLock = new(); - public object VampireLock => vampire; - - private double vampire = 0; // 回血率:0-1之间 - public double Vampire - { - get - { - lock (vampireLock) - return vampire; - } - set - { - lock (vampireLock) - { - if (value > 1) - vampire = 1; - else if (value < 0) - vampire = 0; - else - vampire = value; - } - } - } + public DoubleInTheVariableRange Vampire { get; } = new DoubleInTheVariableRange(0, 1); public double OriVampire { get; protected set; } private readonly object treatLock = new(); @@ -159,7 +136,7 @@ public bool AddDegreeOfTreatment(int value, Student whoTreatYou) lock (treatLock) { degreeOfTreatment += value; - long addV = HP.TryAddAll(degreeOfTreatment); + long addV = HP.TryAddToMaxV(degreeOfTreatment); if (addV == 0) { degreeOfTreatment = 0; diff --git a/logic/GameClass/GameObj/Map/Chest.cs b/logic/GameClass/GameObj/Map/Chest.cs index 0fc69794..aae11fa0 100644 --- a/logic/GameClass/GameObj/Map/Chest.cs +++ b/logic/GameClass/GameObj/Map/Chest.cs @@ -18,7 +18,7 @@ public Chest(XY initPos) : private readonly Gadget[] propInChest = new Gadget[GameData.maxNumOfPropInChest] { new NullProp(), new NullProp() }; public Gadget[] PropInChest => propInChest; - private LongProgressByTime openProgress = new LongProgressByTime(); - public LongProgressByTime OpenProgress { get => openProgress; } + private TimeBasedProgressForInterrupting openProgress = new TimeBasedProgressForInterrupting(); + public TimeBasedProgressForInterrupting OpenProgress { get => openProgress; } } } diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs index 1b565d10..bfb78d27 100644 --- a/logic/Gaming/ActionManager.cs +++ b/logic/Gaming/ActionManager.cs @@ -318,7 +318,7 @@ public bool Rescue(Student player, Student? playerRescued = null) { if (playerRescued.StateNum == stateNumRescued) { - if (playerRescued.AddTimeOfRescue(GameData.checkInterval)) + if (playerRescued.TimeOfRescue.Add(GameData.checkInterval) >= GameData.basicTimeOfRescue) { playerRescued.SetPlayerStateNaturally(); playerRescued.HP.SetPositiveV(playerRescued.HP.GetMaxV() / 2); @@ -334,7 +334,7 @@ public bool Rescue(Student player, Student? playerRescued = null) finallyReturn: () => 0 ) .Start(); - playerRescued.SetTimeOfRescue(0); + playerRescued.TimeOfRescue.SetReturnOri(0); player.ThreadNum.Release(); playerRescued.ThreadNum.Release(); diff --git a/logic/Gaming/CharacterManager.cs b/logic/Gaming/CharacterManager.cs index 71c403ff..9a51e869 100644 --- a/logic/Gaming/CharacterManager.cs +++ b/logic/Gaming/CharacterManager.cs @@ -196,9 +196,9 @@ public void BeAddictedToGame(Student player, Ghost ghost) if (player.GamingAddiction > 0) { if (player.GamingAddiction < GameData.BeginGamingAddiction) - player.GamingAddiction = GameData.BeginGamingAddiction; + player.GamingAddiction.SetV(GameData.BeginGamingAddiction); else if (player.GamingAddiction < GameData.MidGamingAddiction) - player.GamingAddiction = GameData.MidGamingAddiction; + player.GamingAddiction.SetV(GameData.MidGamingAddiction); else { Die(player); @@ -214,16 +214,16 @@ public void BeAddictedToGame(Student player, Ghost ghost) Debugger.Output(player, " is addicted "); new FrameRateTaskExecutor( - () => stateNum == player.StateNum && player.GamingAddiction < player.MaxGamingAddiction && gameMap.Timer.IsGaming, + () => stateNum == player.StateNum && !player.GamingAddiction.IsMaxV() && gameMap.Timer.IsGaming, () => { - player.GamingAddiction += (player.PlayerState == PlayerStateType.Addicted) ? GameData.frameDuration : 0; + if (player.PlayerState == PlayerStateType.Addicted) player.GamingAddiction.AddPositiveV(GameData.frameDuration); }, timeInterval: GameData.frameDuration, () => { gameMap.MapRescueStudent(); - if (player.GamingAddiction == player.MaxGamingAddiction && gameMap.Timer.IsGaming) + if (player.GamingAddiction.IsMaxV() && gameMap.Timer.IsGaming) { Die(player); } diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs index 1a480b1b..c2326a83 100644 --- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs +++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs @@ -59,8 +59,8 @@ public bool ShowTime(Character player) else if (dis >= player.ViewRange) { Student student = (Student)person; - student.GamingAddiction += GameData.checkIntervalWhenShowTime; - if (student.GamingAddiction == student.MaxGamingAddiction) + student.GamingAddiction.AddPositiveV(GameData.checkIntervalWhenShowTime); + if (student.GamingAddiction.IsMaxV()) { characterManager.Die(student); } @@ -422,7 +422,7 @@ public bool Rouse(Character player) { character.SetPlayerStateNaturally(); character.HP.SetPositiveV(GameData.RemainHpWhenAddLife); - ((Student)character).SetTimeOfRescue(0); + ((Student)character).TimeOfRescue.SetReturnOri(0); player.AddScore(GameData.StudentScoreRescue); break; } diff --git a/logic/Preparation/Interface/ICharacter.cs b/logic/Preparation/Interface/ICharacter.cs index dbddda81..a6e6a5d0 100644 --- a/logic/Preparation/Interface/ICharacter.cs +++ b/logic/Preparation/Interface/ICharacter.cs @@ -5,15 +5,15 @@ namespace Preparation.Interface public interface ICharacter : IMoveable { public AtomicLong TeamID { get; } - public LongWithVariableRange HP { get; } + public LongInTheVariableRange HP { get; } public long Score { get; } public void AddScore(long add); - public double Vampire { get; } + public DoubleInTheVariableRange Vampire { get; } public PlayerStateType PlayerState { get; } public BulletType BulletOfPlayer { get; set; } public CharacterType CharacterType { get; } public ActiveSkill FindActiveSkill(ActiveSkillType activeSkillType); - public IntNumUpdateByCD BulletNum { get; } + public IntNumUpdateEachCD BulletNum { get; } public long SetPlayerState(RunningStateType running, PlayerStateType value = PlayerStateType.Null, IGameObj? obj = null); public bool ResetPlayerState(long state, RunningStateType running = RunningStateType.Null, PlayerStateType value = PlayerStateType.Null, IGameObj? obj = null); diff --git a/logic/Preparation/Interface/ISkill.cs b/logic/Preparation/Interface/ISkill.cs index d7b9330a..02aa6407 100644 --- a/logic/Preparation/Interface/ISkill.cs +++ b/logic/Preparation/Interface/ISkill.cs @@ -13,7 +13,7 @@ public interface IPassiveSkill : ISkill } public interface IActiveSkill : ISkill { - public LongProgressCoolingDownByCD SkillCD { get; } + public LongProgressUpdateEachCD SkillCD { get; } public int DurationTime { get; } //技能持续时间 public object ActiveSkillUseLock { get; } public bool IsBeingUsed { get; set; } @@ -21,7 +21,7 @@ public interface IActiveSkill : ISkill public abstract class ActiveSkill : IActiveSkill { - public abstract LongProgressCoolingDownByCD SkillCD { get; } + public abstract LongProgressUpdateEachCD SkillCD { get; } public abstract int DurationTime { get; } private readonly object activeSkillUseLock = new(); @@ -40,79 +40,79 @@ public bool IsBeingUsed public class CanBeginToCharge : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 2); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 2); public override int DurationTime => GameData.commonSkillTime * 3 / 10; } public class BecomeInvisible : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4 / 3); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 4 / 3); public override int DurationTime => GameData.commonSkillTime; } public class Punish : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 45 / 30); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 45 / 30); public override int DurationTime => 0; } public class HaveTea : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 3); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 3); public override int DurationTime => 0; } public class Rouse : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 4); public override int DurationTime => 0; } public class Encourage : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 4); public override int DurationTime => 0; } public class Inspire : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 4); public override int DurationTime => 0; } public class Howl : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 25 / 30); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 25 / 30); public override int DurationTime => 0; } public class ShowTime : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 8 / 3); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 8 / 3); public override int DurationTime => GameData.commonSkillTime; } public class JumpyBomb : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD / 2); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD / 2); public override int DurationTime => GameData.commonSkillTime * 3 / 10; } public class SparksNSplash : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 45 / 30); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 45 / 30); public override int DurationTime => GameData.commonSkillTime; } public class UseKnife : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD); public override int DurationTime => GameData.commonSkillTime / 10; } public class UseRobot : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD / 300); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD / 300); public override int DurationTime => 0; private int nowPlayerID; @@ -149,7 +149,7 @@ public bool TryResetNowPlayerID(int tryPlayerID) public class WriteAnswers : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD); public override int DurationTime => 0; private AtomicInt degreeOfMeditation = new(0); @@ -158,7 +158,7 @@ public class WriteAnswers : ActiveSkill public class SummonGolem : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD * 4 / 3); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD * 4 / 3); public override int DurationTime => 6000; private int[] golemStateArray = new int[GameData.maxSummonedGolemNum] { 0, 0, 0 }; @@ -211,7 +211,7 @@ public void AddGolem(int num) public class NullSkill : ActiveSkill { - public override LongProgressCoolingDownByCD SkillCD { get; } = new(GameData.commonSkillCD); + public override LongProgressUpdateEachCD SkillCD { get; } = new(GameData.commonSkillCD); public override int DurationTime => GameData.commonSkillTime; } diff --git a/logic/Preparation/Utility/SafeValue/Atomic.cs b/logic/Preparation/Utility/SafeValue/Atomic.cs new file mode 100644 index 00000000..5486c4ad --- /dev/null +++ b/logic/Preparation/Utility/SafeValue/Atomic.cs @@ -0,0 +1,67 @@ +using System; +using System.Threading; + +namespace Preparation.Utility +{ + //其对应属性不应当有set访问器,避免不安全的=赋值 + public class AtomicInt + { + private int v; + public AtomicInt(int x) + { + v = x; + } + public override string ToString() => Interlocked.CompareExchange(ref v, -1, -1).ToString(); + public int Get() => Interlocked.CompareExchange(ref v, -1, -1); + public static implicit operator int(AtomicInt aint) => Interlocked.CompareExchange(ref aint.v, -1, -1); + /// 返回操作前的值 + 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 int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); + } + + public class AtomicLong + { + private 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 aint) => Interlocked.Read(ref aint.v); + /// 返回操作前的值 + 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 long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); + } + + public class AtomicBool + { + private int v;//v==0为false,v==1为true + public AtomicBool(bool x) + { + v = x ? 1 : 0; + } + public override string ToString() => (Interlocked.CompareExchange(ref v, -2, -2) == 0) ? "false" : "true"; + public bool Get() => (Interlocked.CompareExchange(ref v, -1, -1) != 0); + public static implicit operator bool(AtomicBool abool) => (Interlocked.CompareExchange(ref abool.v, -1, -1) != 0); + /// 返回操作前的值 + public bool SetReturnOri(bool value) => (Interlocked.Exchange(ref v, value ? 1 : 0) != 0); + /// 赋值前的值是否与将赋予的值不相同 + public bool TrySet(bool value) + { + return (Interlocked.CompareExchange(ref v, value ? 1 : 0, value ? 0 : 1) ^ (value ? 1 : 0)) != 0; + } + public bool And(bool x) => Interlocked.And(ref v, x ? 1 : 0) != 0; + public bool Or(bool x) => Interlocked.Or(ref v, x ? 1 : 0) != 0; + } +} \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/InTheRange.cs b/logic/Preparation/Utility/SafeValue/InTheRange.cs new file mode 100644 index 00000000..44595be6 --- /dev/null +++ b/logic/Preparation/Utility/SafeValue/InTheRange.cs @@ -0,0 +1,730 @@ +using System; +using System.Threading; + +namespace Preparation.Utility +{ + //其对应属性不应当有set访问器,避免不安全的=赋值 + + /// + /// 一个保证在[0,maxValue]的可变int,支持可变的maxValue(请确保大于0) + /// + public class IntInTheVariableRange + { + private int v; + private int maxV; + private readonly object vLock = new(); + public IntInTheVariableRange(int value, int maxValue) + { + if (maxValue < 0) + { + Debugger.Output("Warning:Try to set IntInTheVariableRange.maxValue to " + maxValue.ToString() + "."); + maxValue = 0; + } + v = value < maxValue ? value : maxValue; + this.maxV = maxValue; + } + /// + /// 默认使Value=maxValue + /// + public IntInTheVariableRange(int maxValue) + { + if (maxValue < 0) + { + Debugger.Output("Warning:Try to set IntInTheVariableRange.maxValue to " + maxValue.ToString() + "."); + maxValue = 0; + } + v = this.maxV = maxValue; + } + public IntInTheVariableRange() + { + v = this.maxV = int.MaxValue; + } + + public override string ToString() + { + lock (vLock) + { + return "value:" + v.ToString() + " ,maxValue:" + maxV.ToString(); + } + } + public int GetValue() { lock (vLock) return v; } + public static implicit operator int(IntInTheVariableRange aint) => aint.GetValue(); + public int GetMaxV() { lock (vLock) return maxV; } + + /// + /// 若maxValue<=0则maxValue设为0并返回False + /// + public bool SetMaxV(int maxValue) + { + if (maxValue <= 0) + { + lock (vLock) + { + v = maxV = 0; + return false; + } + } + lock (vLock) + { + maxV = maxValue; + if (v > maxValue) v = maxValue; + } + return true; + } + /// + /// 应当保证该maxValue>=0 + /// + public void SetPositiveMaxV(int maxValue) + { + lock (vLock) + { + maxV = maxValue; + if (v > maxValue) v = maxValue; + } + } + /// + /// 如果当前值大于maxValue,则更新maxValue失败 + /// + public bool TrySetMaxV(int maxValue) + { + lock (vLock) + { + if (v > maxValue) return false; + maxV = maxValue; + return true; + } + } + + /// + /// 应当保证该value>=0 + /// + public int SetPositiveV(int value) + { + lock (vLock) + { + return v = (value > maxV) ? maxV : value; + } + } + public int SetV(int value) + { + if (value <= 0) + { + lock (vLock) + { + return v = 0; + } + } + lock (vLock) + { + return v = (value > maxV) ? maxV : value; + } + } + /// 返回实际改变量 + public int AddV(int addV) + { + lock (vLock) + { + int previousV = v; + v += addV; + if (v < 0) v = 0; + if (v > maxV) v = maxV; + return v - previousV; + } + } + /// + /// 应当保证增加值大于0 + /// + /// 返回实际改变量 + public int AddPositiveV(int addPositiveV) + { + lock (vLock) + { + addPositiveV = Math.Min(addPositiveV, maxV - v); + v += addPositiveV; + } + return addPositiveV; + } + public void MulV(int mulV) + { + if (mulV <= 0) + { + lock (vLock) v = 0; + return; + } + lock (vLock) + { + if (v > maxV / mulV) v = maxV; //避免溢出 + else v *= mulV; + } + } + /// + /// 应当保证乘数大于0 + /// + public void MulPositiveV(int mulPositiveV) + { + lock (vLock) + { + if (v > maxV / mulPositiveV) v = maxV; //避免溢出 + else v *= mulPositiveV; + } + } + /// 返回实际改变量 + public int SubV(int subV) + { + lock (vLock) + { + int previousV = v; + v -= subV; + if (v < 0) v = 0; + if (v > maxV) v = maxV; + return v - previousV; + } + } + /// + /// 应当保证该减少值大于0 + /// + /// 返回实际改变量 + public int SubPositiveV(int subPositiveV) + { + lock (vLock) + { + subPositiveV = Math.Min(subPositiveV, v); + v -= subPositiveV; + } + return subPositiveV; + } + + /// + /// 试图加到满,如果无法加到maxValue则不加并返回-1 + /// + /// 返回实际改变量 + public int TryAddToMaxV(int addV) + { + lock (vLock) + { + if (maxV - v <= addV) + { + addV = maxV - v; + v = maxV; + return addV; + } + return -1; + } + } + + public bool Set0IfNotMax() + { + lock (vLock) + { + if (v < maxV) + { + v = 0; + return true; + } + } + return false; + } + public bool Set0IfMax() + { + lock (vLock) + { + if (v == maxV) + { + v = 0; + return true; + } + } + return false; + } + + public bool IsMaxV() + { + lock (vLock) + { + return v == maxV; + } + } + } + + /// + /// 一个保证在[0,maxValue]的可变long,支持可变的maxValue(请确保大于0) + /// + public class LongInTheVariableRange + { + private long v; + private long maxV; + private readonly object vLock = new(); + public LongInTheVariableRange(long value, long maxValue) + { + if (maxValue < 0) + { + Debugger.Output("Warning:Try to set SafaValues.LongInTheVariableRange.maxValue to " + maxValue.ToString() + "."); + maxValue = 0; + } + v = value < maxValue ? value : maxValue; + this.maxV = maxValue; + } + /// + /// 默认使Value=maxValue + /// + public LongInTheVariableRange(long maxValue) + { + if (maxValue < 0) + { + Debugger.Output("Warning:Try to set SafaValues.LongInTheVariableRange.maxValue to " + maxValue.ToString() + "."); + maxValue = 0; + } + v = this.maxV = maxValue; + } + public LongInTheVariableRange() + { + v = this.maxV = long.MaxValue; + } + + public override string ToString() + { + lock (vLock) + { + return "value:" + v.ToString() + " ,maxValue:" + maxV.ToString(); + } + } + public long GetValue() { lock (vLock) return v; } + public static implicit operator long(LongInTheVariableRange aint) => aint.GetValue(); + public long GetMaxV() { lock (vLock) return maxV; } + + /// + /// 若maxValue<=0则maxValue设为0并返回False + /// + public bool SetMaxV(long maxValue) + { + if (maxValue <= 0) + { + lock (vLock) + { + v = maxV = 0; + return false; + } + } + lock (vLock) + { + maxV = maxValue; + if (v > maxValue) v = maxValue; + } + return true; + } + /// + /// 应当保证该maxValue>=0 + /// + public void SetPositiveMaxV(long maxValue) + { + lock (vLock) + { + maxV = maxValue; + if (v > maxValue) v = maxValue; + } + } + /// + /// 如果当前值大于maxValue,则更新maxValue失败 + /// + public bool TrySetMaxV(long maxValue) + { + lock (vLock) + { + if (v > maxValue) return false; + maxV = maxValue; + return true; + } + } + + /// + /// 应当保证该value>=0 + /// + public long SetPositiveV(long value) + { + lock (vLock) + { + return v = (value > maxV) ? maxV : value; + } + } + public long SetV(long value) + { + if (value <= 0) + { + lock (vLock) + { + return v = 0; + } + } + lock (vLock) + { + return v = (value > maxV) ? maxV : value; + } + } + /// 返回实际改变量 + public long AddV(long addV) + { + lock (vLock) + { + long previousV = v; + v += addV; + if (v < 0) v = 0; + if (v > maxV) v = maxV; + return v - previousV; + } + } + /// + /// 应当保证增加值大于0 + /// + /// 返回实际改变量 + public long AddPositiveV(long addPositiveV) + { + lock (vLock) + { + addPositiveV = Math.Min(addPositiveV, maxV - v); + v += addPositiveV; + } + return addPositiveV; + } + public void MulV(long mulV) + { + if (mulV <= 0) + { + lock (vLock) v = 0; + return; + } + lock (vLock) + { + if (v > maxV / mulV) v = maxV; //避免溢出 + else v *= mulV; + } + } + /// + /// 应当保证乘数大于0 + /// + public void MulPositiveV(long mulPositiveV) + { + lock (vLock) + { + if (v > maxV / mulPositiveV) v = maxV; //避免溢出 + else v *= mulPositiveV; + } + } + /// 返回实际改变量 + public long SubV(long subV) + { + lock (vLock) + { + long previousV = v; + v -= subV; + if (v < 0) v = 0; + if (v > maxV) v = maxV; + return v - previousV; + } + } + /// + /// 应当保证该减少值大于0 + /// + /// 返回实际改变量 + public long SubPositiveV(long subPositiveV) + { + lock (vLock) + { + subPositiveV = Math.Min(subPositiveV, v); + v -= subPositiveV; + } + return subPositiveV; + } + + /// + /// 试图加到满,如果无法加到maxValue则不加并返回-1 + /// + /// 返回实际改变量 + public long TryAddToMaxV(long addV) + { + lock (vLock) + { + if (maxV - v <= addV) + { + addV = maxV - v; + v = maxV; + return addV; + } + return -1; + } + } + + public bool Set0IfNotMax() + { + lock (vLock) + { + if (v < maxV) + { + v = 0; + return true; + } + } + return false; + } + public bool Set0IfMax() + { + lock (vLock) + { + if (v == maxV) + { + v = 0; + return true; + } + } + return false; + } + + public bool IsMaxV() + { + lock (vLock) + { + return v == maxV; + } + } + } + + /// + /// 一个保证在[0,maxValue]的可变double,支持可变的maxValue(请确保大于0) + /// + public class DoubleInTheVariableRange + { + private double v; + private double maxV; + private readonly object vLock = new(); + public DoubleInTheVariableRange(double value, double maxValue) + { + if (maxValue < 0) + { + Debugger.Output("Warning:Try to set DoubleInTheVariableRange.maxValue to " + maxValue.ToString() + "."); + maxValue = 0; + } + v = value < maxValue ? value : maxValue; + this.maxV = maxValue; + } + /// + /// 默认使Value=maxValue + /// + public DoubleInTheVariableRange(double maxValue) + { + if (maxValue < 0) + { + Debugger.Output("Warning:Try to set DoubleInTheVariableRange.maxValue to " + maxValue.ToString() + "."); + maxValue = 0; + } + v = this.maxV = maxValue; + } + public DoubleInTheVariableRange() + { + v = this.maxV = double.MaxValue; + } + + public override string ToString() + { + lock (vLock) + { + return "value:" + v.ToString() + " ,maxValue:" + maxV.ToString(); + } + } + public double GetValue() { lock (vLock) return v; } + public static implicit operator double(DoubleInTheVariableRange adouble) => adouble.GetValue(); + public double GetMaxV() { lock (vLock) return maxV; } + + /// + /// 若maxValue<=0则maxValue设为0并返回False + /// + public bool SetMaxV(double maxValue) + { + if (maxValue <= 0) + { + lock (vLock) + { + v = maxV = 0; + return false; + } + } + lock (vLock) + { + maxV = maxValue; + if (v > maxValue) v = maxValue; + } + return true; + } + /// + /// 应当保证该maxValue>=0 + /// + public void SetPositiveMaxV(double maxValue) + { + lock (vLock) + { + maxV = maxValue; + if (v > maxValue) v = maxValue; + } + } + /// + /// 如果当前值大于maxValue,则更新maxValue失败 + /// + public bool TrySetMaxV(double maxValue) + { + lock (vLock) + { + if (v > maxValue) return false; + maxV = maxValue; + return true; + } + } + + /// + /// 应当保证该value>=0 + /// + public double SetPositiveV(double value) + { + lock (vLock) + { + return v = (value > maxV) ? maxV : value; + } + } + public double SetV(double value) + { + if (value <= 0) + { + lock (vLock) + { + return v = 0; + } + } + lock (vLock) + { + return v = (value > maxV) ? maxV : value; + } + } + /// 返回实际改变量 + public double AddV(double addV) + { + lock (vLock) + { + double previousV = v; + v += addV; + if (v < 0) v = 0; + if (v > maxV) v = maxV; + return v - previousV; + } + } + /// + /// 应当保证增加值大于0 + /// + /// 返回实际改变量 + public double AddPositiveV(double addPositiveV) + { + lock (vLock) + { + addPositiveV = Math.Min(addPositiveV, maxV - v); + v += addPositiveV; + } + return addPositiveV; + } + public void MulV(double mulV) + { + if (mulV <= 0) + { + lock (vLock) v = 0; + return; + } + lock (vLock) + { + if (v > maxV / mulV) v = maxV; //避免溢出 + else v *= mulV; + } + } + /// + /// 应当保证乘数大于0 + /// + public void MulPositiveV(double mulPositiveV) + { + lock (vLock) + { + if (v > maxV / mulPositiveV) v = maxV; //避免溢出 + else v *= mulPositiveV; + } + } + /// 返回实际改变量 + public double SubV(double subV) + { + lock (vLock) + { + double previousV = v; + v -= subV; + if (v < 0) v = 0; + if (v > maxV) v = maxV; + return v - previousV; + } + } + /// + /// 应当保证该减少值大于0 + /// + /// 返回实际改变量 + public double SubPositiveV(double subPositiveV) + { + lock (vLock) + { + subPositiveV = Math.Min(subPositiveV, v); + v -= subPositiveV; + } + return subPositiveV; + } + + /// + /// 试图加到满,如果无法加到maxValue则不加并返回-1 + /// + /// 返回实际改变量 + public double TryAddToMaxV(double addV) + { + lock (vLock) + { + if (maxV - v <= addV) + { + addV = maxV - v; + v = maxV; + return addV; + } + return -1; + } + } + + public bool Set0IfNotMax() + { + lock (vLock) + { + if (v < maxV) + { + v = 0; + return true; + } + } + return false; + } + public bool Set0IfMax() + { + lock (vLock) + { + if (v == maxV) + { + v = 0; + return true; + } + } + return false; + } + + public bool IsMaxV() + { + lock (vLock) + { + return v == maxV; + } + } + } +} \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/SafeValueDouble.cs b/logic/Preparation/Utility/SafeValue/SafeValueDouble.cs deleted file mode 100644 index e3ac9c6d..00000000 --- a/logic/Preparation/Utility/SafeValue/SafeValueDouble.cs +++ /dev/null @@ -1,8 +0,0 @@ -using System; -using System.Threading; - -namespace Preparation.Utility -{ - //其对应属性不应当有set访问器,避免不安全的=赋值 - -} \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/SafeValueInt.cs b/logic/Preparation/Utility/SafeValue/SafeValueInt.cs deleted file mode 100644 index c26dc6b9..00000000 --- a/logic/Preparation/Utility/SafeValue/SafeValueInt.cs +++ /dev/null @@ -1,371 +0,0 @@ -using System; -using System.Threading; - -namespace Preparation.Utility -{ - //其对应属性不应当有set访问器,避免不安全的=赋值 - public class AtomicInt - { - private int v; - public AtomicInt(int x) - { - v = x; - } - public override string ToString() => Interlocked.CompareExchange(ref v, -1, -1).ToString(); - public int Get() => Interlocked.CompareExchange(ref v, -1, -1); - public static implicit operator int(AtomicInt aint) => Interlocked.CompareExchange(ref aint.v, -1, -1); - /// 返回操作前的值 - 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 int CompareExReturnOri(int newV, int compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); - } - - /* - /// - /// 记录(不是根据时间)完成多少进度的进度条(long)。 - /// - public struct IntProgressByAdding - { - private int completedProgress = -1; - private int requiredProgress; - public IntProgressByAdding(int completedProgress, int requiredProgress) - { - this.completedProgress = completedProgress; - this.requiredProgress = requiredProgress; - } - public IntProgressByAdding(int requiredProgress) - { - this.requiredProgress = requiredProgress; - } - public IntProgressByAdding() - { - this.requiredProgress=int.MaxValue; - } - } - */ - - /// - /// 一个保证在[0,maxValue]的可变int,支持可变的maxValue(请确保大于0) - /// - public class IntWithVariableRange - { - private int v; - private int maxV; - private readonly object vLock = new(); - public IntWithVariableRange(int value, int maxValue) - { - if (maxValue < 0) - { - Debugger.Output("Warning:Try to set IntWithVariableRange.maxValue to " + maxValue.ToString() + "."); - maxValue = 0; - } - v = value < maxValue ? value : maxValue; - this.maxV = maxValue; - } - /// - /// 默认使Value=maxValue - /// - public IntWithVariableRange(int maxValue) - { - if (maxValue < 0) - { - Debugger.Output("Warning:Try to set IntWithVariableRange.maxValue to " + maxValue.ToString() + "."); - maxValue = 0; - } - v = this.maxV = maxValue; - } - public IntWithVariableRange() - { - v = this.maxV = int.MaxValue; - } - - public override string ToString() - { - lock (vLock) - { - return "value:" + v.ToString() + " ,maxValue:" + maxV.ToString(); - } - } - public int GetValue() { lock (vLock) return v; } - public static implicit operator int(IntWithVariableRange aint) => aint.GetValue(); - public int GetMaxV() { lock (vLock) return maxV; } - - /// - /// 若maxValue<=0则maxValue设为0并返回False - /// - public bool SetMaxV(int maxValue) - { - if (maxValue < 0) maxValue = 0; - lock (vLock) - { - maxV = maxValue; - if (v > maxValue) v = maxValue; - } - return maxValue > 0; - } - /// - /// 应当保证该maxValue>=0 - /// - public void SetPositiveMaxV(int maxValue) - { - lock (vLock) - { - maxV = maxValue; - if (v > maxValue) v = maxValue; - } - } - /// - /// 应当保证该value>=0 - /// - public int SetPositiveV(int value) - { - lock (vLock) - { - return v = (value > maxV) ? maxV : value; - } - } - public int SetV(int value) - { - if (value < 0) value = 0; - lock (vLock) - { - return v = (value > maxV) ? maxV : value; - } - } - /// 返回实际改变量 - public int AddV(int addV) - { - lock (vLock) - { - int previousV = v; - v += addV; - if (v < 0) v = 0; - if (v > maxV) v = maxV; - return v - previousV; - } - } - /// - /// 应当保证增加值大于0 - /// - /// 返回实际改变量 - public int AddPositiveV(int addPositiveV) - { - lock (vLock) - { - addPositiveV = Math.Min(addPositiveV, maxV - v); - v += addPositiveV; - } - return addPositiveV; - } - /// - /// 应当保证该减少值大于0,返回实际改变量 - /// - public int SubPositiveV(int subPositiveV) - { - lock (vLock) - { - subPositiveV = Math.Min(subPositiveV, v); - v -= subPositiveV; - } - return subPositiveV; - } - - /// - /// 试图加到满,如果无法加到maxValue则不加并返回-1 - /// - public int TryAddAll(int addV) - { - lock (vLock) - { - if (maxV - v <= addV) - { - addV = maxV - v; - v = maxV; - return addV; - } - return 0; - } - } - } - - /// - /// 一个保证在[0,maxNum],每CDms自动+1的int,支持可变的CD、maxNum(请确保大于0) - /// - public class IntNumUpdateByCD - { - private int num; - private int maxNum; - private int cd; - private long updateTime = 0; - private readonly object numLock = new(); - public IntNumUpdateByCD(int num, int maxNum, int cd) - { - if (num < 0) Debugger.Output("Bug:IntNumUpdateByCD.num (" + num.ToString() + ") is less than 0."); - if (maxNum < 0) Debugger.Output("Bug:IntNumUpdateByCD.maxNum (" + maxNum.ToString() + ") is less than 0."); - if (cd <= 0) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 0."); - this.num = (num < maxNum) ? num : maxNum; - this.maxNum = maxNum; - this.cd = cd; - this.updateTime = Environment.TickCount64; - } - /// - /// 默认使num=maxNum - /// - public IntNumUpdateByCD(int maxNum, int cd) - { - if (maxNum < 0) Debugger.Output("Bug:IntNumUpdateByCD.maxNum (" + maxNum.ToString() + ") is less than 0."); - if (cd <= 0) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 0."); - this.num = this.maxNum = maxNum; - this.cd = cd; - } - public IntNumUpdateByCD() - { - this.num = this.maxNum = 0; - this.cd = int.MaxValue; - } - - public int GetMaxNum() { lock (numLock) return maxNum; } - public int GetCD() { lock (numLock) return cd; } - public int GetNum(long time) - { - lock (numLock) - { - if (num < maxNum && time - updateTime >= cd) - { - int add = (int)Math.Min(maxNum - num, (time - updateTime) / cd); - updateTime += add * cd; - return (num += add); - } - return num; - } - } - public static implicit operator int(IntNumUpdateByCD aint) => aint.GetNum(Environment.TickCount64); - - /// - /// 应当保证该subV>=0 - /// - public int TrySub(int subV) - { - if (subV < 0) Debugger.Output("Bug:IntNumUpdateByCD Try to sub " + subV.ToString() + ", which is less than 0."); - long time = Environment.TickCount64; - lock (numLock) - { - if (num < maxNum && time - updateTime >= cd) - { - int add = (int)Math.Min(maxNum - num, (time - updateTime) / cd); - updateTime += add * cd; - num += add; - } - if (num == maxNum) updateTime = time; - num -= subV = Math.Min(subV, num); - } - return subV; - } - /// - /// 应当保证该addV>=0 - /// - public void TryAdd(int addV) - { - if (addV < 0) Debugger.Output("Bug:IntNumUpdateByCD Try to add " + addV.ToString() + ", which is less than 0."); - lock (numLock) - { - num += Math.Min(addV, maxNum - num); - } - } - /// - /// 若maxNum<=0则maxNum及Num设为0并返回False - /// - public bool SetMaxNumAndNum(int maxNum) - { - if (maxNum < 0) maxNum = 0; - lock (numLock) - { - this.num = this.maxNum = maxNum; - } - return maxNum > 0; - } - /// - /// 应当保证该maxnum>=0 - /// - public void SetPositiveMaxNumAndNum(int maxNum) - { - lock (numLock) - { - this.num = this.maxNum = maxNum; - } - } - /// - /// 应当保证该maxnum>=0 - /// - public void SetPositiveMaxNum(int maxNum) - { - lock (numLock) - { - if ((this.maxNum = maxNum) < num) - num = maxNum; - } - } - /// - /// 若maxNum<=0则maxNum及Num设为0并返回False - /// - public bool SetMaxNum(int maxNum) - { - if (maxNum < 0) maxNum = 0; - lock (numLock) - { - if ((this.maxNum = maxNum) < num) - num = maxNum; - } - return maxNum > 0; - } - /// - /// 若num<0则num设为0并返回False - /// - public bool SetNum(int num) - { - lock (numLock) - { - if (num < 0) - { - this.num = 0; - updateTime = Environment.TickCount64; - return false; - } - if (num < maxNum) - { - if (this.num == maxNum) updateTime = Environment.TickCount64; - this.num = num; - } - else this.num = maxNum; - return true; - } - } - /// - /// 应当保证该num>=0 - /// - public void SetPositiveNum(int num) - { - lock (numLock) - { - if (num < maxNum) - { - if (this.num == maxNum) updateTime = Environment.TickCount64; - this.num = num; - } - else this.num = maxNum; - } - } - public void SetCD(int cd) - { - lock (numLock) - { - if (cd <= 0) Debugger.Output("Bug:SetReturnOri IntNumUpdateByCD.cd to " + cd.ToString() + "."); - this.cd = cd; - } - } - } -} \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/SafeValueLong.cs b/logic/Preparation/Utility/SafeValue/SafeValueLong.cs deleted file mode 100644 index 345d683b..00000000 --- a/logic/Preparation/Utility/SafeValue/SafeValueLong.cs +++ /dev/null @@ -1,171 +0,0 @@ -using System; -using System.Threading; - -namespace Preparation.Utility -{ - //其对应属性不应当有set访问器,避免不安全的=赋值 - public class AtomicLong - { - private 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 aint) => Interlocked.Read(ref aint.v); - /// 返回操作前的值 - 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 long CompareExReturnOri(long newV, long compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); - } - - /// - /// 一个保证在[0,maxValue]的可变long,支持可变的maxValue(请确保大于0) - /// - public class LongWithVariableRange - { - private long v; - private long maxV; - private readonly object vLock = new(); - public LongWithVariableRange(long value, long maxValue) - { - if (maxValue < 0) - { - Debugger.Output("Warning:Try to set SafaValues.LongWithVariableRange.maxValue to " + maxValue.ToString() + "."); - maxValue = 0; - } - v = value < maxValue ? value : maxValue; - this.maxV = maxValue; - } - /// - /// 默认使Value=maxValue - /// - public LongWithVariableRange(long maxValue) - { - if (maxValue < 0) - { - Debugger.Output("Warning:Try to set SafaValues.LongWithVariableRange.maxValue to " + maxValue.ToString() + "."); - maxValue = 0; - } - v = this.maxV = maxValue; - } - public LongWithVariableRange() - { - v = this.maxV = long.MaxValue; - } - - public override string ToString() - { - lock (vLock) - { - return "value:" + v.ToString() + " ,maxValue:" + maxV.ToString(); - } - } - public long GetValue() { lock (vLock) return v; } - public static implicit operator long(LongWithVariableRange aint) => aint.GetValue(); - public long GetMaxV() { lock (vLock) return maxV; } - - /// - /// 若maxValue<=0则maxValue设为0并返回False - /// - public bool SetMaxV(long maxValue) - { - if (maxValue < 0) maxValue = 0; - lock (vLock) - { - maxV = maxValue; - if (v > maxValue) v = maxValue; - } - return maxValue > 0; - } - /// - /// 应当保证该maxValue>=0 - /// - public void SetPositiveMaxV(long maxValue) - { - lock (vLock) - { - maxV = maxValue; - if (v > maxValue) v = maxValue; - } - } - /// - /// 应当保证该value>=0 - /// - public long SetPositiveV(long value) - { - lock (vLock) - { - return v = (value > maxV) ? maxV : value; - } - } - public long SetV(long value) - { - if (value < 0) value = 0; - lock (vLock) - { - return v = (value > maxV) ? maxV : value; - } - } - /// - /// 返回实际改变量 - /// - public long AddV(long addV) - { - lock (vLock) - { - long previousV = v; - v += addV; - if (v < 0) v = 0; - if (v > maxV) v = maxV; - return v - previousV; - } - } - /// - /// 应当保证该增加值大于0,返回实际改变量 - /// - public long AddPositiveV(long addPositiveV) - { - lock (vLock) - { - addPositiveV = Math.Min(addPositiveV, maxV - v); - v += addPositiveV; - } - return addPositiveV; - } - /// - /// 应当保证该减少值大于0,返回实际改变量 - /// - public long SubPositiveV(long subPositiveV) - { - lock (vLock) - { - subPositiveV = Math.Min(subPositiveV, v); - v -= subPositiveV; - } - return subPositiveV; - } - - /// - /// 试图加到满,如果无法加到maxValue则不加并返回-1 - /// - public long TryAddAll(long addV) - { - lock (vLock) - { - if (maxV - v <= addV) - { - addV = maxV - v; - v = maxV; - return addV; - } - return -1; - } - } - } -} \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/SafeValueOther.cs b/logic/Preparation/Utility/SafeValue/SafeValueOther.cs deleted file mode 100644 index d839da72..00000000 --- a/logic/Preparation/Utility/SafeValue/SafeValueOther.cs +++ /dev/null @@ -1,28 +0,0 @@ -using System; -using System.Threading; - -namespace Preparation.Utility -{ - //其对应属性不应当有set访问器,避免不安全的=赋值 - - public class AtomicBool - { - private int v;//v==0为false,v==1为true - public AtomicBool(bool x) - { - v = x ? 1 : 0; - } - public override string ToString() => (Interlocked.CompareExchange(ref v, -2, -2) == 0) ? "false" : "true"; - public bool Get() => (Interlocked.CompareExchange(ref v, -1, -1) != 0); - public static implicit operator bool(AtomicBool abool) => (Interlocked.CompareExchange(ref abool.v, -1, -1) != 0); - /// 返回操作前的值 - public bool SetReturnOri(bool value) => (Interlocked.Exchange(ref v, value ? 1 : 0) != 0); - /// 赋值前的值是否与将赋予的值不相同 - public bool TrySet(bool value) - { - return (Interlocked.CompareExchange(ref v, value ? 1 : 0, value ? 0 : 1) ^ (value ? 1 : 0)) != 0; - } - public bool And(bool x) => Interlocked.And(ref v, x ? 1 : 0) != 0; - public bool Or(bool x) => Interlocked.Or(ref v, x ? 1 : 0) != 0; - } -} \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/SafeValueTime.cs b/logic/Preparation/Utility/SafeValue/SafeValueTime.cs deleted file mode 100644 index 41f911dc..00000000 --- a/logic/Preparation/Utility/SafeValue/SafeValueTime.cs +++ /dev/null @@ -1,226 +0,0 @@ -using System; -using System.Threading; - -namespace Preparation.Utility -{ - //其对应属性不应当有set访问器,避免不安全的=赋值 - - /// - /// 根据时间推算Start后完成多少进度的进度条(long)。 - /// 只允许Start时修改needTime(请确保大于0); - /// 支持TrySet0使未完成的进度条终止清零;支持Set0使进度条强制终止清零; - /// 通过原子操作实现。 - /// - public class LongProgressByTime - { - private long endT = long.MaxValue; - private long needT; - - public LongProgressByTime(long needTime) - { - if (needTime <= 0) Debugger.Output("Bug:LongProgressByTime.needTime (" + needTime.ToString() + ") is less than 0."); - this.needT = needTime; - } - public LongProgressByTime() - { - this.needT = 0; - } - public long GetEndTime() => Interlocked.CompareExchange(ref endT, -2, -2); - public long GetNeedTime() => Interlocked.CompareExchange(ref needT, -2, -2); - public override string ToString() => "EndTime:" + Interlocked.CompareExchange(ref endT, -2, -2).ToString() + " ms, NeedTime:" + Interlocked.CompareExchange(ref needT, -2, -2).ToString() + " ms"; - public bool IsFinished() - { - return Interlocked.CompareExchange(ref endT, -2, -2) <= Environment.TickCount64; - } - public bool IsOpened() => Interlocked.Read(ref endT) != long.MaxValue; - /// - /// GetProgress<0则表明未开始 - /// - public long GetProgress() - { - long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - Environment.TickCount64; - if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); - return Interlocked.CompareExchange(ref needT, -2, -2) - cutime; - } - public long GetNonNegativeProgress() - { - long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - Environment.TickCount64; - if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); - long progress = Interlocked.CompareExchange(ref needT, -2, -2) - cutime; - return progress < 0 ? 0 : progress; - } - /// - /// GetProgress<0则表明未开始 - /// - public long GetProgress(long time) - { - long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - time; - if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); - return Interlocked.CompareExchange(ref needT, -2, -2) - cutime; - } - public long GetNonNegativeProgress(long time) - { - long cutime = Interlocked.Read(ref endT) - time; - if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); - long progress = Interlocked.CompareExchange(ref needT, -2, -2) - cutime; - return progress < 0 ? 0 : progress; - } - /// - /// <0则表明未开始 - /// - public static implicit operator long(LongProgressByTime pLong) => pLong.GetProgress(); - - /// - /// GetProgressDouble<0则表明未开始 - /// - public double GetProgressDouble() - { - long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - Environment.TickCount64; - if (cutime <= 0) return 1; - long needTime = Interlocked.CompareExchange(ref needT, -2, -2); - if (needTime == 0) return 0; - return 1.0 - ((double)cutime / needTime); - } - public double GetNonNegativeProgressDouble(long time) - { - long cutime = Interlocked.Read(ref endT) - time; - if (cutime <= 0) return 1; - long needTime = Interlocked.CompareExchange(ref needT, -2, -2); - if (needTime <= cutime) return 0; - return 1.0 - ((double)cutime / needTime); - } - - public bool Start(long needTime) - { - if (needTime <= 0) - { - Debugger.Output("Warning:Start LongProgressByTime with the needTime (" + needTime.ToString() + ") which is less than 0."); - return false; - } - //规定只有Start可以修改needT,且需要先访问endTime,从而避免锁(某种程度上endTime可以认为是needTime的锁) - if (Interlocked.CompareExchange(ref endT, Environment.TickCount64 + needTime, long.MaxValue) != long.MaxValue) return false; - if (needTime <= 2) Debugger.Output("Warning:the field of LongProgressByTime is " + needTime.ToString() + ",which is too small."); - Interlocked.Exchange(ref needT, needTime); - return true; - } - public bool Start() - { - long needTime = Interlocked.CompareExchange(ref needT, -2, -2); - if (Interlocked.CompareExchange(ref endT, Environment.TickCount64 + needTime, long.MaxValue) != long.MaxValue) return false; - return true; - } - /// - /// 使进度条强制终止清零 - /// - public void Set0() => Interlocked.Exchange(ref endT, long.MaxValue); - /// - /// 使未完成的进度条终止清零 - /// - public bool TrySet0() - { - if (Environment.TickCount64 < Interlocked.CompareExchange(ref endT, -2, -2)) - { - Interlocked.Exchange(ref endT, long.MaxValue); - return true; - } - return false; - } - //增加其他新的写操作可能导致不安全 - } - - /// - /// 一个每CDms自动更新冷却的bool,支持可变的无锁CD,不支持查看当前进度,初始为True - /// - public class BoolCoolingDownByCD - { - private long cd; - private long nextUpdateTime = 0; - public BoolCoolingDownByCD(int cd) - { - if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); - this.cd = cd; - } - public BoolCoolingDownByCD(long cd) - { - if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); - this.cd = cd; - } - public BoolCoolingDownByCD(long cd, long startTime) - { - if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); - this.cd = cd; - this.nextUpdateTime = startTime; - } - - public long GetCD() => Interlocked.Read(ref cd); - - public bool TryUse() - { - long needTime = Interlocked.Exchange(ref nextUpdateTime, long.MaxValue); - if (needTime <= Environment.TickCount64) - { - Interlocked.Exchange(ref nextUpdateTime, Environment.TickCount64 + Interlocked.Read(ref cd)); - return true; - } - Interlocked.Exchange(ref nextUpdateTime, needTime); - return false; - } - public void SetCD(int cd) - { - if (cd <= 1) Debugger.Output("Bug:SetReturnOri IntNumUpdateByCD.cd to " + cd.ToString() + "."); - Interlocked.Exchange(ref this.cd, cd); - } - } - - /// - /// 一个每CDms自动更新的进度条,支持可变的CD,初始为满 - /// - public class LongProgressCoolingDownByCD - { - private int isusing = 0; - private long cd; - private long nextUpdateTime = 0; - public LongProgressCoolingDownByCD(int cd) - { - if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); - this.cd = cd; - } - public LongProgressCoolingDownByCD(long cd) - { - if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); - this.cd = cd; - } - public LongProgressCoolingDownByCD(long cd, long startTime) - { - if (cd <= 1) Debugger.Output("Bug:IntNumUpdateByCD.cd (" + cd.ToString() + ") is less than 1."); - this.cd = cd; - this.nextUpdateTime = startTime; - } - - public long GetRemainingTime() - { - long v = Interlocked.Read(ref nextUpdateTime) - Environment.TickCount64; - return v < 0 ? 0 : v; - } - public long GetCD() => Interlocked.Read(ref cd); - - public bool TryUse() - { - if (Interlocked.Exchange(ref isusing, 1) == 1) return false; - long needTime = Interlocked.Read(ref nextUpdateTime); - if (needTime <= Environment.TickCount64) - { - Interlocked.Exchange(ref nextUpdateTime, Environment.TickCount64 + Interlocked.Read(ref cd)); - Interlocked.Exchange(ref isusing, 0); - return true; - } - Interlocked.Exchange(ref isusing, 0); - return false; - } - public void SetCD(int cd) - { - if (cd <= 1) Debugger.Output("Bug:SetReturnOri IntNumUpdateByCD.cd to " + cd.ToString() + "."); - Interlocked.Exchange(ref this.cd, cd); - } - } -} \ No newline at end of file diff --git a/logic/Preparation/Utility/SafeValue/TimeBased.cs b/logic/Preparation/Utility/SafeValue/TimeBased.cs new file mode 100644 index 00000000..566441c2 --- /dev/null +++ b/logic/Preparation/Utility/SafeValue/TimeBased.cs @@ -0,0 +1,403 @@ +using System; +using System.Threading; + +namespace Preparation.Utility +{ + //其对应属性不应当有set访问器,避免不安全的=赋值 + + /// + /// 根据时间推算Start后完成多少进度的进度条(long)。 + /// 只允许Start(清零状态的进度条才可以Start)时修改needTime(请确保大于0); + /// 支持InterruptToSet0使未完成的进度条终止清零;支持Set0使进度条强制终止清零; + /// 通过原子操作实现。 + /// + public class TimeBasedProgressForInterrupting + { + private long endT = long.MaxValue; + private long needT; + + public TimeBasedProgressForInterrupting(long needTime) + { + if (needTime <= 0) Debugger.Output("Bug:TimeBasedProgressForInterrupting.needTime (" + needTime.ToString() + ") is less than 0."); + this.needT = needTime; + } + public TimeBasedProgressForInterrupting() + { + this.needT = 0; + } + public long GetEndTime() => Interlocked.CompareExchange(ref endT, -2, -2); + public long GetNeedTime() => Interlocked.CompareExchange(ref needT, -2, -2); + public override string ToString() => "EndTime:" + Interlocked.CompareExchange(ref endT, -2, -2).ToString() + " ms, NeedTime:" + Interlocked.CompareExchange(ref needT, -2, -2).ToString() + " ms"; + public bool IsFinished() + { + return Interlocked.CompareExchange(ref endT, -2, -2) <= Environment.TickCount64; + } + public bool IsOpened() => Interlocked.Read(ref endT) != long.MaxValue; + /// + /// GetProgress<0则表明未开始 + /// + public long GetProgress() + { + long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - Environment.TickCount64; + if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); + return Interlocked.CompareExchange(ref needT, -2, -2) - cutime; + } + public long GetNonNegativeProgress() + { + long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - Environment.TickCount64; + if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); + long progress = Interlocked.CompareExchange(ref needT, -2, -2) - cutime; + return progress < 0 ? 0 : progress; + } + /// + /// GetProgress<0则表明未开始 + /// + public long GetProgress(long time) + { + long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - time; + if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); + return Interlocked.CompareExchange(ref needT, -2, -2) - cutime; + } + public long GetNonNegativeProgress(long time) + { + long cutime = Interlocked.Read(ref endT) - time; + if (cutime <= 0) return Interlocked.CompareExchange(ref needT, -2, -2); + long progress = Interlocked.CompareExchange(ref needT, -2, -2) - cutime; + return progress < 0 ? 0 : progress; + } + /// + /// <0则表明未开始 + /// + public static implicit operator long(TimeBasedProgressForInterrupting pLong) => pLong.GetProgress(); + + /// + /// GetProgressDouble<0则表明未开始 + /// + public double GetProgressDouble() + { + long cutime = Interlocked.CompareExchange(ref endT, -2, -2) - Environment.TickCount64; + if (cutime <= 0) return 1; + long needTime = Interlocked.CompareExchange(ref needT, -2, -2); + if (needTime == 0) return 0; + return 1.0 - ((double)cutime / needTime); + } + public double GetNonNegativeProgressDouble(long time) + { + long cutime = Interlocked.Read(ref endT) - time; + if (cutime <= 0) return 1; + long needTime = Interlocked.CompareExchange(ref needT, -2, -2); + if (needTime <= cutime) return 0; + return 1.0 - ((double)cutime / needTime); + } + + public bool Start(long needTime) + { + if (needTime <= 0) + { + Debugger.Output("Warning:Start TimeBasedProgressForInterrupting with the needTime (" + needTime.ToString() + ") which is less than 0."); + return false; + } + //规定只有Start可以修改needT,且需要先访问endTime,从而避免锁(某种程度上endTime可以认为是needTime的锁) + if (Interlocked.CompareExchange(ref endT, Environment.TickCount64 + needTime, long.MaxValue) != long.MaxValue) return false; + if (needTime <= 2) Debugger.Output("Warning:the field of TimeBasedProgressForInterrupting is " + needTime.ToString() + ",which is too small."); + Interlocked.Exchange(ref needT, needTime); + return true; + } + public bool Start() + { + long needTime = Interlocked.CompareExchange(ref needT, -2, -2); + if (Interlocked.CompareExchange(ref endT, Environment.TickCount64 + needTime, long.MaxValue) != long.MaxValue) return false; + return true; + } + /// + /// 使进度条强制终止清零 + /// + public void Set0() => Interlocked.Exchange(ref endT, long.MaxValue); + /// + /// 使未完成的进度条终止清零 + /// + public bool InterruptToSet0() + { + if (Environment.TickCount64 < Interlocked.CompareExchange(ref endT, -2, -2)) + { + Interlocked.Exchange(ref endT, long.MaxValue); + return true; + } + return false; + } + //增加其他新的写操作可能导致不安全 + } + + /// + /// 冷却时间为可变的CDms的bool,不支持查看当前进度,初始为True + /// + public class BoolUpdateEachCD + { + private long cd; + private long nextUpdateTime = 0; + public BoolUpdateEachCD(int cd) + { + if (cd <= 1) Debugger.Output("Bug:BoolUpdateEachCD.cd (" + cd.ToString() + ") is less than 1."); + this.cd = cd; + } + public BoolUpdateEachCD(long cd) + { + if (cd <= 1) Debugger.Output("Bug:BoolUpdateEachCD.cd (" + cd.ToString() + ") is less than 1."); + this.cd = cd; + } + public BoolUpdateEachCD(long cd, long startTime) + { + if (cd <= 1) Debugger.Output("Bug:BoolUpdateEachCD.cd (" + cd.ToString() + ") is less than 1."); + this.cd = cd; + this.nextUpdateTime = startTime; + } + + public long GetCD() => Interlocked.Read(ref cd); + + public bool TryUse() + { + long needTime = Interlocked.Exchange(ref nextUpdateTime, long.MaxValue); + if (needTime <= Environment.TickCount64) + { + Interlocked.Exchange(ref nextUpdateTime, Environment.TickCount64 + Interlocked.Read(ref cd)); + return true; + } + Interlocked.Exchange(ref nextUpdateTime, needTime); + return false; + } + public void SetCD(int cd) + { + if (cd <= 1) Debugger.Output("Bug:BoolUpdateEachCD.cd to " + cd.ToString() + "."); + Interlocked.Exchange(ref this.cd, cd); + } + } + + /// + /// 冷却时间为可变的CDms的进度条,初始为满 + /// + public class LongProgressUpdateEachCD + { + private int isusing = 0; + private long cd; + private long nextUpdateTime = 0; + public LongProgressUpdateEachCD(int cd) + { + if (cd <= 1) Debugger.Output("Bug:LongProgressUpdateEachCD.cd (" + cd.ToString() + ") is less than 1."); + this.cd = cd; + } + public LongProgressUpdateEachCD(long cd) + { + if (cd <= 1) Debugger.Output("Bug:LongProgressUpdateEachCD.cd (" + cd.ToString() + ") is less than 1."); + this.cd = cd; + } + public LongProgressUpdateEachCD(long cd, long startTime) + { + if (cd <= 1) Debugger.Output("Bug:LongProgressUpdateEachCD.cd (" + cd.ToString() + ") is less than 1."); + this.cd = cd; + this.nextUpdateTime = startTime; + } + + public long GetRemainingTime() + { + long v = Interlocked.Read(ref nextUpdateTime) - Environment.TickCount64; + return v < 0 ? 0 : v; + } + public long GetCD() => Interlocked.Read(ref cd); + + public bool TryUse() + { + if (Interlocked.Exchange(ref isusing, 1) == 1) return false; + long needTime = Interlocked.Read(ref nextUpdateTime); + if (needTime <= Environment.TickCount64) + { + Interlocked.Exchange(ref nextUpdateTime, Environment.TickCount64 + Interlocked.Read(ref cd)); + Interlocked.Exchange(ref isusing, 0); + return true; + } + Interlocked.Exchange(ref isusing, 0); + return false; + } + public void SetCD(int cd) + { + if (cd <= 1) Debugger.Output("Bug:Set LongProgressUpdateEachCD.cd to " + cd.ToString() + "."); + Interlocked.Exchange(ref this.cd, cd); + } + } + + /// + /// 一个保证在[0,maxNum],每CDms自动+1的int,支持可变的CD、maxNum(请确保大于0) + /// + public class IntNumUpdateEachCD + { + private int num; + private int maxNum; + private int cd; + private long updateTime = 0; + private readonly object numLock = new(); + public IntNumUpdateEachCD(int num, int maxNum, int cd) + { + if (num < 0) Debugger.Output("Bug:IntNumUpdateEachCD.num (" + num.ToString() + ") is less than 0."); + if (maxNum < 0) Debugger.Output("Bug:IntNumUpdateEachCD.maxNum (" + maxNum.ToString() + ") is less than 0."); + if (cd <= 0) Debugger.Output("Bug:IntNumUpdateEachCD.cd (" + cd.ToString() + ") is less than 0."); + this.num = (num < maxNum) ? num : maxNum; + this.maxNum = maxNum; + this.cd = cd; + this.updateTime = Environment.TickCount64; + } + /// + /// 默认使num=maxNum + /// + public IntNumUpdateEachCD(int maxNum, int cd) + { + if (maxNum < 0) Debugger.Output("Bug:IntNumUpdateEachCD.maxNum (" + maxNum.ToString() + ") is less than 0."); + if (cd <= 0) Debugger.Output("Bug:IntNumUpdateEachCD.cd (" + cd.ToString() + ") is less than 0."); + this.num = this.maxNum = maxNum; + this.cd = cd; + } + public IntNumUpdateEachCD() + { + this.num = this.maxNum = 0; + this.cd = int.MaxValue; + } + + public int GetMaxNum() { lock (numLock) return maxNum; } + public int GetCD() { lock (numLock) return cd; } + public int GetNum(long time) + { + lock (numLock) + { + if (num < maxNum && time - updateTime >= cd) + { + int add = (int)Math.Min(maxNum - num, (time - updateTime) / cd); + updateTime += add * cd; + return (num += add); + } + return num; + } + } + public static implicit operator int(IntNumUpdateEachCD aint) => aint.GetNum(Environment.TickCount64); + + /// + /// 应当保证该subV>=0 + /// + public int TrySub(int subV) + { + if (subV < 0) Debugger.Output("Bug:IntNumUpdateEachCD Try to sub " + subV.ToString() + ", which is less than 0."); + long time = Environment.TickCount64; + lock (numLock) + { + if (num < maxNum && time - updateTime >= cd) + { + int add = (int)Math.Min(maxNum - num, (time - updateTime) / cd); + updateTime += add * cd; + num += add; + } + if (num == maxNum) updateTime = time; + num -= subV = Math.Min(subV, num); + } + return subV; + } + /// + /// 应当保证该addV>=0 + /// + public void TryAdd(int addV) + { + if (addV < 0) Debugger.Output("Bug:IntNumUpdateEachCD Try to add " + addV.ToString() + ", which is less than 0."); + lock (numLock) + { + num += Math.Min(addV, maxNum - num); + } + } + /// + /// 若maxNum<=0则maxNum及Num设为0并返回False + /// + public bool SetMaxNumAndNum(int maxNum) + { + if (maxNum < 0) maxNum = 0; + lock (numLock) + { + this.num = this.maxNum = maxNum; + } + return maxNum > 0; + } + /// + /// 应当保证该maxnum>=0 + /// + public void SetPositiveMaxNumAndNum(int maxNum) + { + lock (numLock) + { + this.num = this.maxNum = maxNum; + } + } + /// + /// 应当保证该maxnum>=0 + /// + public void SetPositiveMaxNum(int maxNum) + { + lock (numLock) + { + if ((this.maxNum = maxNum) < num) + num = maxNum; + } + } + /// + /// 若maxNum<=0则maxNum及Num设为0并返回False + /// + public bool SetMaxNum(int maxNum) + { + if (maxNum < 0) maxNum = 0; + lock (numLock) + { + if ((this.maxNum = maxNum) < num) + num = maxNum; + } + return maxNum > 0; + } + /// + /// 若num<0则num设为0并返回False + /// + public bool SetNum(int num) + { + lock (numLock) + { + if (num < 0) + { + this.num = 0; + updateTime = Environment.TickCount64; + return false; + } + if (num < maxNum) + { + if (this.num == maxNum) updateTime = Environment.TickCount64; + this.num = num; + } + else this.num = maxNum; + return true; + } + } + /// + /// 应当保证该num>=0 + /// + public void SetPositiveNum(int num) + { + lock (numLock) + { + if (num < maxNum) + { + if (this.num == maxNum) updateTime = Environment.TickCount64; + this.num = num; + } + else this.num = maxNum; + } + } + public void SetCD(int cd) + { + lock (numLock) + { + if (cd <= 0) Debugger.Output("Bug:Set IntNumUpdateEachCD.cd to " + cd.ToString() + "."); + this.cd = cd; + } + } + } +} \ No newline at end of file