Browse Source

Merge pull request #476 from eesast/dev

chore: add numpy in py requirements
tags/0.1.0
Changli Tang GitHub 2 years ago
parent
commit
7cedb024ed
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 224 additions and 130 deletions
  1. +26
    -0
      CAPI/cpp/API/src/main.cpp
  2. +2
    -2
      CAPI/python/PyAPI/logic.py
  3. +24
    -0
      CAPI/python/PyAPI/main.py
  4. +1
    -0
      CAPI/python/requirements.txt
  5. +13
    -0
      installer/Installer/Installer.csproj
  6. +45
    -38
      installer/Installer/Model.cs
  7. BIN
      installer/Installer/eesast_software_trans_enlarged.ico
  8. +8
    -0
      installer/InstallerUpdater/InstallerUpdater.csproj
  9. +8
    -13
      logic/Server/GameServer.cs
  10. +11
    -11
      logic/Server/PlaybackServer.cs
  11. +68
    -55
      logic/Server/Program.cs
  12. +4
    -11
      logic/Server/RpcServices.cs
  13. +14
    -0
      logic/Server/ServerBase.cs

+ 26
- 0
CAPI/cpp/API/src/main.cpp View File

@@ -3,6 +3,7 @@
#include "structures.h"
#include <tclap/CmdLine.h>
#include <array>
#include <string_view>

#undef GetMessage
#undef SendMessage
@@ -12,6 +13,26 @@
#pragma warning(disable : 4996)
#endif

using namespace std::literals::string_view_literals;

// Generated by http://www.network-science.de/ascii/ with font "standard"
static constexpr std::string_view welcomeString = R"welcome(

_____ _ _ _ _ _ ___ __
|_ _| | | | | | | / \ |_ _/ /_
| | | |_| | | | |/ _ \ | | '_ \
| | | _ | |_| / ___ \ | | (_) |
|_| |_| |_|\___/_/ \_\___\___/

____ _ _ ____ _ _ _
/ ___|_ __ __ _ __| |_ _ __ _| |_ ___ / ___(_)_ __| |___| |
| | _| '__/ _` |/ _` | | | |/ _` | __/ _ \ | | _| | '__| / __| |
| |_| | | | (_| | (_| | |_| | (_| | || __/_ | |_| | | | | \__ \_|
\____|_| \__,_|\__,_|\__,_|\__,_|\__\___( ) \____|_|_| |_|___(_)


)welcome"sv;

int THUAI6Main(int argc, char** argv, CreateAIFunc AIBuilder)
{
int pID = 0;
@@ -84,6 +105,11 @@ int THUAI6Main(int argc, char** argv, CreateAIFunc AIBuilder)
playerType = THUAI6::PlayerType::StudentPlayer;
stuType = studentType[pID];
}

#ifdef _MSC_VER
std::cout << welcomeString << std::endl;
#endif

Logic logic(playerType, pID, trickerType, stuType);
logic.Main(AIBuilder, sIP, sPort, file, print, warnOnly);
}


+ 2
- 2
CAPI/python/PyAPI/logic.py View File

@@ -512,10 +512,10 @@ class Logic(ILogic):

if platform.system().lower() == "windows":
os.system(
f"mkdir {os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '/logs'}")
f"mkdir \"{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}\\logs\"")
else:
os.system(
f"mkdir -p {os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + '/logs'}")
f"mkdir -p \"{os.path.dirname(os.path.dirname(os.path.realpath(__file__)))}/logs\"")

fileHandler = logging.FileHandler(os.path.dirname(
os.path.dirname(os.path.realpath(__file__))) + "/logs/logic" + str(self.__playerID) + "-log.txt", "w+", encoding="utf-8")


+ 24
- 0
CAPI/python/PyAPI/main.py View File

@@ -9,8 +9,28 @@ from PyAPI.AI import AI
from PyAPI.logic import Logic
from typing import List, Callable
import argparse
import platform
import PyAPI.structures as THUAI6

def PrintWelcomeString() -> None:
# Generated by http://www.network-science.de/ascii/ with font "standard"
welcomeString = """

_____ _ _ _ _ _ ___ __
|_ _| | | | | | | / \ |_ _/ /_
| | | |_| | | | |/ _ \ | | '_ \
| | | _ | |_| / ___ \ | | (_) |
|_| |_| |_|\___/_/ \_\___\___/

____ _ _ ____ _ _ _
/ ___|_ __ __ _ __| |_ _ __ _| |_ ___ / ___(_)_ __| |___| |
| | _| '__/ _` |/ _` | | | |/ _` | __/ _ \ | | _| | '__| / __| |
| |_| | | | (_| | (_| | |_| | (_| | || __/_ | |_| | | | | \__ \_|
\____|_| \__,_|\__,_|\__,_|\__,_|\__\___( ) \____|_|_| |_|___(_)


"""
print(welcomeString)

def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None:
pID: int = 0
@@ -45,6 +65,10 @@ def THUAI6Main(argv: List[str], AIBuilder: Callable) -> None:
playerType = THUAI6.PlayerType.TrickerPlayer
else:
playerType = THUAI6.PlayerType.StudentPlayer

if platform.system().lower() == "windows":
PrintWelcomeString()

logic = Logic(pID, playerType)
logic.Main(AIBuilder, sIP, sPort, file, screen, warnOnly)



+ 1
- 0
CAPI/python/requirements.txt View File

@@ -1,2 +1,3 @@
grpcio==1.52.0
grpcio-tools==1.52.0
numpy

+ 13
- 0
installer/Installer/Installer.csproj View File

@@ -6,8 +6,21 @@
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>eesast_software_trans_enlarged.ico</ApplicationIcon>
<PackageIcon>eesast_software_trans.png</PackageIcon>
</PropertyGroup>

<ItemGroup>
<Content Include="eesast_software_trans_enlarged.ico" />
</ItemGroup>

<ItemGroup>
<None Include="..\..\resource\eesast_software_trans.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<PackageReference Include="ICSharpCode.SharpZipLib.dll" Version="0.85.4.369" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="7.0.0" />


+ 45
- 38
installer/Installer/Model.cs View File

@@ -392,7 +392,7 @@ namespace Downloader
public class Data
{
public static string path = ""; // 标记路径记录文件THUAI6.json的路径
public static string FilePath = ""; // 最后一级为THUAI6文件夹所在目录
public static string FilePath = ""; // 最后一级为THUAI6文件夹所在目录
public static string dataPath = ""; // C盘的文档文件夹
public Data(string path)
{
@@ -401,7 +401,7 @@ namespace Downloader
Data.path = System.IO.Path.Combine(dataPath, "THUAI6.json");
if (File.Exists(Data.path))
{
var dict = new Dictionary<string, string>();
Dictionary<string, string>? dict;
using (StreamReader r = new StreamReader(Data.path))
{
string json = r.ReadToEnd();
@@ -409,7 +409,7 @@ namespace Downloader
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
if (dict != null && dict.ContainsKey("installpath"))
{
FilePath = dict["installpath"].Replace('\\', '/');
@@ -424,7 +424,7 @@ namespace Downloader
else
{
FilePath = System.IO.Path.GetDirectoryName(@path)
?? throw new Exception("Fail to find the path of the file");
?? throw new Exception("Failed to get the path of the file");

//将dat文件写入程序运行路径
string json;
@@ -437,7 +437,7 @@ namespace Downloader
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
dict?.Add("installpath", path);
}
using FileStream fs2 = new FileStream(Data.path, FileMode.Create, FileAccess.ReadWrite);
@@ -461,7 +461,7 @@ namespace Downloader
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
if (dict != null && dict.ContainsKey("installpath"))
{
dict["installpath"] = newPath;
@@ -634,7 +634,7 @@ namespace Downloader
using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
Dictionary<string, string> jsonDict = Utils.DeserializeJson<Dictionary<string, string>>(json);
var jsonDict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
string updatingFolder = "";
switch (OS)
{
@@ -815,7 +815,7 @@ namespace Downloader
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
var dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
var dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
if (dict == null || !dict.ContainsKey("download") || "false" == dict["download"])
{
return false;
@@ -865,7 +865,7 @@ namespace Downloader
using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, jsonName)))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
Dictionary<string, string> jsonDict = Utils.DeserializeJson<Dictionary<string, string>>(json);
// var jsonDict = Utils.DeserializeJson<Dictionary1<string, string>>(json);

newFileName.Clear();
updateFileName.Clear();
@@ -899,7 +899,7 @@ namespace Downloader
FileInfo fileInfo = new FileInfo(System.IO.Path.Combine(Data.FilePath, "THUAI6.tar.gz"));
fileInfo.Delete();
string json2;
Dictionary<string, string> dict = new Dictionary<string, string>();
Dictionary<string, string>? dict;
string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
using (StreamReader r = new StreamReader(fs))
@@ -909,7 +909,7 @@ namespace Downloader
{
json2 += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json2);
dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json2);
if (dict == null || !dict.ContainsKey("download"))
{
dict?.Add("download", "true");
@@ -1000,7 +1000,7 @@ namespace Downloader
using (StreamReader r = new StreamReader(System.IO.Path.Combine(Data.FilePath, "hash.json")))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty).Replace("/", @"\\");
Dictionary<string, string> jsonDict = Utils.DeserializeJson<Dictionary<string, string>>(json);
Dictionary<string, string> jsonDict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
Change_all_hash(Data.FilePath, jsonDict);
OverwriteHash(jsonDict);
break;
@@ -1058,7 +1058,7 @@ namespace Downloader
}

string json2;
Dictionary<string, string> dict = new Dictionary<string, string>();
Dictionary<string, string>? dict;
string existpath = System.IO.Path.Combine(Data.dataPath, "THUAI6.json");
using FileStream fs = new FileStream(existpath, FileMode.Open, FileAccess.ReadWrite);
using (StreamReader r = new StreamReader(fs))
@@ -1068,7 +1068,7 @@ namespace Downloader
{
json2 += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json2);
dict = Utils.TryDeserializeJson<Dictionary<string, string>>(json2);
if (dict == null || !dict.ContainsKey("download"))
{
dict?.Add("download", "false");
@@ -1302,7 +1302,7 @@ namespace Downloader
using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, hashName)))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
Dictionary<string, string> jsonDict = Utils.DeserializeJson<Dictionary<string, string>>(json);
var jsonDict = Utils.TryDeserializeJson<Dictionary<string, string>>(json);
string md5 = "";
List<string> awaitUpdate = new List<string>();
if (jsonDict != null)
@@ -1351,9 +1351,9 @@ namespace Downloader
using (StreamReader r = new StreamReader(System.IO.Path.Combine(dir, "updateList.json")))
json = r.ReadToEnd();
json = json.Replace("\r", string.Empty).Replace("\n", string.Empty);
List<string> jsonList;
List<string>? jsonList;
if (json != null)
jsonList = Utils.DeserializeJson<List<string>>(json);
jsonList = Utils.TryDeserializeJson<List<string>>(json);
else
return false;
if (jsonList != null && jsonList.Contains("Dismiss"))
@@ -1405,7 +1405,7 @@ namespace WebConnect
throw new Exception("no token!");
logintoken = token;
SaveToken();
var info = Utils.DeserializeJson<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
var info = Utils.DeserializeJson1<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
Downloader.UserInfo._id = info["_id"];
Downloader.UserInfo.email = info["email"];
break;
@@ -1461,19 +1461,19 @@ namespace WebConnect
{
case System.Net.HttpStatusCode.OK:

var res = Utils.DeserializeJson<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
string appid = "1255334966"; // 设置腾讯云账户的账户标识(APPID)
string region = "ap-beijing"; // 设置一个默认的存储桶地域
var res = Utils.DeserializeJson1<Dictionary<string, string>>(await response.Content.ReadAsStringAsync());
string appid = "1255334966"; // 设置腾讯云账户的账户标识(APPID)
string region = "ap-beijing"; // 设置一个默认的存储桶地域
CosXmlConfig config = new CosXmlConfig.Builder()
.IsHttps(true) // 设置默认 HTTPS 请求
.SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
.SetRegion(region) // 设置一个默认的存储桶地域
.SetDebugLog(true) // 显示日志
.Build(); // 创建 CosXmlConfig 对象
string tmpSecretId = res["TmpSecretId"]; //"临时密钥 SecretId";
string tmpSecretKey = res["TmpSecretKey"]; //"临时密钥 SecretKey";
string tmpToken = res["SecurityToken"]; //"临时密钥 token";
long tmpExpiredTime = Convert.ToInt64(res["ExpiredTime"]);//临时密钥有效截止时间,精确到秒
.IsHttps(true) // 设置默认 HTTPS 请求
.SetAppid(appid) // 设置腾讯云账户的账户标识 APPID
.SetRegion(region) // 设置一个默认的存储桶地域
.SetDebugLog(true) // 显示日志
.Build(); // 创建 CosXmlConfig 对象
string tmpSecretId = res["TmpSecretId"]; //"临时密钥 SecretId";
string tmpSecretKey = res["TmpSecretKey"]; //"临时密钥 SecretKey";
string tmpToken = res["SecurityToken"]; //"临时密钥 token";
long tmpExpiredTime = Convert.ToInt64(res["ExpiredTime"]); //临时密钥有效截止时间,精确到秒
QCloudCredentialProvider cosCredentialProvider = new DefaultSessionQCloudCredentialProvider(
tmpSecretId, tmpSecretKey, tmpExpiredTime, tmpToken
);
@@ -1586,7 +1586,7 @@ namespace WebConnect
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
if (dict.ContainsKey("token"))
{
dict.Remove("token");
@@ -1629,7 +1629,7 @@ namespace WebConnect
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
Dictionary<string, string> dict = new Dictionary<string, string>();
dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
if (!dict.ContainsKey(key))
{
dict.Add(key, data);
@@ -1666,7 +1666,7 @@ namespace WebConnect
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
fs.Close();
sr.Close();
return dict[key];
@@ -1693,7 +1693,7 @@ namespace WebConnect
{
json += @"{""THUAI6""" + ":" + @"""2023""}";
}
dict = Utils.DeserializeJson<Dictionary<string, string>>(json);
dict = Utils.DeserializeJson1<Dictionary<string, string>>(json);
if (!dict.ContainsKey("token"))
{
return false;
@@ -1747,9 +1747,9 @@ namespace WebConnect
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var info = await response.Content.ReadAsStringAsync();
var s1 = Utils.DeserializeJson<Dictionary<string, object>>(info)["data"];
var s2 = Utils.DeserializeJson<Dictionary<string, List<object>>>(s1.ToString() ?? "")["contest_team_member"];
var sres = Utils.DeserializeJson<Dictionary<string, string>>(s2[0].ToString() ?? "")["team_id"];
var s1 = Utils.DeserializeJson1<Dictionary<string, object>>(info)["data"];
var s2 = Utils.DeserializeJson1<Dictionary<string, List<object>>>(s1.ToString() ?? "")["contest_team_member"];
var sres = Utils.DeserializeJson1<Dictionary<string, string>>(s2[0].ToString() ?? "")["team_id"];
return sres;
}
async public Task<string> GetUserId(string learnNumber)
@@ -1777,11 +1777,18 @@ namespace WebConnect

internal static class Utils
{
public static T DeserializeJson<T>(string json)
public static T DeserializeJson1<T>(string json)
where T : notnull
{
return JsonConvert.DeserializeObject<T>(json)
?? throw new Exception("Failed to deserialize json.");
}

public static T? TryDeserializeJson<T>(string json)
where T : notnull
{
return JsonConvert.DeserializeObject<T>(json);
}
}

}

BIN
installer/Installer/eesast_software_trans_enlarged.ico View File

Before After

+ 8
- 0
installer/InstallerUpdater/InstallerUpdater.csproj View File

@@ -5,8 +5,16 @@
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWPF>true</UseWPF>
<PackageIcon>eesast_software_trans.png</PackageIcon>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\resource\eesast_software_trans.png">
<Pack>True</Pack>
<PackagePath>\</PackagePath>
</None>
</ItemGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Tencent.QCloud.Cos.Sdk" Version="5.4.34">


+ 8
- 13
logic/Server/GameServer.cs View File

@@ -1,22 +1,17 @@
using Grpc.Core;
using Protobuf;
using System.Threading;
using Timothy.FrameRateTask;
using System;
using System.Net.Http.Headers;
using GameClass.GameObj;
using Gaming;
using GameClass.GameObj;
using Preparation.Utility;
using Playback;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Preparation.Interface;
using Playback;
using Preparation.Utility;
using Protobuf;
using System.Collections.Concurrent;
using Timothy.FrameRateTask;


namespace Server
{
public partial class GameServer : AvailableService.AvailableServiceBase
partial class GameServer : ServerBase
{
private ConcurrentDictionary<long, (SemaphoreSlim, SemaphoreSlim)> semaDict = new();
// private object semaDictLock = new();
@@ -86,7 +81,7 @@ namespace Server
}
}

public void WaitForEnd()
public override void WaitForEnd()
{
this.endGameSem.Wait();
mwr?.Dispose();
@@ -202,7 +197,7 @@ namespace Server
return false;
}

public int[] GetScore()
public override int[] GetScore()
{
int[] score = new int[2]; // 0代表Student,1代表Tricker
game.GameMap.GameObjLockDict[GameObjType.Character].EnterReadLock();


+ 11
- 11
logic/Server/PlaybackServer.cs View File

@@ -1,26 +1,23 @@
using Protobuf;
using Playback;
using System;
using System.Threading;
using Timothy.FrameRateTask;
using Gaming;
using Gaming;
using Grpc.Core;
using Playback;
using Protobuf;
using System.Collections.Concurrent;
using Timothy.FrameRateTask;

namespace Server
{
class PlaybackServer : AvailableService.AvailableServiceBase
class PlaybackServer : ServerBase
{
protected readonly ArgumentOptions options;
private int[,] teamScore;
private ConcurrentDictionary<long, (SemaphoreSlim, SemaphoreSlim)> semaDict = new();
private object semaDictLock = new();
// private object semaDictLock = new();
private MessageToClient? currentGameInfo = new();
private MessageOfObj currentMapMsg = new();
private uint spectatorMinPlayerID = 2023;
private List<uint> spectatorList = new List<uint>();
// private List<uint> spectatorList = new List<uint>();
public int TeamCount => options.TeamCount;
private MessageWriter? mwr = null;
private object spetatorJoinLock = new();
protected object spectatorLock = new object();
protected bool isSpectatorJoin = false;
@@ -47,6 +44,7 @@ namespace Server
return finalScore;
}
}
public override int[] GetScore() => FinalScore;
public PlaybackServer(ArgumentOptions options)
{
this.options = options;
@@ -57,6 +55,7 @@ namespace Server

public override async Task AddPlayer(PlayerMsg request, IServerStreamWriter<MessageToClient> responseStream, ServerCallContext context)
{
Console.WriteLine($"AddPlayer: {request.PlayerId}");
if (request.PlayerId >= spectatorMinPlayerID && options.NotAllowSpectator == false)
{
// 观战模式
@@ -95,6 +94,7 @@ namespace Server
}
catch { }
Console.WriteLine($"The spectator {request.PlayerId} exited");
return;
}
}
catch (Exception)
@@ -139,7 +139,7 @@ namespace Server
}
}

public void WaitForGame()
public override void WaitForEnd()
{
try
{


+ 68
- 55
logic/Server/Program.cs View File

@@ -1,15 +1,55 @@
using Grpc.Core;
using CommandLine;
using Grpc.Core;
using Protobuf;
using System.Threading;
using Timothy.FrameRateTask;
using System;
using System.Net.Http.Headers;
using CommandLine;

namespace Server
{
public class Program
{
/// <summary>
/// Generated by http://www.network-science.de/ascii/ with font "standard"
/// </summary>
const string welcome =
@"

_____ _ _ _ _ _ ___ __
|_ _| | | | | | | / \ |_ _/ /_
| | | |_| | | | |/ _ \ | | '_ \
| | | _ | |_| / ___ \ | | (_) |
|_| |_| |_|\___/_/ \_\___\___/

____ _ _ ____ _ _ _
/ ___|_ __ __ _ __| |_ _ __ _| |_ ___ / ___(_)_ __| |___| |
| | _| '__/ _` |/ _` | | | |/ _` | __/ _ \ | | _| | '__| / __| |
| |_| | | | (_| | (_| | |_| | (_| | || __/_ | |_| | | | | \__ \_|
\____|_| \__,_|\__,_|\__,_|\__,_|\__\___( ) \____|_|_| |_|___(_)


";
// 特别说明:在 .NET 7 及以上,C# 支持新的多行字符串,允许多行前面缩进,因此可以不必再定格写字符串,
// 即升级 .NET 版本后可以改为如下的:
// const string welcome = """
//
// _____ _ _ _ _ _ ___ __
// |_ _| | | | | | | / \ |_ _/ /_
// | | | |_| | | | |/ _ \ | | '_ \
// | | | _ | |_| / ___ \ | | (_) |
// |_| |_| |_|\___/_/ \_\___\___/
//
// ____ _ _ ____ _ _ _
// / ___|_ __ __ _ __| |_ _ __ _| |_ ___ / ___(_)_ __| |___| |
// | | _| '__/ _` |/ _` | | | |/ _` | __/ _ \ | | _| | '__| / __| |
// | |_| | | | (_| | (_| | |_| | (_| | || __/_ | |_| | | | | \__ \_|
// \____|_| \__,_|\__,_|\__,_|\__,_|\__\___( ) \____|_|_| |_|___(_)
//
//
// """; // 将以此结束符为基准开始缩进(但 Python 没有这个 feature,差评 x)

static ServerBase CreateServer(ArgumentOptions options)
{
return options.Playback ? new PlaybackServer(options) : new GameServer(options);
}

static int Main(string[] args)
{
foreach (var arg in args)
@@ -26,63 +66,36 @@ namespace Server
return 1;
}

if (options.StartLockFile == DefaultArgumentOptions.FileName)
{
Console.WriteLine(welcome);
}
Console.WriteLine("Server begins to run: " + options.ServerPort.ToString());

if (options.Playback)
try
{
try
var server = CreateServer(options);
Grpc.Core.Server rpcServer = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
{
PlaybackServer? playbackServer = new(options);
Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
{
Services = { AvailableService.BindService(playbackServer) },
Ports = { new ServerPort(options.ServerIP, options.ServerPort, ServerCredentials.Insecure) }
};
server.Start();
Services = { AvailableService.BindService(server) },
Ports = { new ServerPort(options.ServerIP, options.ServerPort, ServerCredentials.Insecure) }
};
rpcServer.Start();

Console.WriteLine("Server begins to listen!");
playbackServer.WaitForGame();
Console.WriteLine("Server end!");
server.ShutdownAsync().Wait();
Console.WriteLine("Server begins to listen!");
server.WaitForEnd();
Console.WriteLine("Server end!");
rpcServer.ShutdownAsync().Wait();

Thread.Sleep(50);
Console.WriteLine("");
Console.WriteLine("=================== Final Score ====================");
Console.WriteLine($"Studnet: {playbackServer.FinalScore[0]}");
Console.WriteLine($"Tricker: {playbackServer.FinalScore[1]}");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Thread.Sleep(50);
Console.WriteLine("");
Console.WriteLine("=================== Final Score ====================");
Console.WriteLine($"Studnet: {server.GetScore()[0]}");
Console.WriteLine($"Tricker: {server.GetScore()[1]}");
}
else
catch (Exception ex)
{
try
{
GameServer? gameServer = new(options);
Grpc.Core.Server server = new Grpc.Core.Server(new[] { new ChannelOption(ChannelOptions.SoReuseport, 0) })
{
Services = { AvailableService.BindService(gameServer) },
Ports = { new ServerPort(options.ServerIP, options.ServerPort, ServerCredentials.Insecure) }
};
server.Start();

Console.WriteLine("Server begins to listen!");
gameServer.WaitForEnd();
Console.WriteLine("Server end!");
server.ShutdownAsync().Wait();

Thread.Sleep(50);
Console.WriteLine("");
Console.WriteLine("=================== Final Score ====================");
Console.WriteLine($"Studnet: {gameServer.GetScore()[0]}");
Console.WriteLine($"Tricker: {gameServer.GetScore()[1]}");
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine(ex.ToString());
}
return 0;
}


+ 4
- 11
logic/Server/RpcServices.cs View File

@@ -1,19 +1,12 @@
using Grpc.Core;
using Protobuf;
using System.Threading;
using System;
using System.Net.Http.Headers;
using GameClass.GameObj;
using Gaming;
using GameClass.GameObj;
using Grpc.Core;
using Preparation.Utility;
using Playback;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Preparation.Interface;
using Protobuf;

namespace Server
{
public partial class GameServer : AvailableService.AvailableServiceBase
partial class GameServer : ServerBase
{
private int playerCountNow = 0;
protected object spectatorLock = new object();


+ 14
- 0
logic/Server/ServerBase.cs View File

@@ -0,0 +1,14 @@
using Grpc.Core;
using Playback;
using Protobuf;
using System.Collections.Concurrent;
using Timothy.FrameRateTask;

namespace Server
{
abstract class ServerBase : AvailableService.AvailableServiceBase
{
public abstract void WaitForEnd();
public abstract int[] GetScore();
}
}

Loading…
Cancel
Save