| @@ -5,10 +5,10 @@ python_main_dir=/usr/local/PlayerCode/CAPI/python | |||
| playback_dir=/usr/local/playback | |||
| if [ $EXPOSED -eq 1 ]; then | |||
| nice -10 ./Server --port 8888 --studentCount 4 --trickerCount 1 --resultFileName $playback_dir/result --gameTimeInSecond $TIME --mapResource $MAP --url $URL --token $TOKEN --fileName $playback_dir/video --startLockFile $playback_dir/start.lock > $playback_dir/server.log 2>&1 & | |||
| nice -10 ./Server --port 8888 --studentCount 4 --trickerCount 1 --resultFileName $playback_dir/result --gameTimeInSecond $TIME --mode $MODE --mapResource $MAP --url $URL --token $TOKEN --fileName $playback_dir/video --startLockFile $playback_dir/start.lock > $playback_dir/server.log 2>&1 & | |||
| server_pid=$! | |||
| else | |||
| nice -10 ./Server --port 8888 --studentCount 4 --trickerCount 1 --resultFileName $playback_dir/result --gameTimeInSecond $TIME --mapResource $MAP --notAllowSpectator --url $URL --token $TOKEN --fileName $playback_dir/video --startLockFile $playback_dir/start.lock > $playback_dir/server.log 2>&1 & | |||
| nice -10 ./Server --port 8888 --studentCount 4 --trickerCount 1 --resultFileName $playback_dir/result --gameTimeInSecond $TIME --mode $MODE --mapResource $MAP --notAllowSpectator --url $URL --token $TOKEN --fileName $playback_dir/video --startLockFile $playback_dir/start.lock > $playback_dir/server.log 2>&1 & | |||
| server_pid=$! | |||
| fi | |||
| sleep 5 | |||
| @@ -11,7 +11,7 @@ namespace GameClass.GameObj | |||
| private readonly IOccupation occupation; | |||
| public IOccupation Occupation => occupation; | |||
| private Dictionary<ActiveSkillType, ActiveSkill> activeSkillDictionary = new(); | |||
| private readonly Dictionary<ActiveSkillType, ActiveSkill> activeSkillDictionary = new(); | |||
| public Dictionary<ActiveSkillType, ActiveSkill> ActiveSkillDictionary => activeSkillDictionary; | |||
| public ActiveSkill FindActiveSkill(ActiveSkillType activeSkillType) | |||
| @@ -42,9 +42,9 @@ namespace GameClass.GameObj | |||
| this.alertnessRadius = Occupation.AlertnessRadius; | |||
| this.viewRange = Occupation.ViewRange; | |||
| this.characterType = characterType; | |||
| this.SpeedOfOpeningOrLocking = Occupation.SpeedOfOpeningOrLocking; | |||
| this.SpeedOfClimbingThroughWindows = Occupation.SpeedOfClimbingThroughWindows; | |||
| this.SpeedOfOpenChest = Occupation.SpeedOfOpenChest; | |||
| this.speedOfOpeningOrLocking = Occupation.SpeedOfOpeningOrLocking; | |||
| this.speedOfClimbingThroughWindows = Occupation.SpeedOfClimbingThroughWindows; | |||
| this.speedOfOpenChest = Occupation.SpeedOfOpenChest; | |||
| foreach (var activeSkill in this.Occupation.ListOfIActiveSkill) | |||
| { | |||
| @@ -7,16 +7,21 @@ namespace GameClass.GameObj | |||
| { | |||
| public class Student : Character | |||
| { | |||
| private readonly object fixLock = new(); | |||
| protected int fixSpeed; | |||
| /// <summary> | |||
| /// 修理电机速度 | |||
| /// </summary> | |||
| public int FixSpeed | |||
| { | |||
| get => fixSpeed; | |||
| get | |||
| { | |||
| lock (fixLock) | |||
| return fixSpeed; | |||
| } | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| lock (fixLock) | |||
| { | |||
| fixSpeed = value; | |||
| } | |||
| @@ -25,7 +30,7 @@ namespace GameClass.GameObj | |||
| /// <summary> | |||
| /// 原初修理电机速度 | |||
| /// </summary> | |||
| public int OrgFixSpeed { get; protected set; } | |||
| protected readonly int orgFixSpeed; | |||
| protected int treatSpeed = GameData.basicTreatSpeed; | |||
| public int TreatSpeed | |||
| @@ -122,7 +127,7 @@ namespace GameClass.GameObj | |||
| public Student(XY initPos, int initRadius, CharacterType characterType) : base(initPos, initRadius, characterType) | |||
| { | |||
| this.OrgFixSpeed = this.fixSpeed = ((IStudentType)Occupation).FixSpeed; | |||
| this.orgFixSpeed = this.fixSpeed = ((IStudentType)Occupation).FixSpeed; | |||
| this.TreatSpeed = this.OrgTreatSpeed = ((IStudentType)Occupation).TreatSpeed; | |||
| this.MaxGamingAddiction = ((IStudentType)Occupation).MaxGamingAddiction; | |||
| } | |||
| @@ -31,7 +31,15 @@ namespace GameClass.GameObj | |||
| } | |||
| } | |||
| } | |||
| public int OrgCD { get; protected set; } | |||
| private int orgCD; | |||
| public int OrgCD | |||
| { | |||
| get | |||
| { | |||
| lock (actionLock) | |||
| return orgCD; | |||
| } | |||
| } | |||
| public readonly BulletType OriBulletOfPlayer; | |||
| private BulletType bulletOfPlayer; | |||
| @@ -49,7 +57,7 @@ namespace GameClass.GameObj | |||
| lock (actionLock) | |||
| { | |||
| bulletOfPlayer = value; | |||
| cd = OrgCD = (BulletFactory.BulletCD(value)); | |||
| cd = orgCD = (BulletFactory.BulletCD(value)); | |||
| Debugger.Output(this, string.Format("'s CD has been set to: {0}.", cd)); | |||
| maxBulletNum = bulletNum = (BulletFactory.BulletNum(value)); | |||
| } | |||
| @@ -167,43 +175,22 @@ namespace GameClass.GameObj | |||
| public int ViewRange => viewRange; | |||
| #endregion | |||
| #region 交互相关的基本属性及方法 | |||
| private int speedOfOpeningOrLocking; | |||
| private readonly int speedOfOpeningOrLocking; | |||
| public int SpeedOfOpeningOrLocking | |||
| { | |||
| get => speedOfOpeningOrLocking; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| speedOfOpeningOrLocking = value; | |||
| } | |||
| } | |||
| } | |||
| private int speedOfClimbingThroughWindows; | |||
| private readonly int speedOfClimbingThroughWindows; | |||
| public int SpeedOfClimbingThroughWindows | |||
| { | |||
| get => speedOfClimbingThroughWindows; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| speedOfClimbingThroughWindows = value; | |||
| } | |||
| } | |||
| } | |||
| private int speedOfOpenChest; | |||
| private readonly int speedOfOpenChest; | |||
| public int SpeedOfOpenChest | |||
| { | |||
| get => speedOfOpenChest; | |||
| set | |||
| { | |||
| lock (gameObjLock) | |||
| { | |||
| speedOfOpenChest = value; | |||
| } | |||
| } | |||
| } | |||
| #endregion | |||
| #region 血量相关的基本属性及方法 | |||
| @@ -25,7 +25,7 @@ namespace GameClass.GameObj | |||
| public Character? WhoOpen => whoOpen; | |||
| public bool Open(Character character) | |||
| { | |||
| lock (GameObjReaderWriterLock) | |||
| lock (gameObjLock) | |||
| { | |||
| if (whoOpen != null) return false; | |||
| openStartTime = Environment.TickCount64; | |||
| @@ -35,7 +35,7 @@ namespace GameClass.GameObj | |||
| } | |||
| public void StopOpen() | |||
| { | |||
| lock (GameObjReaderWriterLock) | |||
| lock (gameObjLock) | |||
| { | |||
| whoOpen = null; | |||
| } | |||
| @@ -98,6 +98,7 @@ namespace GameClass.GameObj | |||
| if (whoLockOrOpen != null) | |||
| { | |||
| if ((Environment.TickCount64 - openStartTime) >= GameData.degreeOfLockingOrOpeningTheDoor / whoLockOrOpen.SpeedOfOpeningOrLocking) | |||
| //现在框架没有问题,但是调用可变的SpeedOfOpeningOrLocking可能死锁 | |||
| isOpen = true; | |||
| whoLockOrOpen = null; | |||
| } | |||
| @@ -21,7 +21,7 @@ namespace GameClass.GameObj | |||
| uint value = Interlocked.Increment(ref numOfRepairedGenerators); | |||
| if (value == GameData.numOfGeneratorRequiredForEmergencyExit) | |||
| { | |||
| GameObjLockDict[GameObjType.EmergencyExit].EnterWriteLock(); | |||
| GameObjLockDict[GameObjType.EmergencyExit].EnterReadLock(); | |||
| try | |||
| { | |||
| Random r = new Random(Environment.TickCount); | |||
| @@ -31,13 +31,13 @@ namespace GameClass.GameObj | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[GameObjType.EmergencyExit].ExitWriteLock(); | |||
| GameObjLockDict[GameObjType.EmergencyExit].ExitReadLock(); | |||
| } | |||
| } | |||
| else | |||
| if (value == GameData.numOfGeneratorRequiredForRepair) | |||
| { | |||
| GameObjLockDict[GameObjType.Doorway].EnterWriteLock(); | |||
| GameObjLockDict[GameObjType.Doorway].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (Doorway doorway in GameObjDict[GameObjType.Doorway]) | |||
| @@ -45,7 +45,7 @@ namespace GameClass.GameObj | |||
| } | |||
| finally | |||
| { | |||
| GameObjLockDict[GameObjType.Doorway].ExitWriteLock(); | |||
| GameObjLockDict[GameObjType.Doorway].ExitReadLock(); | |||
| } | |||
| } | |||
| } | |||
| @@ -52,14 +52,7 @@ namespace Gaming | |||
| { | |||
| moveEngine.MoveObj(playerToMove, moveTimeInMilliseconds, moveDirection, playerToMove.StateNum); | |||
| Thread.Sleep(moveTimeInMilliseconds); | |||
| lock (playerToMove.ActionLock) | |||
| { | |||
| lock (playerToMove.ActionLock) | |||
| { | |||
| if (stateNum == playerToMove.StateNum) | |||
| playerToMove.SetPlayerStateNaturally(); | |||
| } | |||
| } | |||
| playerToMove.ResetPlayerState(stateNum); | |||
| } | |||
| } | |||
| ) | |||
| @@ -664,7 +657,7 @@ namespace Gaming | |||
| } | |||
| break; | |||
| case GameObjType.Character: | |||
| if (player.FindActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed == 1 && ((Character)collisionObj).IsGhost()) | |||
| if (player.FindActiveSkill(ActiveSkillType.CanBeginToCharge).IsBeingUsed && ((Character)collisionObj).IsGhost()) | |||
| { | |||
| if (CharacterManager.BeStunned((Character)collisionObj, GameData.timeOfGhostStunnedWhenCharge) > 0) | |||
| player.AddScore(GameData.StudentScoreTrickerBeStunned(GameData.timeOfGhostStunnedWhenCharge)); | |||
| @@ -281,7 +281,7 @@ namespace Gaming | |||
| { | |||
| if (!gameMap.Timer.IsGaming) | |||
| return; | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterWriteLock(); | |||
| gameMap.GameObjLockDict[GameObjType.Character].EnterReadLock(); | |||
| try | |||
| { | |||
| foreach (Character player in gameMap.GameObjDict[GameObjType.Character]) | |||
| @@ -291,7 +291,7 @@ namespace Gaming | |||
| } | |||
| finally | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Character].ExitWriteLock(); | |||
| gameMap.GameObjLockDict[GameObjType.Character].ExitReadLock(); | |||
| } | |||
| } | |||
| @@ -142,7 +142,7 @@ namespace Gaming | |||
| int len = availableCellForGenerateProp.Count; | |||
| Random r = new Random(Environment.TickCount); | |||
| gameMap.GameObjLockDict[GameObjType.Chest].EnterWriteLock(); | |||
| gameMap.GameObjLockDict[GameObjType.Chest].EnterReadLock(); | |||
| try | |||
| { | |||
| int cou = 0; | |||
| @@ -181,7 +181,7 @@ namespace Gaming | |||
| } | |||
| finally | |||
| { | |||
| gameMap.GameObjLockDict[GameObjType.Chest].ExitWriteLock(); | |||
| gameMap.GameObjLockDict[GameObjType.Chest].ExitReadLock(); | |||
| } | |||
| /* | |||
| new Thread | |||
| @@ -505,11 +505,11 @@ namespace Gaming | |||
| (() => | |||
| { | |||
| startSkill(); | |||
| activeSkill.IsBeingUsed = 1; | |||
| activeSkill.IsBeingUsed = true; | |||
| Thread.Sleep(activeSkill.DurationTime); | |||
| endSkill(); | |||
| activeSkill.IsBeingUsed = 0; | |||
| activeSkill.IsBeingUsed = false; | |||
| Debugger.Output(player, "return to normal."); | |||
| } | |||
| ) | |||
| @@ -16,7 +16,7 @@ namespace Preparation.Interface | |||
| public int SkillCD { get; } | |||
| public int DurationTime { get; } //技能持续时间 | |||
| public object ActiveSkillUseLock { get; } | |||
| public int IsBeingUsed { get; set; } | |||
| public bool IsBeingUsed { get; set; } | |||
| } | |||
| public abstract class ActiveSkill : IActiveSkill | |||
| @@ -53,10 +53,10 @@ namespace Preparation.Interface | |||
| } | |||
| public int isBeingUsed = 0;//实为bool | |||
| public int IsBeingUsed | |||
| public bool IsBeingUsed | |||
| { | |||
| get => Interlocked.CompareExchange(ref isBeingUsed, 0, 0); | |||
| set => Interlocked.Exchange(ref isBeingUsed, value); | |||
| get => (Interlocked.CompareExchange(ref isBeingUsed, -1, -1) == 1); | |||
| set => Interlocked.Exchange(ref isBeingUsed, value ? 1 : 0); | |||
| } | |||
| } | |||
| @@ -74,5 +74,8 @@ namespace Server | |||
| [Option("startLockFile", Required = false, HelpText = "Whether to create a file that identifies whether the game has started")] | |||
| public string StartLockFile { get; set; } = DefaultArgumentOptions.FileName; | |||
| [Option("mode", Required = false, HelpText = "Whether to run final competition")] | |||
| public int Mode { get; set; } = 0; | |||
| } | |||
| } | |||
| } | |||
| @@ -102,10 +102,9 @@ namespace Server | |||
| } | |||
| } | |||
| } | |||
| protected void SendGameResult() // 天梯的 Server 给网站发消息记录比赛结果 | |||
| protected void SendGameResult(int[] scores, int mode) // 天梯的 Server 给网站发消息记录比赛结果 | |||
| { | |||
| int[] scores = GetScore(); | |||
| httpSender?.SendHttpRequest(scores).Wait(); | |||
| httpSender?.SendHttpRequest(scores, mode).Wait(); | |||
| } | |||
| private void OnGameEnd() | |||
| @@ -114,7 +113,8 @@ namespace Server | |||
| mwr?.Flush(); | |||
| if (options.ResultFileName != DefaultArgumentOptions.FileName) | |||
| SaveGameResult(options.ResultFileName.EndsWith(".json") ? options.ResultFileName : options.ResultFileName + ".json"); | |||
| SendGameResult(); | |||
| int[] scores = GetScore(); | |||
| SendGameResult(scores, options.Mode); | |||
| this.endGameSem.Release(); | |||
| } | |||
| public void ReportGame(GameState gameState, bool requiredGaming = true) | |||
| @@ -20,7 +20,7 @@ namespace Server | |||
| // { | |||
| // this.SendHttpRequest(new()).Wait(); | |||
| // } | |||
| public async Task SendHttpRequest(int[] scores) | |||
| public async Task SendHttpRequest(int[] scores, int mode) | |||
| { | |||
| try | |||
| { | |||
| @@ -33,7 +33,7 @@ namespace Server | |||
| new TeamScore() { team_id = 0, score = scores[0], }, | |||
| new TeamScore() { team_id = 1, score = scores[1], }, | |||
| }, | |||
| mode = 0 | |||
| mode = mode | |||
| }))) | |||
| { | |||
| Console.WriteLine("Send to web successfully!"); | |||
| @@ -1,3 +1,2 @@ | |||
| @echo off | |||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --port 8891 --characterId 2087 --ip thuai6.eesast.com | |||
| start cmd /k ..\Client\bin\Debug\net6.0-windows\Client.exe --port 8894 --characterID 123321123 --type 1 --occupation 1 --ip thuai6.eesast.com --cl | |||