Compare commits
1 Commits
191f7a2bd6
...
0d0214b323
Author | SHA1 | Date | |
---|---|---|---|
0d0214b323 |
@ -319,7 +319,7 @@ GameObject:
|
|||||||
m_Icon: {fileID: 0}
|
m_Icon: {fileID: 0}
|
||||||
m_NavMeshLayer: 0
|
m_NavMeshLayer: 0
|
||||||
m_StaticEditorFlags: 0
|
m_StaticEditorFlags: 0
|
||||||
m_IsActive: 0
|
m_IsActive: 1
|
||||||
--- !u!4 &912467178
|
--- !u!4 &912467178
|
||||||
Transform:
|
Transform:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
@ -616,7 +616,6 @@ GameObject:
|
|||||||
serializedVersion: 6
|
serializedVersion: 6
|
||||||
m_Component:
|
m_Component:
|
||||||
- component: {fileID: 1371068282}
|
- component: {fileID: 1371068282}
|
||||||
- component: {fileID: 1371068283}
|
|
||||||
m_Layer: 0
|
m_Layer: 0
|
||||||
m_Name: Loader
|
m_Name: Loader
|
||||||
m_TagString: Untagged
|
m_TagString: Untagged
|
||||||
@ -639,18 +638,6 @@ Transform:
|
|||||||
m_Children: []
|
m_Children: []
|
||||||
m_Father: {fileID: 0}
|
m_Father: {fileID: 0}
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||||
--- !u!114 &1371068283
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1371068281}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 147e91e6929d90a4fb877c0b0a6b608c, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
--- !u!1660057539 &9223372036854775807
|
--- !u!1660057539 &9223372036854775807
|
||||||
SceneRoots:
|
SceneRoots:
|
||||||
m_ObjectHideFlags: 0
|
m_ObjectHideFlags: 0
|
||||||
|
@ -160,17 +160,19 @@ namespace Configs
|
|||||||
|
|
||||||
foreach (var path in paths)
|
foreach (var path in paths)
|
||||||
{
|
{
|
||||||
|
// 获取程序所在的目录路径
|
||||||
|
var appDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||||
|
|
||||||
|
// 构建目标目录的完整路径
|
||||||
|
var dataDirectory = Path.Combine(appDirectory, path);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// 检查目录是否存在
|
// 检查目录是否存在
|
||||||
if (!Directory.Exists(path))
|
if (Directory.Exists(dataDirectory))
|
||||||
{
|
{
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取目录下的所有子文件夹
|
// 获取目录下的所有子文件夹
|
||||||
var subDirectories = Directory.GetDirectories(path);
|
var subDirectories = Directory.GetDirectories(dataDirectory);
|
||||||
|
|
||||||
// 遍历并收集每个子文件夹中的 XML 文件
|
// 遍历并收集每个子文件夹中的 XML 文件
|
||||||
foreach (var dir in subDirectories)
|
foreach (var dir in subDirectories)
|
||||||
@ -178,7 +180,7 @@ namespace Configs
|
|||||||
var xmlFiles = Directory.GetFiles(dir, "*.xml", SearchOption.AllDirectories);
|
var xmlFiles = Directory.GetFiles(dir, "*.xml", SearchOption.AllDirectories);
|
||||||
xmlFilePaths.AddRange(xmlFiles);
|
xmlFilePaths.AddRange(xmlFiles);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
@ -11,15 +11,15 @@ namespace Data
|
|||||||
{
|
{
|
||||||
public class PackAbout
|
public class PackAbout
|
||||||
{
|
{
|
||||||
public string name;
|
public string[] after;
|
||||||
public string description;
|
|
||||||
public string author;
|
public string author;
|
||||||
public string version;
|
public string[] before;
|
||||||
public string packID;
|
public string description;
|
||||||
|
public string name;
|
||||||
|
|
||||||
public string[] necessary;
|
public string[] necessary;
|
||||||
public string[] after;
|
public string packID;
|
||||||
public string[] before;
|
public string version;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 使用静态方法从 XML 文档创建 PackAbout 实例。
|
/// 使用静态方法从 XML 文档创建 PackAbout 实例。
|
||||||
@ -123,9 +123,9 @@ namespace Data
|
|||||||
packID = packAbout.packID;
|
packID = packAbout.packID;
|
||||||
if (aboutXmls.Count > 1) Debug.LogWarning($"{packAbout.name}包拥有多个配置文件,系统选择了加载序的第一个,请避免这种情况");
|
if (aboutXmls.Count > 1) Debug.LogWarning($"{packAbout.name}包拥有多个配置文件,系统选择了加载序的第一个,请避免这种情况");
|
||||||
|
|
||||||
var defineXmls = FindDocumentsWithRootName(packDatas, "Define");
|
var defineXmls = FindDocumentsWithRootName(aboutXmls, "Define");
|
||||||
// Debug.Log($"Define文件数量{defineXmls.Count}");
|
|
||||||
foreach (var defineXml in defineXmls) LoadDefines(defineXml);
|
foreach (var defineXml in defineXmls) LoadDefines(defineXml);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,15 +140,12 @@ namespace Data
|
|||||||
var className = element.Name.ToString();
|
var className = element.Name.ToString();
|
||||||
if (string.IsNullOrEmpty(className))
|
if (string.IsNullOrEmpty(className))
|
||||||
continue;
|
continue;
|
||||||
// Debug.Log("1");
|
|
||||||
var def = LoadDefineClass(element);
|
var def = LoadDefineClass(element);
|
||||||
if (def == null)
|
if (def == null)
|
||||||
continue;
|
continue;
|
||||||
// Debug.Log("2");
|
|
||||||
if (!defines.ContainsKey(className))
|
if (!defines.ContainsKey(className))
|
||||||
defines.Add(className, new List<Define>());
|
defines.Add(className, new List<Define>());
|
||||||
defines[className].Add(def);
|
defines[className].Add(def);
|
||||||
// Debug.Log($"插入{className},{def.defName}");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,29 +15,12 @@ namespace Managers
|
|||||||
|
|
||||||
public void Init()
|
public void Init()
|
||||||
{
|
{
|
||||||
var packFolder = Configs.ConfigProcessor.GetSubFolders(new(dataSetFilePath));
|
var packFolder = Directory.GetDirectories(dataSetFilePath[0]);
|
||||||
foreach (var folder in packFolder)
|
foreach (var folder in packFolder)
|
||||||
{
|
{
|
||||||
var pack = new DefinePack();
|
var pack = new DefinePack();
|
||||||
if (pack.LoadPack(folder)) packs.Add(pack.packID, pack);
|
if (pack.LoadPack(folder)) packs.Add(pack.packID, pack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
if (packs == null || packs.Count == 0)
|
|
||||||
{
|
|
||||||
return "No packs available"; // 如果集合为空或为 null,返回默认信息
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = new System.Text.StringBuilder();
|
|
||||||
|
|
||||||
foreach (var definePack in packs)
|
|
||||||
{
|
|
||||||
result.AppendLine(definePack.ToString()); // 每个元素占一行
|
|
||||||
}
|
|
||||||
|
|
||||||
return result.ToString();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ namespace Test
|
|||||||
{
|
{
|
||||||
public class ClockTest : MonoBehaviour
|
public class ClockTest : MonoBehaviour
|
||||||
{
|
{
|
||||||
//private static float timer = 0;
|
private static float timer = 0;
|
||||||
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
||||||
private void Start()
|
private void Start()
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Test
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
public class TestDefine : MonoBehaviour
|
|
||||||
{
|
|
||||||
// Start is called once before the first execution of Update after the MonoBehaviour is created
|
|
||||||
void Start()
|
|
||||||
{
|
|
||||||
Managers.DefineManager.Instance.Init();
|
|
||||||
Debug.Log(Managers.DefineManager.Instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update is called once per frame
|
|
||||||
void Update()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,2 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 147e91e6929d90a4fb877c0b0a6b608c
|
|
@ -1,11 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<About>
|
|
||||||
<name>核心</name>
|
|
||||||
<description>这是游戏的核心模块,除非有完整的代替,否则应该永远作为启动项</description>
|
|
||||||
<version>0.1</version>
|
|
||||||
<packID>core</packID>
|
|
||||||
<sort>
|
|
||||||
<before></before>
|
|
||||||
<after></after>
|
|
||||||
</sort>
|
|
||||||
</About>
|
|
@ -1,37 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<Define><!--表示是游戏数据定义 -->
|
|
||||||
<Attributes><!--定义一个Attributes类型 -->
|
|
||||||
<defName>CatGirl</defName><!--此Attributes的引用名,应该保持唯一(在同一种类型中) -->
|
|
||||||
<health>100</health><!--C#中定义的同名的Attributes类中含有的变量,并对其进行赋值 -->
|
|
||||||
<speed>1.2</speed>
|
|
||||||
<strength>5</strength>
|
|
||||||
</Attributes>
|
|
||||||
|
|
||||||
<Character>
|
|
||||||
<defName>CatGirl</defName>
|
|
||||||
<label>CatGirl</label>
|
|
||||||
<description>She is a cat girl with agile movements and sharp senses.</description>
|
|
||||||
<attributes>CatGirl</attributes>
|
|
||||||
|
|
||||||
<drawingOrder_down>CatGirl_down</drawingOrder_down><!--根据defName引用其他的属性,识别过程是首先根据C#中定义的此变量的类型,再根据名称查找此类型定义的数据块 -->
|
|
||||||
<drawingOrder_left>CatGirl_left</drawingOrder_left>
|
|
||||||
<drawingOrder_right>CatGirl_right</drawingOrder_right>
|
|
||||||
<drawingOrder_up>CatGirl_up</drawingOrder_up>
|
|
||||||
</Character>
|
|
||||||
|
|
||||||
|
|
||||||
<DrawingOrder>
|
|
||||||
<defName>CatGirl_down</defName>
|
|
||||||
<DrawNode name="body">
|
|
||||||
<DrawNode name="head">
|
|
||||||
<DrawNode name="backHair"/>
|
|
||||||
<DrawNode name="ear"/>
|
|
||||||
<DrawNode name="face"/>
|
|
||||||
<DrawNode name="frontHair"/>
|
|
||||||
<DrawNode name="hat"/>
|
|
||||||
</DrawNode>
|
|
||||||
<DrawNode name="clothes"/>
|
|
||||||
</DrawNode>
|
|
||||||
</DrawingOrder>
|
|
||||||
</Define>
|
|
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 33 KiB |
Before Width: | Height: | Size: 27 KiB |
Before Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.1 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 6.9 KiB |
Before Width: | Height: | Size: 8.0 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 8.4 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 8.3 KiB |
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
|
|
||||||
<Translation>
|
|
||||||
<Character.CatGirl.label>猫娘</Character.CatGirl.label>
|
|
||||||
<Character.CatGirl.description>她是一个猫娘,拥有猫的特性和人类的智慧。她的耳朵和尾巴显示了她的猫族血统。</Character.CatGirl.description>
|
|
||||||
</Translation>
|
|
810
Server/Cargo.lock
generated
@ -8,10 +8,4 @@ description = "The game server."
|
|||||||
chrono = "0.4"
|
chrono = "0.4"
|
||||||
colored = "3"
|
colored = "3"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
# The prost version must match with that of tonic, or the building will fail.
|
|
||||||
prost = "0.13"
|
|
||||||
tokio = { version = "1", features = ["full"] }
|
tokio = { version = "1", features = ["full"] }
|
||||||
tonic = "0.13"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
tonic-build = "0.13"
|
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
use std::env;
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
fn main() -> io::Result<()> {
|
|
||||||
unsafe {
|
|
||||||
env::set_var("PROTOC", "../Tools/ProtoBuf/bin/protoc.exe");
|
|
||||||
}
|
|
||||||
tonic_build::compile_protos("../Tools/ProtoBuf/proto/message.proto")?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
@ -1,6 +1,5 @@
|
|||||||
mod command_helper;
|
mod command_helper;
|
||||||
mod network_service;
|
mod network_service;
|
||||||
mod protocol;
|
|
||||||
mod server_logger;
|
mod server_logger;
|
||||||
|
|
||||||
use network_service::NetworkService;
|
use network_service::NetworkService;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
mod grpc_server;
|
mod message_dispatcher;
|
||||||
|
mod tcp_server;
|
||||||
|
|
||||||
use grpc_server::GrpcServer;
|
use tcp_server::TcpServer;
|
||||||
|
|
||||||
pub(crate) struct NetworkService;
|
pub(crate) struct NetworkService;
|
||||||
|
|
||||||
@ -8,7 +9,7 @@ impl NetworkService {
|
|||||||
pub(crate) async fn init() {
|
pub(crate) async fn init() {
|
||||||
log::info!("Starting network service...");
|
log::info!("Starting network service...");
|
||||||
|
|
||||||
tokio::spawn(async { GrpcServer::init().await });
|
tokio::spawn(async { TcpServer::init().await });
|
||||||
|
|
||||||
log::info!("network service successfully started!");
|
log::info!("network service successfully started!");
|
||||||
}
|
}
|
||||||
|
@ -1,73 +0,0 @@
|
|||||||
use std::net::SocketAddr;
|
|
||||||
|
|
||||||
use tonic::transport::Server;
|
|
||||||
use tonic::{Request, Response, Status};
|
|
||||||
|
|
||||||
use crate::protocol::game_service_server::{GameService, GameServiceServer};
|
|
||||||
use crate::protocol::general_service_server::{GeneralService, GeneralServiceServer};
|
|
||||||
use crate::protocol::{
|
|
||||||
Empty, LoginRequest, LoginResponse, RequestResult, ServerInfo, SignupRequest, SignupResponse,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub(crate) struct GrpcServer;
|
|
||||||
|
|
||||||
impl GrpcServer {
|
|
||||||
pub(crate) async fn init() {
|
|
||||||
let addr = SocketAddr::new([127, 0, 0, 1].into(), 12345);
|
|
||||||
|
|
||||||
let general_service = GeneralServiceServer::new(GeneralServiceImpl);
|
|
||||||
let game_service = GameServiceServer::new(GameServiceImpl);
|
|
||||||
|
|
||||||
Server::builder()
|
|
||||||
.add_service(general_service)
|
|
||||||
.add_service(game_service)
|
|
||||||
.serve(addr)
|
|
||||||
.await
|
|
||||||
.unwrap_or_else(|e| log::error!("Failed to build server: {e}"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define server implementations
|
|
||||||
|
|
||||||
struct GeneralServiceImpl;
|
|
||||||
struct GameServiceImpl;
|
|
||||||
|
|
||||||
#[tonic::async_trait]
|
|
||||||
impl GeneralService for GeneralServiceImpl {
|
|
||||||
async fn get_server_info(
|
|
||||||
&self,
|
|
||||||
_request: Request<Empty>,
|
|
||||||
) -> Result<Response<ServerInfo>, Status> {
|
|
||||||
Ok(Response::new(ServerInfo {
|
|
||||||
lang: "Rust".into(),
|
|
||||||
ver: "0.1.0".into(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tonic::async_trait]
|
|
||||||
impl GameService for GameServiceImpl {
|
|
||||||
async fn login(
|
|
||||||
&self,
|
|
||||||
request: Request<LoginRequest>,
|
|
||||||
) -> Result<Response<LoginResponse>, Status> {
|
|
||||||
log::info!("User {} logged in!", request.get_ref().username);
|
|
||||||
|
|
||||||
Ok(Response::new(LoginResponse {
|
|
||||||
result: RequestResult::Success.into(),
|
|
||||||
message: "".into(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn signup(
|
|
||||||
&self,
|
|
||||||
request: Request<SignupRequest>,
|
|
||||||
) -> Result<Response<SignupResponse>, Status> {
|
|
||||||
log::info!("User {} signed up!", request.get_ref().username);
|
|
||||||
|
|
||||||
Ok(Response::new(SignupResponse {
|
|
||||||
result: RequestResult::Success.into(),
|
|
||||||
message: "".into(),
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
}
|
|
68
Server/src/network_service/message_dispatcher.rs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
|
pub(crate) struct MessageDispatcher<H>
|
||||||
|
where
|
||||||
|
H: Fn(String) + Send + Sync,
|
||||||
|
{
|
||||||
|
handlers: RwLock<HashMap<String, H>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) static DISPATCHER: LazyLock<MessageDispatcher<Box<dyn Fn(String) + Send + Sync>>> =
|
||||||
|
LazyLock::new(MessageDispatcher::new);
|
||||||
|
|
||||||
|
impl<H> MessageDispatcher<H>
|
||||||
|
where
|
||||||
|
H: Fn(String) + Send + Sync,
|
||||||
|
{
|
||||||
|
fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
handlers: RwLock::new(HashMap::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn register_handler(&self, handler_name: String, handler: H) {
|
||||||
|
let mut handlers = self.handlers.write().await;
|
||||||
|
handlers.insert(handler_name, handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn dispatch(&self, handler_name: String, message: String) {
|
||||||
|
let handlers = self.handlers.read().await;
|
||||||
|
|
||||||
|
match handlers.get(&handler_name) {
|
||||||
|
Some(handler) => handler(message),
|
||||||
|
None => log::error!(
|
||||||
|
"The handler corresponds to this kind of message hasn't been registered!"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod test {
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_dispatch() {
|
||||||
|
use super::DISPATCHER;
|
||||||
|
|
||||||
|
DISPATCHER
|
||||||
|
.register_handler(
|
||||||
|
"UserLogin".into(),
|
||||||
|
Box::new(|message| println!("Received message: {message}")),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
DISPATCHER
|
||||||
|
.register_handler(
|
||||||
|
"UserSignUp".into(),
|
||||||
|
Box::new(|message| println!("Received message: {message}")),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
DISPATCHER
|
||||||
|
.dispatch("UserLogin".into(), "I want to login".into())
|
||||||
|
.await;
|
||||||
|
DISPATCHER
|
||||||
|
.dispatch("UserSignUp".into(), "I want to signup".into())
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
}
|
72
Server/src/network_service/tcp_server.rs
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
use tokio::io::{self, ErrorKind, Interest};
|
||||||
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
|
use tokio::time::{self, Duration};
|
||||||
|
|
||||||
|
pub(crate) struct TcpServer;
|
||||||
|
|
||||||
|
impl TcpServer {
|
||||||
|
pub(crate) async fn init() {
|
||||||
|
match TcpListener::bind("127.0.0.1:12345").await {
|
||||||
|
Ok(listener) => loop {
|
||||||
|
match listener.accept().await {
|
||||||
|
Ok((socket, addr)) => {
|
||||||
|
log::info!("New client connected: {addr}");
|
||||||
|
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut retry_times = 0;
|
||||||
|
|
||||||
|
while retry_times <= 3 {
|
||||||
|
let result = Self::process(&socket).await;
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Ok(_) => continue,
|
||||||
|
Err(e) if e.kind() == ErrorKind::WouldBlock => continue,
|
||||||
|
Err(e) => {
|
||||||
|
if retry_times == 3 {
|
||||||
|
log::error!("Failed to process this socket: {e}");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
retry_times += 1;
|
||||||
|
|
||||||
|
log::error!(
|
||||||
|
"Failed to process this socket: {e}. Retry {retry_times} time(s)..."
|
||||||
|
);
|
||||||
|
|
||||||
|
time::sleep(Duration::from_secs(1)).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(e) => log::error!("Couldn't get client: {e:?}"),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => log::error!("Failed to bind port: {e:?}"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn process(socket: &TcpStream) -> io::Result<()> {
|
||||||
|
let ready = socket
|
||||||
|
.ready(Interest::READABLE | Interest::WRITABLE)
|
||||||
|
.await?;
|
||||||
|
if ready.is_readable() {
|
||||||
|
// Size of per received data shound be smaller than 1KiB.
|
||||||
|
let mut buffer = [0; 1024];
|
||||||
|
let size = socket.try_read(&mut buffer)?;
|
||||||
|
|
||||||
|
log::info!("Received {size} Bytes message.")
|
||||||
|
|
||||||
|
// TODO: Start dispatching messages here.
|
||||||
|
}
|
||||||
|
if ready.is_writable() {
|
||||||
|
// TODO: Start sending back message here.
|
||||||
|
let size = socket.try_write(b"Hello from server written in Rust!")?;
|
||||||
|
|
||||||
|
log::info!("Sent {size} Bytes message.")
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
@ -1 +0,0 @@
|
|||||||
tonic::include_proto!("protocol");
|
|
@ -1,52 +1,3 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
package protocol;
|
option csharp_namespace = "Protocol";
|
||||||
|
|
||||||
// Define services
|
|
||||||
|
|
||||||
service GeneralService {
|
|
||||||
// Get server info from server.
|
|
||||||
//
|
|
||||||
// This parameter actually doesn't accept any arguments,
|
|
||||||
// but it is still required owing to Protobuf grammar.
|
|
||||||
rpc GetServerInfo(Empty) returns (ServerInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
service GameService {
|
|
||||||
rpc Login(LoginRequest) returns (LoginResponse);
|
|
||||||
rpc Signup(SignupRequest) returns (SignupResponse);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define messages
|
|
||||||
|
|
||||||
enum RequestResult {
|
|
||||||
Success = 0;
|
|
||||||
Fail = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Empty {}
|
|
||||||
|
|
||||||
message ServerInfo {
|
|
||||||
string Lang = 1;
|
|
||||||
string ver = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message LoginRequest {
|
|
||||||
string Username = 1;
|
|
||||||
string Password = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message LoginResponse {
|
|
||||||
RequestResult result = 1;
|
|
||||||
string message = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SignupRequest {
|
|
||||||
string Username = 1;
|
|
||||||
string Password = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message SignupResponse {
|
|
||||||
RequestResult result = 1;
|
|
||||||
string message = 2;
|
|
||||||
}
|
|
||||||
|