diff --git a/logic/GameClass/GameObj/GameObj.cs b/logic/GameClass/GameObj/GameObj.cs index eae58e58..8754ab9c 100755 --- a/logic/GameClass/GameObj/GameObj.cs +++ b/logic/GameClass/GameObj/GameObj.cs @@ -19,6 +19,7 @@ public abstract class GameObj(XY initPos, int initRadius, GameObjType initType) private static long currentMaxID = 0; // 目前游戏对象的最大ID public const long invalidID = long.MaxValue; // 无效的ID public long ID { get; } = Interlocked.Increment(ref currentMaxID); + protected XY position = initPos; public abstract XY Position { get; } public abstract bool IsRigid { get; } diff --git a/logic/GameClass/GameObj/Map/Map.cs b/logic/GameClass/GameObj/Map/Map.cs index 53d83f43..a368f255 100755 --- a/logic/GameClass/GameObj/Map/Map.cs +++ b/logic/GameClass/GameObj/Map/Map.cs @@ -220,7 +220,7 @@ public Map(MapStruct mapResource) return false; }; - if (GameObjDict[GameObjType.Wormhole].Cast().Find(wormhole => HasWormhole(wormhole)) == null) + if (GameObjDict[GameObjType.Wormhole].Cast()?.Find(wormhole => HasWormhole(wormhole)) == null) { List grids = [new XY(i, j)]; Add(new Wormhole(GameData.GetCellCenterPos(i, j), grids)); @@ -233,7 +233,7 @@ public Map(MapStruct mapResource) } } } - Homes = GameObjDict[GameObjType.Home].Cast().ToNewList(); + Homes = GameObjDict[GameObjType.Home].Cast()?.ToNewList()!; } } } \ No newline at end of file diff --git a/logic/GameClass/GameObj/Movable.cs b/logic/GameClass/GameObj/Movable.cs index 1b9922c8..cc22edef 100755 --- a/logic/GameClass/GameObj/Movable.cs +++ b/logic/GameClass/GameObj/Movable.cs @@ -14,7 +14,7 @@ public abstract class Movable(XY initPos, int initRadius, GameObjType initType) public object ActionLock => actionLock; private readonly ReaderWriterLockSlim moveReaderWriterLock = new(); /// - /// 规定MoveReaderWriterLock < ActionLock + /// 规定ActionLock > MoveReaderWriterLock /// public ReaderWriterLockSlim MoveReaderWriterLock => moveReaderWriterLock; public Semaphore ThreadNum { get; } = new(1, 1); diff --git a/logic/GameClass/GameObj/ObjOfShip.cs b/logic/GameClass/GameObj/ObjOfShip.cs index 39978a2f..716b2fb0 100755 --- a/logic/GameClass/GameObj/ObjOfShip.cs +++ b/logic/GameClass/GameObj/ObjOfShip.cs @@ -10,19 +10,16 @@ namespace GameClass.GameObj public abstract class ObjOfShip(XY initPos, int initRadius, GameObjType initType) : Movable(initPos, initRadius, initType), IObjOfShip { - public object ObjOfShipLock { get; } = new(); private IShip? parent = null; public IShip? Parent { get { - lock (ObjOfShipLock) - return parent; + return Interlocked.CompareExchange(ref parent, null, null); } set { - lock (ObjOfShipLock) - parent = value; + Interlocked.Exchange(ref parent, value); } } } diff --git a/logic/Gaming/AttackManager.cs b/logic/Gaming/AttackManager.cs index 4604da94..6fcf6059 100755 --- a/logic/Gaming/AttackManager.cs +++ b/logic/Gaming/AttackManager.cs @@ -99,7 +99,8 @@ private void BulletBomb(Bullet bullet, GameObj? objBeingShot) { if (bullet.CanBeBombed(kvp.Key)) { - beAttackedList.AddRange(gameMap.GameObjDict[kvp.Key].FindAll(gameObj => bullet.CanAttack((GameObj)gameObj))); + var thisList = gameMap.GameObjDict[kvp.Key].FindAll(gameObj => bullet.CanAttack((GameObj)gameObj)); + if (thisList != null) beAttackedList.AddRange(thisList); } } foreach (GameObj beAttackedObj in beAttackedList.Cast()) diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs index 26165738..37334a29 100755 --- a/logic/Gaming/Game.cs +++ b/logic/Gaming/Game.cs @@ -222,14 +222,15 @@ public List GetGameObj() { if (GameData.NeedCopy(keyValuePair.Key)) { - gameObjList.AddRange(gameMap.GameObjDict[keyValuePair.Key].ToNewList()); + var thisList = gameMap.GameObjDict[keyValuePair.Key].ToNewList(); + if (thisList != null) gameObjList.AddRange(thisList); } } return gameObjList; } public void UpdateBirthPoint() { - gameMap.GameObjDict[GameObjType.Construction].Cast().ForEach( + gameMap.GameObjDict[GameObjType.Construction].Cast()?.ForEach( delegate (Construction construction) { if (construction.ConstructionType == ConstructionType.Community) @@ -254,7 +255,7 @@ public void UpdateBirthPoint() { foreach (XY birthPoint in team.BirthPointList) { - gameMap.GameObjDict[GameObjType.Construction].Cast().ForEach( + gameMap.GameObjDict[GameObjType.Construction].Cast()?.ForEach( delegate (Construction construction) { if (construction.Position == birthPoint) @@ -277,7 +278,7 @@ public Game(MapStruct mapResource, int numOfTeam) actionManager = new(gameMap, shipManager); attackManager = new(gameMap, shipManager); teamList = []; - gameMap.GameObjDict[GameObjType.Home].Cast().ForEach( + gameMap.GameObjDict[GameObjType.Home].Cast()?.ForEach( delegate (GameObj gameObj) { if (gameObj.Type == GameObjType.Home) diff --git a/logic/Preparation/Utility/SafeValue/Atomic.cs b/logic/Preparation/Utility/SafeValue/Atomic.cs index 6a20f2d1..4cda558a 100755 --- a/logic/Preparation/Utility/SafeValue/Atomic.cs +++ b/logic/Preparation/Utility/SafeValue/Atomic.cs @@ -8,6 +8,20 @@ public abstract class Atomic { } + + public class AtomicT(T? x) : Atomic where T : class? + { + protected T? v = x; + + public override string ToString() => Interlocked.CompareExchange(ref v, null, null)?.ToString() ?? "NULL"; + public T? Get() => Interlocked.CompareExchange(ref v, null, null); + public static implicit operator T?(AtomicT aint) => Interlocked.CompareExchange(ref aint.v, null, null); + /// 返回操作前的值 + public virtual T? SetReturnOri(T? value) => Interlocked.Exchange(ref v, value); + /// 返回操作前的值 + public virtual T? CompareExReturnOri(T? newV, T? compareTo) => Interlocked.CompareExchange(ref v, newV, compareTo); + } + public class AtomicInt(int x) : Atomic { protected int v = x; diff --git a/logic/Preparation/Utility/SafeValue/ListLocked.cs b/logic/Preparation/Utility/SafeValue/ListLocked.cs index d95e261b..66d2d111 100755 --- a/logic/Preparation/Utility/SafeValue/ListLocked.cs +++ b/logic/Preparation/Utility/SafeValue/ListLocked.cs @@ -6,7 +6,7 @@ namespace Preparation.Utility { - public class LockedClassList where T : class + public class LockedClassList where T : class? { private readonly ReaderWriterLockSlim listLock = new(); private List list; @@ -104,7 +104,7 @@ public bool RemoveAt(int index) #endregion #region 读取与对类操作 - public TResult ReadLock(Func func) + public TResult? ReadLock(Func func) { listLock.EnterReadLock(); try @@ -130,7 +130,7 @@ public void ReadLock(Action func) } - public T this[int index] + public T? this[int index] { get { @@ -158,7 +158,7 @@ public bool Contains(T item) return ReadLock(() => { return list.Find(match); }); } - public List FindAll(Predicate match) + public List? FindAll(Predicate match) { return ReadLock(() => { return list.FindAll(match); }); } @@ -167,17 +167,17 @@ public List FindAll(Predicate match) public void ForEach(Action action) => ReadLock(() => { list.ForEach(action); }); - public Array ToArray() + public Array? ToArray() { return ReadLock(() => { return list.ToArray(); }); } - public List ToNewList() + public List? ToNewList() { List lt = new(); return ReadLock(() => { lt.AddRange(list); return lt; }); } - public LockedClassList Cast() where TResult : class + public LockedClassList? Cast() where TResult : class? { LockedClassList lt = new(); return ReadLock(() => { lt.AddRange(list.Cast()); return lt; }); diff --git a/logic/Server/GameServer.cs b/logic/Server/GameServer.cs index 32f1624e..acc74943 100755 --- a/logic/Server/GameServer.cs +++ b/logic/Server/GameServer.cs @@ -188,7 +188,7 @@ public void ReportGame(GameState gameState, bool requiredGaming = true) private bool PlayerDeceased(int playerID) //# 这里需要判断大本营deceased吗? { - return game.GameMap.GameObjDict[GameObjType.Ship].Cast().Find( + return game.GameMap.GameObjDict[GameObjType.Ship].Cast()?.Find( ship => ship.PlayerID == playerID && ship.ShipState == ShipStateType.Deceased ) != null; }