From cd65ab8a9e0ea031d81312b38f5ecf0c31d466fd Mon Sep 17 00:00:00 2001
From: shangfengh <3495281661@qq.com>
Date: Tue, 16 May 2023 23:42:23 +0800
Subject: [PATCH] refactor: :construction: refactor the fuctions of LockDoor
and OpenDoor
---
docs/GameRules.md | 1 +
.../GameClass/GameObj/Character/Character.cs | 95 ++++++++--
logic/GameClass/GameObj/Map/Door.cs | 119 +++++++++++--
logic/Gaming/ActionManager.cs | 164 ++++++++++++------
logic/Gaming/Game.cs | 15 +-
logic/Gaming/PropManager.cs | 2 +-
.../SkillManager/SkillManager.ActiveSkill.cs | 4 +-
logic/Preparation/Utility/EnumType.cs | 3 +-
logic/Preparation/Utility/Transformation.cs | 3 +-
logic/Server/CopyInfo.cs | 2 +-
logic/Server/RpcServices.cs | 4 +-
11 files changed, 328 insertions(+), 84 deletions(-)
diff --git a/docs/GameRules.md b/docs/GameRules.md
index b2fe500..2108843 100644
--- a/docs/GameRules.md
+++ b/docs/GameRules.md
@@ -316,6 +316,7 @@ $$
### 道具
- 使用钥匙相当于销毁
+ - 可接受指令状态下能捡起或扔道具,在场上即可使用道具
### 交互
- 被唤醒或被勉励不属于交互状态,翻窗属于交互状态
diff --git a/logic/GameClass/GameObj/Character/Character.cs b/logic/GameClass/GameObj/Character/Character.cs
index 1d6ab0e..10e9523 100644
--- a/logic/GameClass/GameObj/Character/Character.cs
+++ b/logic/GameClass/GameObj/Character/Character.cs
@@ -341,12 +341,14 @@ namespace GameClass.GameObj
set
{
lock (vampireLock)
+ {
if (value > 1)
vampire = 1;
else if (value < 0)
vampire = 0;
else
vampire = value;
+ }
}
}
public double OriVampire { get; protected set; }
@@ -394,7 +396,8 @@ namespace GameClass.GameObj
{
lock (actionLock)
{
- return (playerState == PlayerStateType.LockingOrOpeningTheDoor || playerState == PlayerStateType.Fixing || playerState == PlayerStateType.OpeningTheChest);
+ return (playerState == PlayerStateType.LockingTheDoor || playerState == PlayerStateType.OpeningTheDoor
+ || playerState == PlayerStateType.Fixing || playerState == PlayerStateType.OpeningTheChest);
}
}
public bool NullOrMoving()
@@ -465,41 +468,75 @@ namespace GameClass.GameObj
else return -1;
case PlayerStateType.TryingToAttack:
- if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows)
+ if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows
+ && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor)
return ChangePlayerState(value, gameObj);
else return -1;
case PlayerStateType.Stunned:
case PlayerStateType.Charmed:
- if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows && value != PlayerStateType.Swinging)
+ if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows
+ && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor
+ && value != PlayerStateType.Swinging)
return ChangePlayerState(value, gameObj);
else return -1;
case PlayerStateType.Swinging:
- if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows)
+ if (value != PlayerStateType.Moving && value != PlayerStateType.ClimbingThroughWindows
+ && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor)
{
- ThreadNum.Release();
- return ChangePlayerState(value, gameObj);
+ try
+ {
+ return ChangePlayerState(value, gameObj);
+ }
+ finally
+ {
+ ThreadNum.Release();
+ }
}
else return -1;
case PlayerStateType.ClimbingThroughWindows:
- if (value != PlayerStateType.Moving)
+ if (value != PlayerStateType.Moving && value != PlayerStateType.LockingTheDoor && value != PlayerStateType.OpeningTheDoor)
{
Window window = (Window)WhatInteractingWith!;
- window.FinishClimbing();
- if (window.Stage.x == 0)
- ThreadNum.Release();
- else ReSetPos(window.Stage);
- return ChangePlayerState(value, gameObj);
+ try
+ {
+ window.FinishClimbing();
+ return ChangePlayerState(value, gameObj);
+ }
+ finally
+ {
+ if (window.Stage.x == 0)
+ ThreadNum.Release();
+ else ReSetPos(window.Stage);
+ }
}
else return -1;
case PlayerStateType.OpeningTheChest:
- ((Chest)WhatInteractingWith!).StopOpen();
+ ((Chest)whatInteractingWith!).StopOpen();
return ChangePlayerState(value, gameObj);
case PlayerStateType.OpeningTheDoorway:
- Doorway doorway = (Doorway)WhatInteractingWith!;
+ Doorway doorway = (Doorway)whatInteractingWith!;
doorway.StopOpenning();
return ChangePlayerState(value, gameObj);
+ case PlayerStateType.OpeningTheDoor:
+ Door door = (Door)whatInteractingWith!;
+ try
+ {
+ door.StopOpen();
+ ReleaseTool(door.DoorNum switch
+ {
+ 3 => PropType.Key3,
+ 5 => PropType.Key5,
+ _ => PropType.Key6,
+ }
+ );
+ return ChangePlayerState(value, gameObj);
+ }
+ finally
+ {
+ ThreadNum.Release();
+ }
default:
return ChangePlayerState(value, gameObj);
}
@@ -638,6 +675,36 @@ namespace GameClass.GameObj
return new NullProp();
}
+ public bool UseTool(PropType propType)
+ {
+ lock (inventoryLock)
+ {
+ for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing)
+ {
+ if (PropInventory[indexing].GetPropType() == propType && PropInventory[indexing].IsUsable())
+ {
+ return ((Tool)PropInventory[indexing]).IsUsed = true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void ReleaseTool(PropType propType)
+ {
+ lock (inventoryLock)
+ {
+ for (int indexing = 0; indexing < GameData.maxNumOfPropInPropInventory; ++indexing)
+ {
+ if (PropInventory[indexing].GetPropType() == propType && ((Tool)PropInventory[indexing]).IsUsed)
+ {
+ ((Tool)PropInventory[indexing]).IsUsed = false;
+ break;
+ }
+ }
+ }
+ }
+
///
/// 如果indexing==GameData.maxNumOfPropInPropInventory表明道具栏为满
///
diff --git a/logic/GameClass/GameObj/Map/Door.cs b/logic/GameClass/GameObj/Map/Door.cs
index 2410421..5955a57 100644
--- a/logic/GameClass/GameObj/Map/Door.cs
+++ b/logic/GameClass/GameObj/Map/Door.cs
@@ -1,5 +1,7 @@
using Preparation.Interface;
using Preparation.Utility;
+using System;
+using System.Threading;
namespace GameClass.GameObj
{
@@ -32,30 +34,123 @@ namespace GameClass.GameObj
public override bool IsRigid => !isOpen;
public override ShapeType Shape => ShapeType.Square;
+ private Character? whoLockOrOpen = null;
+ public Character? WhoLockOrOpen
+ {
+ get
+ {
+ lock (gameObjLock)
+ return whoLockOrOpen;
+ }
+ }
+
private bool isOpen = true;
public bool IsOpen
{
- get => isOpen;
- set
+ get
{
lock (gameObjLock)
- isOpen = value;
+ return isOpen;
}
}
- private int openOrLockDegree = 0;
- public int OpenOrLockDegree
+ private int lockDegree = 0;
+ public int LockDegree
{
- get => openOrLockDegree;
+ get
+ {
+ lock (gameObjLock)
+ return lockDegree;
+ }
set
{
- if (value > 0)
- lock (gameObjLock)
- openOrLockDegree = (value > GameData.degreeOfLockingOrOpeningTheDoor) ? GameData.degreeOfLockingOrOpeningTheDoor : value;
- else
- lock (gameObjLock)
- openOrLockDegree = 0;
+ value = (value > GameData.degreeOfLockingOrOpeningTheDoor) ? GameData.degreeOfLockingOrOpeningTheDoor : value;
+ lock (gameObjLock)
+ lockDegree = value;
+ }
+ }
+
+ private long openStartTime = 0;
+ public long OpenStartTime
+ {
+ get
+ {
+ lock (gameObjLock)
+ return openStartTime;
+ }
+ }
+
+ public bool TryOpen(Character character)
+ {
+ lock (gameObjLock)
+ {
+ if (isOpen) return false;
+ if (whoLockOrOpen != null) return false;
+ openStartTime = Environment.TickCount64;
+ whoLockOrOpen = character;
+ return true;
+ }
+ }
+ public void StopOpen()
+ {
+ lock (gameObjLock)
+ {
+ if (whoLockOrOpen != null)
+ {
+ if (Environment.TickCount64 - openStartTime >= GameData.degreeOfLockingOrOpeningTheDoor)
+ isOpen = true;
+ whoLockOrOpen = null;
+ }
+ }
+ }
+ public void FinishOpen()
+ {
+ lock (gameObjLock)
+ {
+ isOpen = true;
+ whoLockOrOpen = null;
+ }
+ }
+
+ public bool TryLock(Character character)
+ {
+ lock (gameObjLock)
+ {
+ if (!isOpen) return false;
+ if (whoLockOrOpen != null) return false;
+ lockDegree = 0;
+ whoLockOrOpen = character;
+ return true;
+ }
+ }
+ public void StopLock()
+ {
+ lock (gameObjLock)
+ {
+ if (lockDegree >= GameData.degreeOfLockingOrOpeningTheDoor)
+ isOpen = true;
+ whoLockOrOpen = null;
+ }
+ }
+ public void FinishLock()
+ {
+ lock (gameObjLock)
+ {
+ isOpen = false;
+ whoLockOrOpen = null;
+ }
+ }
+
+ public void ForceToOpen()
+ {
+ Character? character;
+ lock (gameObjLock)
+ {
+ character = whoLockOrOpen;
+ whoLockOrOpen = null;
+ isOpen = true;
}
+ if (character != null) character.SetPlayerState();
}
}
}
diff --git a/logic/Gaming/ActionManager.cs b/logic/Gaming/ActionManager.cs
index 278e04d..faec44b 100644
--- a/logic/Gaming/ActionManager.cs
+++ b/logic/Gaming/ActionManager.cs
@@ -389,67 +389,133 @@ namespace Gaming
return true;
}
- public bool LockOrOpenDoor(Character player)
+ public bool LockDoor(Character player)
{
if (player.CharacterType == CharacterType.Robot) return false;
Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door);
if (doorToLock == null) return false;
- bool flag = false;
- foreach (Gadget prop in player.PropInventory)
+
+ PropType propType = doorToLock.DoorNum switch
+ {
+ 3 => PropType.Key3,
+ 5 => PropType.Key5,
+ _ => PropType.Key6,
+ };
+
+ if (!player.UseTool(propType)) return false;
+
+ long stateNum = player.SetPlayerState(PlayerStateType.LockingTheDoor, doorToLock);
+ if (stateNum == -1)
{
- switch (prop.GetPropType())
+ player.ReleaseTool(propType);
+ return false;
+ }
+
+ new Thread
+ (
+ () =>
{
- case PropType.Key3:
- if (doorToLock.DoorNum == 3)
- flag = true;
- break;
- case PropType.Key5:
- if (doorToLock.DoorNum == 5)
- flag = true;
- break;
- case PropType.Key6:
- if (doorToLock.DoorNum == 6)
- flag = true;
- break;
- default:
- break;
+ player.ThreadNum.WaitOne();
+ if (stateNum != player.StateNum)
+ {
+ player.ReleaseTool(propType);
+ player.ThreadNum.Release();
+ }
+ else
+ {
+ if (!doorToLock.TryLock(player))
+ {
+ player.ReleaseTool(propType);
+ player.SetPlayerState();
+ player.ThreadNum.Release();
+ }
+ else
+ {
+ Thread.Sleep(GameData.checkInterval);
+ new FrameRateTaskExecutor(
+ loopCondition: () => stateNum == player.StateNum && gameMap.Timer.IsGaming && doorToLock.LockDegree < GameData.degreeOfLockingOrOpeningTheDoor,
+ loopToDo: () =>
+ {
+ if ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) != null)
+ return false;
+ doorToLock.LockDegree += GameData.checkInterval * player.SpeedOfOpeningOrLocking;
+ return true;
+ },
+ timeInterval: GameData.checkInterval,
+ finallyReturn: () => 0
+ )
+ .Start();
+ doorToLock.StopLock();
+ if (stateNum == player.StateNum) player.SetPlayerState();
+ player.ReleaseTool(propType);
+ player.ThreadNum.Release();
+ }
+ }
}
- if (flag) break;
- }
- if (!flag) return false;
+ )
+ { IsBackground = true }.Start();
- if (doorToLock.OpenOrLockDegree > 0 || gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character) != null)
- return false;
- if (!(player.Commandable()) || player.PlayerState == PlayerStateType.LockingOrOpeningTheDoor)
+ return true;
+ }
+
+ public bool OpenDoor(Character player)
+ {
+ if (player.CharacterType == CharacterType.Robot) return false;
+ Door? doorToLock = (Door?)gameMap.OneForInteract(player.Position, GameObjType.Door);
+ if (doorToLock == null) return false;
+
+ PropType propType = doorToLock.DoorNum switch
+ {
+ 3 => PropType.Key3,
+ 5 => PropType.Key5,
+ _ => PropType.Key6,
+ };
+
+ if (!player.UseTool(propType)) return false;
+
+ long stateNum = player.SetPlayerState(PlayerStateType.OpeningTheDoor, doorToLock);
+ if (stateNum == -1)
+ {
+ player.ReleaseTool(propType);
return false;
+ }
- player.SetPlayerState(PlayerStateType.LockingOrOpeningTheDoor);
- long threadNum = player.StateNum;
new Thread
- (
- () =>
- {
- new FrameRateTaskExecutor(
- loopCondition: () => flag && threadNum == player.StateNum && gameMap.Timer.IsGaming && doorToLock.OpenOrLockDegree < GameData.degreeOfLockingOrOpeningTheDoor,
- loopToDo: () =>
- {
- flag = ((gameMap.PartInTheSameCell(doorToLock.Position, GameObjType.Character)) == null);
- doorToLock.OpenOrLockDegree += GameData.frameDuration * player.SpeedOfOpeningOrLocking;
- },
- timeInterval: GameData.frameDuration,
- finallyReturn: () => 0
- )
- .Start();
- if (doorToLock.OpenOrLockDegree >= GameData.degreeOfLockingOrOpeningTheDoor)
- {
- doorToLock.IsOpen = (!doorToLock.IsOpen);
- }
- if (threadNum == player.StateNum)
- player.SetPlayerState();
- doorToLock.OpenOrLockDegree = 0;
- }
+ (
+ () =>
+ {
+ player.ThreadNum.WaitOne();
+ if (stateNum != player.StateNum)
+ {
+ player.ReleaseTool(propType);
+ player.ThreadNum.Release();
+ }
+ else
+ {
+ if (!doorToLock.TryOpen(player))
+ {
+ player.ReleaseTool(propType);
+ player.SetPlayerState();
+ player.ThreadNum.Release();
+ }
+ else
+ {
+ Thread.Sleep(GameData.degreeOfLockingOrOpeningTheDoor / player.SpeedOfOpeningOrLocking);
- )
+ lock (player.ActionLock)
+ {
+ if (stateNum == player.StateNum)
+ {
+ player.SetPlayerState();
+ doorToLock.StopOpen();
+ player.ReleaseTool(propType);
+ player.ThreadNum.Release();
+ }
+ }
+ }
+ }
+ }
+ )
{ IsBackground = true }.Start();
return true;
diff --git a/logic/Gaming/Game.cs b/logic/Gaming/Game.cs
index 84074e2..8a973c9 100644
--- a/logic/Gaming/Game.cs
+++ b/logic/Gaming/Game.cs
@@ -197,14 +197,25 @@ namespace Gaming
}
return false;
}
- public bool LockOrOpenDoor(long playerID)
+ public bool LockDoor(long playerID)
{
if (!gameMap.Timer.IsGaming)
return false;
Character? player = gameMap.FindPlayerToAction(playerID);
if (player != null)
{
- return actionManager.LockOrOpenDoor(player);
+ return actionManager.LockDoor(player);
+ }
+ return false;
+ }
+ public bool OpenDoor(long playerID)
+ {
+ if (!gameMap.Timer.IsGaming)
+ return false;
+ Character? player = gameMap.FindPlayerToAction(playerID);
+ if (player != null)
+ {
+ return actionManager.OpenDoor(player);
}
return false;
}
diff --git a/logic/Gaming/PropManager.cs b/logic/Gaming/PropManager.cs
index abb5866..3481cd0 100644
--- a/logic/Gaming/PropManager.cs
+++ b/logic/Gaming/PropManager.cs
@@ -21,7 +21,7 @@ namespace Gaming
public void UseProp(Character player, PropType propType)
{
- if (player.IsRemoved || player.CharacterType == CharacterType.Robot)
+ if (player.CharacterType == CharacterType.Robot || player.IsRemoved)
return;
Gadget prop = player.UseProp(propType);
switch (prop.GetPropType())
diff --git a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
index b9b5d7a..fccac32 100644
--- a/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
+++ b/logic/Gaming/SkillManager/SkillManager.ActiveSkill.cs
@@ -216,7 +216,9 @@ namespace Gaming
{
if (character.IsGhost() &&
(character.PlayerState == PlayerStateType.TryingToAttack || character.PlayerState == PlayerStateType.Swinging
- || character.PlayerState == PlayerStateType.UsingSkill || character.PlayerState == PlayerStateType.LockingOrOpeningTheDoor || character.PlayerState == PlayerStateType.ClimbingThroughWindows)
+ || character.PlayerState == PlayerStateType.UsingSkill
+ || character.PlayerState == PlayerStateType.LockingTheDoor || character.PlayerState == PlayerStateType.OpeningTheDoor
+ || character.PlayerState == PlayerStateType.ClimbingThroughWindows)
&& gameMap.CanSee(player, character))
{
if (characterManager.BeStunned(character, GameData.timeOfGhostStunnedWhenPunish + GameData.factorOfTimeStunnedWhenPunish * (player.MaxHp - player.HP)) > 0)
diff --git a/logic/Preparation/Utility/EnumType.cs b/logic/Preparation/Utility/EnumType.cs
index 5809d85..0608e60 100644
--- a/logic/Preparation/Utility/EnumType.cs
+++ b/logic/Preparation/Utility/EnumType.cs
@@ -19,12 +19,13 @@ namespace Preparation.Utility
Rescued = 10,
Stunned = 11,
TryingToAttack = 12,//指前摇
- LockingOrOpeningTheDoor = 13,
+ LockingTheDoor = 13,
OpeningTheChest = 14,
ClimbingThroughWindows = 15,
UsingSkill = 16,
OpeningTheDoorway = 17,
Charmed = 18,
+ OpeningTheDoor = 19,
}
public enum GameObjType
{
diff --git a/logic/Preparation/Utility/Transformation.cs b/logic/Preparation/Utility/Transformation.cs
index 0a997be..e5ad6fd 100644
--- a/logic/Preparation/Utility/Transformation.cs
+++ b/logic/Preparation/Utility/Transformation.cs
@@ -107,7 +107,8 @@ namespace Preparation.Utility
return PlayerState.Graduated;
case Preparation.Utility.PlayerStateType.Fixing:
return PlayerState.Learning;
- case Preparation.Utility.PlayerStateType.LockingOrOpeningTheDoor:
+ case Preparation.Utility.PlayerStateType.LockingTheDoor:
+ case PlayerStateType.OpeningTheDoor:
return PlayerState.Locking;
case Preparation.Utility.PlayerStateType.OpeningTheChest:
return PlayerState.OpeningAChest;
diff --git a/logic/Server/CopyInfo.cs b/logic/Server/CopyInfo.cs
index 470b479..a4b9030 100644
--- a/logic/Server/CopyInfo.cs
+++ b/logic/Server/CopyInfo.cs
@@ -256,7 +256,7 @@ namespace Server
{
X = door.Position.x,
Y = door.Position.y,
- Progress = door.OpenOrLockDegree,
+ Progress = door.LockDegree,
IsOpen = door.IsOpen
}
};
diff --git a/logic/Server/RpcServices.cs b/logic/Server/RpcServices.cs
index 31ea12b..f624250 100644
--- a/logic/Server/RpcServices.cs
+++ b/logic/Server/RpcServices.cs
@@ -471,7 +471,7 @@ namespace Server
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
- boolRes.ActSuccess = game.LockOrOpenDoor(gameID);
+ boolRes.ActSuccess = game.OpenDoor(gameID);
return Task.FromResult(boolRes);
}
@@ -487,7 +487,7 @@ namespace Server
return Task.FromResult(boolRes);
}
var gameID = communicationToGameID[request.PlayerId];
- boolRes.ActSuccess = game.LockOrOpenDoor(gameID);
+ boolRes.ActSuccess = game.LockDoor(gameID);
return Task.FromResult(boolRes);
}