Browse Source

Merge branch 'dev' of github.com:eesast/THUAI6 into dev

tags/0.1.0
gsy1519 2 years ago
parent
commit
de9038c86c
9 changed files with 279 additions and 21 deletions
  1. +50
    -9
      dependency/proto/Message2Clients.proto
  2. +1
    -1
      dependency/proto/Message2Server.proto
  3. +5
    -2
      dependency/proto/MessageType.proto
  4. +6
    -2
      dependency/proto/Services.proto
  5. +134
    -0
      playback/Playback/MessageReader.cs
  6. +74
    -0
      playback/Playback/MessageWriter.cs
  7. +0
    -6
      playback/Playback/Playback.cs
  8. +1
    -1
      playback/Playback/Playback.csproj
  9. +8
    -0
      playback/Playback/PlaybackConstant.cs

+ 50
- 9
dependency/proto/Message2Clients.proto View File

@@ -13,7 +13,7 @@ message MessageOfStudent
int32 fail_num = 5; // 挂科的科目数
double time_until_skill_available = 6;
PlaceType place = 7;
PropType prop = 8;
repeated PropType prop = 8;
StudentType student_type = 9;
int64 guid = 10;
StudentState state = 11;
@@ -34,7 +34,7 @@ message MessageOfTricker
int32 damage = 4; // 对学生造成的心理伤害
double time_until_skill_available = 5;
PlaceType place = 6;
PropType prop = 7;
repeated PropType prop = 7;
TrickerType tricker_type = 8;
int64 guid = 9;
bool movable = 10; // 是否进入了攻击后摇
@@ -88,6 +88,37 @@ message MessageOfPickedProp //for Unity,直接继承自THUAI5
int64 mapping_id = 5;
}

message MessageOfClassroom
{
int32 x = 1;
int32 y = 2;
int32 progress = 3;
}

message MessageOfGate
{
int32 x = 1;
int32 y = 2;
int32 progress = 3;
}

message MessageOfDoor
{
int32 x = 1;
int32 y = 2;
bool is_open = 3;
}

message MessageOfMapObj
{
oneof message_of_map_obj
{
MessageOfClassroom classroom_message = 1;
MessageOfDoor door_message = 2;
MessageOfGate gate_message = 3;
}
}

message MessageOfMap
{
message Row
@@ -95,17 +126,27 @@ message MessageOfMap
repeated PlaceType col = 1;
}
repeated Row row = 2;
repeated MessageOfMapObj map_obj_message = 3;
}

message MessageOfObj
{
oneof message_of_obj
{
MessageOfStudent student_message = 1;
MessageOfTricker tricker_message = 2;
MessageOfProp prop_message = 3;
MessageOfBullet bullet_message = 4;
MessageOfBombedBullet bombed_bullet_message = 5;
}
}

message MessageToClient
{
repeated MessageOfStudent student_message = 1;
repeated MessageOfTricker tricker_message = 2; // 是否真正repeated待定
repeated MessageOfProp prop_message = 3;
repeated MessageOfBullet bullet_message = 4;
repeated MessageOfBombedBullet bombed_bullet_message = 5;
MessageOfMap map_message = 6;
GameState game_state = 7;
repeated MessageOfObj obj_message = 1;
MessageOfMap map_message = 2;
GameState game_state = 3;
int32 finished_num = 4; // 完成的科目数
}

message MoveRes // 如果打算设计撞墙保留平行速度分量,且需要返回值则可用这个(大概没啥用)


+ 1
- 1
dependency/proto/Message2Server.proto View File

@@ -22,7 +22,7 @@ message MoveMsg
int64 time_in_milliseconds = 3;
}

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


+ 5
- 2
dependency/proto/MessageType.proto View File

@@ -23,6 +23,8 @@ enum PlaceType // 地图中的所有物件类型
CLASSROOM = 4;
GATE = 5;
HIDDEN_GATE = 6;
WINDOW = 7;
DOOR = 8;
// 待补充有特殊效果的地形

}
@@ -109,6 +111,7 @@ enum GameState
{
NULL_GAME_STATE = 0;
GAME_START = 1;
GAME_RUNNING = 2;
GAME_END = 3;
STAGE_1 = 2; // 第一阶段:大门没有开
STAGE_2 = 3; // 第二阶段:大门已经开了
GAME_END = 4;
}

+ 6
- 2
dependency/proto/Services.proto View File

@@ -13,7 +13,7 @@ service AvailableService

// 游戏过程中玩家执行操作的服务
rpc Move (MoveMsg) returns (MoveRes);
rpc PickProp (PickMsg) returns (BoolRes);
rpc PickProp (PropMsg) returns (BoolRes);
rpc UseProp (IDMsg) returns (BoolRes);
rpc UseSkill (IDMsg) returns (BoolRes);
rpc SendMessage (SendMsg) returns (BoolRes);
@@ -23,5 +23,9 @@ service AvailableService
rpc StartHealMate (IDMsg) returns (BoolRes);
rpc Trick (TrickMsg) returns (BoolRes); // 攻击
rpc Graduate (IDMsg) returns (BoolRes); // 相当于逃跑
rpc OpenDoor (IDMsg) returns (BoolRes); // 开门
rpc CloseDoor (IDMsg) returns (BoolRes); // 关门
rpc SkipWindow (IDMsg) returns (BoolRes); // 窗户
rpc StartOpenGate (IDMsg) returns (BoolRes); // 开闸门
rpc EndAllAction (IDMsg) returns (BoolRes); // 结束所有动作
}

+ 134
- 0
playback/Playback/MessageReader.cs View File

@@ -0,0 +1,134 @@
using Communication.Proto;
using Google.Protobuf;
using System;
using System.IO;
using System.IO.Compression;

namespace Playback
{
public class FileFormatNotLegalException : Exception
{
private readonly string fileName;
public FileFormatNotLegalException(string fileName)
{
this.fileName = fileName;
}
public override string Message => $"The file: " + this.fileName + " is not a legal playback file for THUAI6.";
}

public class MessageReader : IDisposable
{
private FileStream? fs;
private CodedInputStream cos;
private GZipStream gzs;
private byte[] buffer;
public bool Finished { get; private set; } = false;

public readonly uint teamCount;
public readonly uint playerCount;

const int bufferMaxSize = 1024 * 1024; // 1M

public MessageReader(string fileName)
{
if (!fileName.EndsWith(PlayBackConstant.ExtendedName))
{
fileName += PlayBackConstant.ExtendedName;
}

fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);

try
{
var prefixLen = PlayBackConstant.Prefix.Length;
byte[] bt = new byte[prefixLen + sizeof(UInt32) * 2];
fs.Read(bt, 0, bt.Length);
for (int i = 0; i < prefixLen; ++i)
{
if (bt[i] != PlayBackConstant.Prefix[i]) throw new FileFormatNotLegalException(fileName);
}

teamCount = BitConverter.ToUInt32(bt, prefixLen);
playerCount = BitConverter.ToUInt32(bt, prefixLen + sizeof(UInt32));
}
catch
{
throw new FileFormatNotLegalException(fileName);
}

gzs = new GZipStream(fs, CompressionMode.Decompress);
var tmpBuffer = new byte[bufferMaxSize];
var bufferSize = gzs.Read(tmpBuffer);
if (bufferSize == 0)
{
buffer = tmpBuffer;
Finished = true;
}
else if (bufferSize != bufferMaxSize) // 不留空位,防止 CodedInputStream 获取信息错误
{
if (bufferSize == 0)
{
Finished = true;
}
buffer = new byte[bufferSize];
Array.Copy(tmpBuffer, buffer, bufferSize);
}
else
{
buffer = tmpBuffer;
}
cos = new CodedInputStream(buffer);
}

public MessageToClient? ReadOne()
{
beginRead:
if (Finished) return null;
var pos = cos.Position;
try
{
MessageToClient? msg = new MessageToClient();
cos.ReadMessage(msg);
return msg;
}
catch (InvalidProtocolBufferException)
{
var leftByte = buffer.Length - pos; // 上次读取剩余的字节
for (int i = 0; i < leftByte; ++i)
{
buffer[i] = buffer[pos + i];
}
var bufferSize = gzs.Read(buffer, (int)leftByte, (int)(buffer.Length - leftByte)) + leftByte;
if (bufferSize == leftByte)
{
Finished = true;
return null;
}
if (bufferSize != buffer.Length) // 不留空位,防止 CodedInputStream 获取信息错误
{
var tmpBuffer = new byte[bufferSize];
Array.Copy(buffer, tmpBuffer, bufferSize);
buffer = tmpBuffer;
}
cos = new CodedInputStream(buffer);
goto beginRead;
}
}

public void Dispose()
{
Finished = true;
if (fs == null)
return;
if (fs.CanRead)
{
fs.Close();
}
}

~MessageReader()
{
Dispose();
}
}
}

+ 74
- 0
playback/Playback/MessageWriter.cs View File

@@ -0,0 +1,74 @@
using Communication.Proto;
using Google.Protobuf;
using System;
using System.IO;
using System.IO.Compression;

namespace Playback
{
public class MessageWriter : IDisposable
{
private FileStream fs;
private CodedOutputStream cos;
private MemoryStream ms;
private GZipStream gzs;
private const int memoryCapacity = 1024 * 1024; // 1M

private static void ClearMemoryStream(MemoryStream msToClear)
{
msToClear.Position = 0;
msToClear.SetLength(0);
}

public MessageWriter(string fileName, uint teamCount, uint playerCount)
{
if (!fileName.EndsWith(PlayBackConstant.ExtendedName))
{
fileName += PlayBackConstant.ExtendedName;
}

fs = new FileStream(fileName, FileMode.Create, FileAccess.Write);
fs.Write(PlayBackConstant.Prefix); // 写入前缀

fs.Write(BitConverter.GetBytes((UInt32)teamCount)); // 写入队伍数
fs.Write(BitConverter.GetBytes((UInt32)playerCount)); // 写入每队的玩家人数
ms = new MemoryStream(memoryCapacity);
cos = new CodedOutputStream(ms);
gzs = new GZipStream(fs, CompressionMode.Compress);
}

public void WriteOne(MessageToClient msg)
{
cos.WriteMessage(msg);
if (ms.Length > memoryCapacity)
Flush();
}

public void Flush()
{
if (fs.CanWrite)
{
cos.Flush();
gzs.Write(ms.GetBuffer(), 0, (int)ms.Length);
ClearMemoryStream(ms);
fs.Flush();
}
}

public void Dispose()
{
if (fs.CanWrite)
{
Flush();
cos.Dispose();
gzs.Dispose();
fs.Dispose();
}
}

~MessageWriter()
{
Dispose();
}
}
}

+ 0
- 6
playback/Playback/Playback.cs View File

@@ -1,6 +0,0 @@
namespace Playback
{
public class Playback
{
}
}

+ 1
- 1
playback/Playback/Playback.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<TargetFrameworks>net6.0;netstandard2.1</TargetFrameworks>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>


+ 8
- 0
playback/Playback/PlaybackConstant.cs View File

@@ -0,0 +1,8 @@
namespace Playback
{
public static class PlayBackConstant
{
public static string ExtendedName = ".thuaipb";
public static byte[] Prefix = { (byte)'P', (byte)'B', 6, 0 }; // 文件前缀,用于标识文件类型,版本号为6
}
}

Loading…
Cancel
Save