Browse Source

chore: 🚀 start

start
tags/0.1.0
gsy1519 3 years ago
parent
commit
bc12e302fe
11 changed files with 72 additions and 372 deletions
  1. +3
    -1
      dependency/proto/Protos.csproj
  2. +1
    -1
      logic/ClientTest/ClientTest.csproj
  3. +1
    -1
      logic/ClientTest/Program.cs
  4. +0
    -125
      logic/Protos/Message2Clients.proto
  5. +0
    -62
      logic/Protos/Message2Server.proto
  6. +0
    -110
      logic/Protos/MessageType.proto
  7. +29
    -30
      logic/Server/Game.cs
  8. +30
    -33
      logic/Server/GameServer.cs
  9. +1
    -2
      logic/Server/Program.cs
  10. +1
    -1
      logic/Server/Server.csproj
  11. +6
    -6
      logic/logic.sln

logic/Protos/Protos.csproj → dependency/proto/Protos.csproj View File

@@ -10,11 +10,12 @@
<None Remove="Message2Clients.proto" />
<None Remove="Message2Server.proto" />
<None Remove="MessageType.proto" />
<None Remove="Services.proto" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="FrameRateTask" Version="1.1.2" />
<PackageReference Include="Google.Protobuf" Version="3.21.9" />
<PackageReference Include="Google.Protobuf.Tools" Version="3.21.9" />
<PackageReference Include="Grpc" Version="2.46.5" />
<PackageReference Include="Grpc.Core" Version="2.46.5" />
<PackageReference Include="Grpc.Tools" Version="2.50.0">
@@ -27,6 +28,7 @@
<Protobuf Include="Message2Clients.proto" />
<Protobuf Include="Message2Server.proto" />
<Protobuf Include="MessageType.proto" />
<Protobuf Include="Services.proto" />
</ItemGroup>

</Project>

+ 1
- 1
logic/ClientTest/ClientTest.csproj View File

@@ -14,7 +14,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Protos\Protos.csproj" />
<ProjectReference Include="..\..\dependency\proto\Protos.csproj" />
</ItemGroup>

</Project>

+ 1
- 1
logic/ClientTest/Program.cs View File

@@ -7,7 +7,7 @@ namespace ClientTest
{
public static async Task Main(string[] args)
{
Channel channel = new Channel("127.0.0.1:8888", ChannelCredentials.Insecure);
Channel channel = new Channel("0.0.0.0:8888", ChannelCredentials.Insecure);
var client = new AvailableService.AvailableServiceClient(channel);
PlayerMsg playerInfo = new();
playerInfo.PlayerId = Convert.ToInt32(args[0]);


+ 0
- 125
logic/Protos/Message2Clients.proto View File

@@ -1,125 +0,0 @@
// Message2Client
syntax = "proto3";
package protobuf;

import "MessageType.proto";
import "Message2Server.proto";

message MessageOfHuman
{
int32 x = 1;
int32 y = 2;
int32 speed = 3;
int32 life = 4; // 本次未倒地前的血量,也即还可以受的伤害
int32 hanged_time = 5; // 被挂上的次数
double time_until_skill_available = 6;
PlaceType place = 7;
PropType prop = 8;
HumanType human_type = 9;
int64 guid = 10;
bool on_chair = 11; // 是否被挂
double chair_time = 12; // 被挂的时间
bool on_ground = 13; // 是否倒地
double ground_time = 14; // 倒地时间
int64 player_id = 15;
int32 view_range = 16; // 视野距离
repeated HumanBuffType buff = 17;
}

message MessageOfButcher
{
int32 x = 1;
int32 y = 2;
int32 speed = 3;
int32 damage = 4;
double time_until_skill_available = 5;
PlaceType place = 6;
PropType prop = 7;
ButcherType butcher_type = 8;
int64 guid = 9;
bool movable = 10; // 是否进入了攻击后摇
int64 playerID = 11;
int32 view_range = 12; // 视野距离
repeated ButcherBuffType buff = 13;
}

message MessageOfProp // 可拾取道具的信息
{
PropType type = 1;
int32 x = 2;
int32 y = 3;
double facing_direction = 4;
int64 guid = 5;
PlaceType place = 6;
int32 size = 7;
bool is_moving = 8;
}

message MessageOfPickedProp //for Unity,直接继承自THUAI5
{
PropType type = 1;
int32 x = 2;
int32 y = 3;
double facing_direction = 4;
int64 mapping_id = 5;
}

message MessageOfMap
{
message Row
{
repeated PlaceType col = 1;
}
repeated Row row = 2;
}

message MessageToClient
{
repeated MessageOfHuman human_message = 1;
repeated MessageOfButcher butcher_message = 2; // 是否真正repeated待定
repeated MessageOfProp prop_message = 3;
MessageOfMap map_massage = 4;
}

message MoveRes // 如果打算设计撞墙保留平行速度分量,且需要返回值则可用这个(大概没啥用)
{
int64 actual_speed = 1;
double actual_angle = 2;
}

message BoolRes // 用于只需要判断执行操作是否成功的行为,如捡起道具、使用道具
{
bool act_success = 1;
}

message MsgRes // 用于获取队友发来的消息
{
bool have_message = 1; // 是否有待接收的消息
int64 from_player_id = 2;
string message_received = 3;
}

service AvailableService
{
rpc TryConnection(IDMsg) returns(BoolRes);

// 游戏开局调用一次的服务
rpc AddPlayer(PlayerMsg) returns(stream MessageToClient); // 连接上后等待游戏开始,server会定时通过该服务向所有client发送消息。

// 游戏过程中玩家执行操作的服务
rpc Move(MoveMsg) returns (MoveRes);
rpc PickProp(PickMsg) returns (BoolRes);
rpc UseProp(IDMsg) returns (BoolRes);
rpc UseSkill(IDMsg) returns (BoolRes);
rpc SendMessage(SendMsg) returns (BoolRes);
rpc HaveMessage(IDMsg) returns (BoolRes);
rpc GetMessage(IDMsg) returns (MsgRes);
rpc FixMachine(stream IDMsg) returns (stream BoolRes); // 若正常修复且未被打断则返回修复成功,位置错误/被打断则返回修复失败,下同
rpc SaveHuman(stream IDMsg) returns (stream BoolRes);
rpc Attack (AttackMsg) returns (BoolRes);
rpc CarryHuman (IDMsg) returns (BoolRes);
rpc ReleaseHuman (IDMsg) returns (BoolRes);
rpc HangHuman (IDMsg) returns (BoolRes);
rpc Escape (IDMsg) returns (BoolRes);
}

+ 0
- 62
logic/Protos/Message2Server.proto View File

@@ -1,62 +0,0 @@
// Message2Server
syntax = "proto3";
package protobuf;

import "MessageType.proto";

message PlayerMsg
{
int64 player_id = 1;
PlayerType player_type = 2;
oneof job_type
{
HumanType human_type = 3;
ButcherType butcher_type = 4;
}
}

message MoveMsg
{
int64 player_id = 1;
double angle = 2;
int64 time_in_milliseconds = 3;
}

message PickMsg
{
int64 player_id = 1;
PropType prop_type = 2;
}

message SendMsg
{
int64 player_id = 1;
int64 to_player_id = 2;
string message = 3;
}

message AttackMsg
{
int64 player_id = 1;
double angle = 2;
}

message IDMsg
{
int64 player_id = 1;
}

// 基本继承于THUAI5,为了使发送的信息尽可能不被浪费,暂定不发这类大包。
// message MessageToServer
// {
// MessageType messageType = 1;
// int64 playerID = 2; // 消息发送者的playerID
// PlayerType playerType = 3;
// HumanType humanType= 4;
// ButcherType butcherType = 5;
// double angle = 6; // messageType为Move, Attack时的角度
// PropType propType = 7; // messageType为PickProp时要捡起的道具类型,防止多个道具堆叠时出现问题
// int64 timeInMilliseconds = 8;//时间参数
// int64 ToPlayerID = 9; // messageType为Send时要发送的对象的ID
// string message = 10; // messageType为Send时发送的消息内容
// }

+ 0
- 110
logic/Protos/MessageType.proto View File

@@ -1,110 +0,0 @@
// MessageType
syntax = "proto3";
package protobuf;

enum PlaceType // 地图中的所有物件类型
{
NULL_PLACE_TYPE = 0;
// 地图情况,其中Gate是总体的大门,HiddenGate是地窖
LAND = 1;
WALL = 2;
GRASS = 3;
MACHINE = 4;
GATE = 5;
HIDDEN_GATE = 6;
// 待补充有特殊效果的地形

}

enum ShapeType // 形状类型
{
NULL_SHAPE_TYPE = 0;
CIRCLE = 1; // 人类、屠夫、可拾取道具等为圆形
SQUARE = 2; // 地形均为方形
}

enum PropType // 地图中的可拾取道具类型
{
NULL_PROP_TYPE = 0;
PTYPE1 = 1;
PTYPE2 = 2;
PTYPE3 = 3;
PTYPE4 = 4;

}

enum HumanBuffType // 人类可用的增益效果类型
{
NULL_HBUFF_TYPE = 0;
HBUFFTYPE1 = 1;
HBUFFTYPE2 = 2;
HBUFFTYPE3 = 3;
HBUFFTYPE4 = 4;
}

enum ButcherBuffType // 屠夫可用的增益效果类型
{
NULL_BBUFF_TYPE = 0;
BBUFFTYPE1 = 1;
BBUFFTYPE2 = 2;
BBUFFTYPE3 = 3;
BBUFFTYPE4 = 4;
}

// 特别说明:由于Human阵营和Butcher阵营有显著的隔离,且暂定职业、主动技能和被动效果相互绑定,故不按照THUAI5的方式区分ActiveSkillType和PassiveSkillType,而是选择了按照阵营来给不同阵营赋予不同的职业(及技能)。

enum PlayerType
{
NULL_PLAYER_TYPE = 0;
HUMAN_PLAYER = 1;
BUTCHER_PLAYER = 2;
}

enum HumanType
{
NULL_HUMAN_TYPE = 0;
HUMANTYPE1 = 1;
HUMANTYPE2 = 2;
HUMANTYPE3 = 3;
HUMANTYPE4 = 4;
}

enum ButcherType
{
NULL_BUTCHER_TYPE = 0;
BUTCHERTYPE1 = 1;
BUTCHERTYPE2 = 2;
BUTCHERTYPE3 = 3;
BUTCHERTYPE4 = 4;
}

// 取消了大包之后,MessageType的枚举是否有必要保留还有待商榷
// enum MessageType
// {
// // 公共信息类型
// Move = 0;
// PickProp = 1;
// UseProp = 2;
// UseSkill = 3;
// Map = 4;
// Send = 5;

// // 人类限定信息类型
// FixMachine = 6;
// SaveHuman = 7;

// // 屠夫限定信息类型
// Attack = 8;
// CarryHuman = 9;
// ReleaseHuman = 10;
// HangHuman = 11;

// // 游戏相关信息类型
// AddPlayer = 12;
// InvalidPlayer = 13;
// ValidPlayer = 14;
// StartGame = 15;
// Gaming = 16;
// EndGame = 17;
// }

+ 29
- 30
logic/Server/Game.cs View File

@@ -18,7 +18,7 @@ namespace Server
public bool IsGaming
{
get => Interlocked.CompareExchange(ref isGaming, 0, 0) != 0;
set => Interlocked.Exchange(ref isGaming, value ? 1 : 0);
set => Interlocked.Exchange(ref isGaming, value? 1: 0);
}

public MessageToClient GetCopiedGameInfo()
@@ -32,19 +32,18 @@ namespace Server
{
lock (gameInfoLock)
{
if (player.PlayerType == PlayerType.NullPlayerType) return;
if (player.PlayerType == PlayerType.NullPlayerType)
return;
if (player.PlayerType == PlayerType.HumanPlayer)
{
gameInfo.HumanMessage.Add(new MessageOfHuman()
{
gameInfo.HumanMessage.Add(new MessageOfHuman() {
PlayerId = player.PlayerId
});
return;
}
if (player.PlayerType == PlayerType.ButcherPlayer)
{
gameInfo.ButcherMessage.Add(new MessageOfButcher()
{
gameInfo.ButcherMessage.Add(new MessageOfButcher() {
PlayerID = player.PlayerId
});
return;
@@ -66,39 +65,39 @@ namespace Server
() => IsGaming,
() =>
{
lock (gameInfo)
{
for (int i = 0; i < gameInfo.HumanMessage.Count; i++)
{
if (gameInfo.HumanMessage[i] != null)
{
gameInfo.HumanMessage[i].X++;
gameInfo.HumanMessage[i].Y--;
}
}
for (int i = 0; i < gameInfo.ButcherMessage.Count; i++)
{
if (gameInfo.ButcherMessage[i] != null)
{
gameInfo.ButcherMessage[i].X--;
gameInfo.ButcherMessage[i].Y++;
}
}
}
lock (gameInfo)
{
for (int i = 0; i < gameInfo.HumanMessage.Count; i++)
{
if (gameInfo.HumanMessage[i] != null)
{
gameInfo.HumanMessage[i].X++;
gameInfo.HumanMessage[i].Y--;
}
}
for (int i = 0; i < gameInfo.ButcherMessage.Count; i++)
{
if (gameInfo.ButcherMessage[i] != null)
{
gameInfo.ButcherMessage[i].X--;
gameInfo.ButcherMessage[i].Y++;
}
}
}
},
100,
() =>
{
IsGaming = false;
waitHandle.Release();
return 0;
IsGaming = false;
waitHandle.Release();
return 0;
},
gameTime
).Start();
}
}
)
{ IsBackground = true }.Start();
return waitHandle;
}
}
}
}

+ 30
- 33
logic/Server/GameServer.cs View File

@@ -11,7 +11,7 @@ namespace Server
{
private Dictionary<long, (SemaphoreSlim, SemaphoreSlim)> semaDict = new();
private object gameLock = new();
private const int playerNum = 2;
private const int playerNum = 1;
private MessageToClient currentGameInfo = new();
private Game game = new();
public int GameTime => game.GameTime;
@@ -22,11 +22,11 @@ namespace Server
var onConnection = new BoolRes();
lock (gameLock)
{
if (0 <= request.PlayerId && request.PlayerId < playerNum)
// if (0 <= request.PlayerId && request.PlayerId < playerNum)
{
onConnection.ActSuccess = true;
return Task.FromResult(onConnection);
}
}
}
onConnection.ActSuccess = false;
return Task.FromResult(onConnection);
@@ -53,13 +53,12 @@ namespace Server
{
Console.WriteLine("Game starts!");
StartGame();
}
}
}

do
{
semaDict[request.PlayerId].Item1.Wait();

if (currentGameInfo != null)
{
await responseStream.WriteAsync(currentGameInfo);
@@ -80,44 +79,42 @@ namespace Server
1000,
() =>
{
ReportGame(); // 最后发一次消息,唤醒发消息的线程,防止发消息的线程由于有概率处在 Wait 状态而卡住
return 0;
ReportGame(); // 最后发一次消息,唤醒发消息的线程,防止发消息的线程由于有概率处在 Wait 状态而卡住
return 0;
}
).Start();
})
})
{ IsBackground = true }.Start();
new Thread(() =>
{
waitHandle.Wait();
this.endGameSem.Release();
})
this.endGameSem.Release();
})
{ IsBackground = true }.Start();

}
public void WaitForEnd()
{
this.endGameSem.Wait();
}

}
public void WaitForEnd()
{
this.endGameSem.Wait();
}

public void ReportGame()
{
currentGameInfo = game.GetCopiedGameInfo();

foreach (var kvp in semaDict)
{
kvp.Value.Item1.Release();
}
public void ReportGame()
{
currentGameInfo = game.GetCopiedGameInfo();

foreach (var kvp in semaDict)
{
kvp.Value.Item2.Wait();
}
}
foreach (var kvp in semaDict)
{
kvp.Value.Item1.Release();
}

public GameServer()
{
foreach (var kvp in semaDict)
{
kvp.Value.Item2.Wait();
}
}

}
}
public GameServer()
{
}
}
}

+ 1
- 2
logic/Server/Program.cs View File

@@ -14,8 +14,7 @@ namespace Server
try
{
GameServer gameServer = new();
Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
{
Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) }) {
Services = { AvailableService.BindService(gameServer) },
Ports = { new ServerPort("0.0.0.0", 8888, ServerCredentials.Insecure) }
};


+ 1
- 1
logic/Server/Server.csproj View File

@@ -19,7 +19,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Protos\Protos.csproj" />
<ProjectReference Include="..\..\dependency\proto\Protos.csproj" />
</ItemGroup>

</Project>

+ 6
- 6
logic/logic.sln View File

@@ -5,9 +5,9 @@ VisualStudioVersion = 17.0.32014.148
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Server", "Server\Server.csproj", "{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "Protos\Protos.csproj", "{EA81EE05-A0E3-4D3E-8D7A-C5CD0C9255CD}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ClientTest", "ClientTest\ClientTest.csproj", "{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ClientTest", "ClientTest\ClientTest.csproj", "{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Protos", "..\dependency\proto\Protos.csproj", "{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -19,14 +19,14 @@ Global
{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D033B809-2FB7-4340-B8B4-DDA30D6CA6FF}.Release|Any CPU.Build.0 = Release|Any CPU
{EA81EE05-A0E3-4D3E-8D7A-C5CD0C9255CD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EA81EE05-A0E3-4D3E-8D7A-C5CD0C9255CD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EA81EE05-A0E3-4D3E-8D7A-C5CD0C9255CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EA81EE05-A0E3-4D3E-8D7A-C5CD0C9255CD}.Release|Any CPU.Build.0 = Release|Any CPU
{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3C98717-DD4F-45B8-B0F0-C217E7E2B5D4}.Release|Any CPU.Build.0 = Release|Any CPU
{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9ADA1EF8-DF2F-4C2E-9DE2-BC94DF89B44D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE


Loading…
Cancel
Save