-
Notifications
You must be signed in to change notification settings - Fork 1
/
Program.cs
202 lines (189 loc) · 7.7 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
using System.Enhance;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;
using Newtonsoft.Json.Linq;
using Team123it.Arcaea.MarveCube.LinkPlay.Core;
using static Team123it.Arcaea.MarveCube.LinkPlay.GlobalProperties;
namespace Team123it.Arcaea.MarveCube.LinkPlay
{
public class Program
{
static Socket? _server;
private static ConsoleWriter? _logWriter;
public static void Main(string[] args)
{
Initialization(args);
}
private static void Initialization(string[] args)
{
Console.Clear();
Console.WriteLine("Welcome to Arcaea Server 2 (123 Marvelous Cube) [LinkPlay Server].");
Console.WriteLine($"(C)Copyright 2015-{DateTime.Now.Year} 123 Open-Source Organization(Team123it). All rights reserved.");
Console.WriteLine();
Thread.Sleep(1000);
if (!File.Exists(Path.Combine(AppContext.BaseDirectory, "data", "config.json")))
{
var data = new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "data"));
if (!data.Exists) data.Create();
uint port, redisPort;
string multiplayerServerUrl, redisUrl, redisPassword;
for (;;)
{
Console.WriteLine("请输入LinkPlay服务器的监听端口(需与主服务器保持同步), 并回车:");
if (ushort.TryParse(Console.ReadLine(), out ushort i))
{
port = i;
break;
}
Console.WriteLine("输入的监听端口无效, 请重新输入");
}
for (;;)
{
Console.WriteLine("请输入LinkPlay服务器的监听端口(需与主服务器保持同步), 并回车(例: \"127.0.0.1\"):");
var i = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(i))
{
multiplayerServerUrl = i;
break;
}
Console.WriteLine("输入的服务器的IP无效, 请重新输入");
}
for (;;)
{
Console.WriteLine("请输入Redis服务器的IP(需与主服务器保持同步), 并回车(例: \"127.0.0.1\"):");
var i = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(i))
{
redisUrl = i;
break;
}
Console.WriteLine("输入的服务器的IP前缀无效, 请重新输入");
}
for (;;)
{
Console.WriteLine("请输入Redis服务器的监听端口(需与主服务器保持同步), 并回车:");
if (ushort.TryParse(Console.ReadLine(), out ushort i))
{
redisPort = i;
break;
}
Console.WriteLine("输入的监听端口无效, 请重新输入");
}
for (;;)
{
Console.WriteLine("请输入Redis服务器的密码(需与主服务器保持同步), 并回车:");
var i = Console.ReadLine();
if (!string.IsNullOrWhiteSpace(i))
{
redisPassword = i;
break;
}
Console.WriteLine("输入的监听端口无效, 请重新输入");
}
Console.WriteLine("正在保存设置, 请稍后");
var config = new JObject()
{
{
"settings", new JObject()
{
{"isMaintaining", false}
}
},
{
"config", new JObject()
{
{"multiplayerServerUrl", multiplayerServerUrl},
{"multiplayerServerPort", port},
{"redisServerUrl", redisUrl},
{"redisServerPort", redisPort},
{"redisServerPassword", redisPassword},
}
}
};
var dataDir = new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "data"));
var songsDir = new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "data", "static", "Songs"));
if (!dataDir.Exists) dataDir.Create();
if (!songsDir.Exists) songsDir.Create();
File.WriteAllText(Path.Combine(AppContext.BaseDirectory, "data", "config.json"), config.ToString(), Encoding.UTF8);
Console.WriteLine("请重启程序以使设置生效");
Thread.Sleep(5000);
Environment.Exit(0);
}
else
{
Console.WriteLine("Detected exist configuration and data store, now starting api...");
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && args.Contains("--background"))
{
DirectoryInfo logFolder;
logFolder = !Directory.Exists(Path.Combine(AppContext.BaseDirectory, "data", "Logs"))
? Directory.CreateDirectory(Path.Combine(AppContext.BaseDirectory, "data", "Logs"))
: new DirectoryInfo(Path.Combine(AppContext.BaseDirectory, "data", "Logs"));
var newLog = string.Concat(DateTime.Now.ToString("yyyyMMddHHmmssfff"), ".log");
_logWriter = new ConsoleWriter() {Tag = Path.Combine(AppContext.BaseDirectory, "data", "Logs", newLog)};
_logWriter.OnOutput += SaveLog;
Console.WriteLine($"[{DateTime.Now:yyyy-M-d H:mm:ss}] Information: Detected '--background' argument. All logs will output to file {Path.Combine(AppContext.BaseDirectory, "data", "Logs", newLog)}.");
Console.SetOut(_logWriter);
}
}
Console.CancelKeyPress += StopServer;
UdpBuilder();
StopServer(null, EventArgs.Empty);
}
private static void SaveLog(object? sender, TextEventArgs e)
{
var logFile = ((ConsoleWriter)sender!).Tag;
File.AppendAllText(logFile, e.Text);
}
private static void UdpBuilder()
{
_server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
_server.Bind(new IPEndPoint(IPAddress.Parse(MultiplayerServerUrl), MultiplayerServerPort));//绑定端口号和IP
Console.WriteLine("Server Initialized, Now starting to process UDP");
ReceiveMsg();
}
/// <summary>
/// 向特定ip的主机的端口发送数据报
/// </summary>
/// <param name="data">需要发出的数据包</param>
/// <param name="token">获取token</param>
/// <param name="endPoint">数据要到达的终止点,可在ReceiveMsg中获得( <see cref="EndPoint"/> )</param>
public static void SendMsg(byte[] data, byte[] token, EndPoint endPoint)
{
try
{
var encryptedData = LinkPlayCrypto.EncryptPack(token, data);
_server?.SendTo(encryptedData, endPoint);
}
catch (Exception e) { Console.WriteLine(e); }
}
/// <summary>
/// 接收发送给本机ip对应端口号的数据报
/// </summary>
private static void ReceiveMsg()
{
try
{
while (true)
{
EndPoint point = new IPEndPoint(IPAddress.Any, 0);//用来保存发送方的ip和端口号
var buffer = new byte[1024];
if (_server == null) continue;
var length = _server.ReceiveFrom(buffer, ref point);//接收数据报
var message = LinkPlayCrypto.DecryptPack(buffer[..length]);
Console.WriteLine(point.ToString() + message);
LinkPlayParser.LinkPlayResp(message, point);
}
}
catch (Exception e) { Console.WriteLine(e); }
}
private static void StopServer(object? sender, EventArgs e)
{
_logWriter?.Dispose();
Console.WriteLine("Api stopped. Press any key to exit program.");
Console.ReadKey(true);
Environment.Exit(0);
}
}
}