forked from Raphael/SCHALE.GameServer
Refactor and Optimize Client
This commit is contained in:
parent
23876dfdea
commit
33995fb87a
|
@ -1,17 +0,0 @@
|
|||
using Microsoft.AspNetCore.Mvc;
|
||||
using SCHALE.GameServer.Services;
|
||||
|
||||
namespace SCHALE.GameClient.Controllers
|
||||
{
|
||||
public class ClientController : Controller
|
||||
{
|
||||
private readonly ILogger<ClientController> _logger;
|
||||
private readonly PrivateClientService _privateClientService;
|
||||
|
||||
public ClientController(ILogger<ClientController> logger, PrivateClientService privateClientService)
|
||||
{
|
||||
_logger = logger;
|
||||
_privateClientService = privateClientService;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,92 +1,156 @@
|
|||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Newtonsoft.Json;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using MX.Core.Crypto;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SCHALE.Common.Crypto;
|
||||
using SCHALE.Common.Crypto.XXHash;
|
||||
using SCHALE.Common.FlatData;
|
||||
using SCHALE.Common.NetworkProtocol;
|
||||
using SCHALE.GameServer.Services;
|
||||
using SCHALE.GameServer.Utils;
|
||||
using Serilog;
|
||||
using Serilog.Events;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SCHALE.GameServer
|
||||
namespace SCHALE.GameServer.Services
|
||||
{
|
||||
public class GameServer
|
||||
public class GameClient
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
private readonly HttpClient httpClient;
|
||||
|
||||
public static readonly string PS_URL = "http://10.0.0.149/api/gateway";
|
||||
public static readonly string MITM_URL = "http://10.0.0.149:8080";
|
||||
public static readonly string OFFICIAL_API_URL = "https://prod-game.bluearchiveyostar.com:5000/api/gateway";
|
||||
|
||||
private long AccountServerId = -1;
|
||||
private string MxToken = "";
|
||||
private long Hash = 0;
|
||||
|
||||
public GameClient()
|
||||
{
|
||||
var config = new ConfigurationBuilder()
|
||||
.SetBasePath(Path.GetDirectoryName(AppContext.BaseDirectory)!)
|
||||
.AddJsonFile("appsettings.json")
|
||||
.AddJsonFile(
|
||||
$"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json",
|
||||
true
|
||||
)
|
||||
.AddJsonFile("appsettings.Local.json", true)
|
||||
.Build();
|
||||
|
||||
{
|
||||
var logFilePath = Path.Combine(
|
||||
Path.GetDirectoryName(AppContext.BaseDirectory)!,
|
||||
"logs",
|
||||
"log.txt"
|
||||
);
|
||||
|
||||
if (File.Exists(logFilePath))
|
||||
{
|
||||
var prevLogFilePath = Path.Combine(
|
||||
Path.GetDirectoryName(logFilePath)!,
|
||||
"log-prev.txt"
|
||||
);
|
||||
if (File.Exists(prevLogFilePath))
|
||||
File.Delete(prevLogFilePath);
|
||||
|
||||
File.Move(logFilePath, prevLogFilePath);
|
||||
}
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.WriteTo.Console()
|
||||
.WriteTo.File(
|
||||
logFilePath,
|
||||
restrictedToMinimumLevel: LogEventLevel.Verbose,
|
||||
shared: true
|
||||
)
|
||||
.ReadFrom.Configuration(config)
|
||||
.CreateBootstrapLogger();
|
||||
.WriteTo.File("logs/log.txt", rollingInterval: RollingInterval.Day)
|
||||
.CreateLogger();
|
||||
|
||||
Log.Information("Application starting up...");
|
||||
|
||||
httpClient = new HttpClient();
|
||||
}
|
||||
|
||||
Log.Information("Starting...");
|
||||
try
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
GameClient gameClient = new GameClient();
|
||||
|
||||
builder.Services.Configure<KestrelServerOptions>(op =>
|
||||
op.AllowSynchronousIO = true
|
||||
);
|
||||
builder.Host.UseSerilog();
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllers();
|
||||
|
||||
builder.Services.AddHttpClient<PrivateClientService>();
|
||||
builder.Services.AddSingleton<PrivateClientService>();
|
||||
builder.Services.AddPrivateClientService();
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
// Configure the HTTP request pipeline.
|
||||
app.UseAuthorization();
|
||||
app.UseSerilogRequestLogging();
|
||||
|
||||
app.MapControllers();
|
||||
|
||||
app.Run();
|
||||
} catch (Exception ex)
|
||||
if (args.Length < 2 && (gameClient.AccountServerId == -1 || gameClient.MxToken == ""))
|
||||
{
|
||||
Log.Fatal(ex, "An unhandled exception occurred during runtime");
|
||||
} finally
|
||||
{
|
||||
Log.CloseAndFlush();
|
||||
Log.Information("Please input the nessary data.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (gameClient.AccountServerId == -1)
|
||||
{
|
||||
gameClient.AccountServerId = int.Parse(args[0]);
|
||||
}
|
||||
|
||||
if (gameClient.MxToken.IsNullOrEmpty())
|
||||
{
|
||||
gameClient.MxToken = args[1];
|
||||
}
|
||||
|
||||
await gameClient.SendPostRequestAsync(OFFICIAL_API_URL, new AcademyGetInfoRequest(){ });
|
||||
/*
|
||||
await gameClient.SendPostRequestAsync(OFFICIAL_API_URL, new ShopBuyGacha3Request()
|
||||
{
|
||||
FreeRecruitId = 0,
|
||||
Cost = new()
|
||||
{
|
||||
ParcelInfos = [
|
||||
new()
|
||||
{
|
||||
Key = new()
|
||||
{
|
||||
Type = ParcelType.Currency,
|
||||
Id = 4,
|
||||
},
|
||||
Amount = 120,
|
||||
Multiplier = new(10000),
|
||||
Probability = new(10000)
|
||||
}
|
||||
],
|
||||
|
||||
Currency = new()
|
||||
{
|
||||
currencyValue = new()
|
||||
{
|
||||
Values = new()
|
||||
{
|
||||
{ CurrencyTypes.Gem, 120 }
|
||||
},
|
||||
Tickets = new() { },
|
||||
Property = new() { },
|
||||
Gem = 120,
|
||||
IsEmpty = false
|
||||
},
|
||||
|
||||
Gold = 0,
|
||||
Gem = 120,
|
||||
|
||||
},
|
||||
EquipmentDBs = [],
|
||||
ItemDBs = [],
|
||||
FurnitureDBs = [],
|
||||
ConsumeCondition = 0,
|
||||
},
|
||||
GoodsId = 35840,
|
||||
ShopUniqueId = 50668,
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
public async Task SendPostRequestAsync<T>(string url, T requestPacket) where T : RequestPacket
|
||||
{
|
||||
requestPacket.SessionKey = new()
|
||||
{
|
||||
MxToken = this.MxToken,
|
||||
AccountServerId = this.AccountServerId,
|
||||
};
|
||||
|
||||
requestPacket.Hash = this.Hash;
|
||||
requestPacket.Resendable = true;
|
||||
requestPacket.ClientUpTime = 0;
|
||||
requestPacket.IsTest = false;
|
||||
|
||||
string packetJsonStr = JsonSerializer.Serialize((T)requestPacket);
|
||||
|
||||
Log.Information("Sending Post Request to " + url);
|
||||
Log.Information($"Payload: {packetJsonStr}");
|
||||
|
||||
byte[] payload = PacketCryptManager.Instance.RequestToBinary(requestPacket.Protocol, packetJsonStr);
|
||||
|
||||
//File.WriteAllBytes("./mx.dat", payload);
|
||||
Log.Information("Written All Bytes");
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, url);
|
||||
request.Headers.Add("mx", "1");
|
||||
request.Headers.Add("Bundle-Version", "li3pmyogha");
|
||||
|
||||
var content = new MultipartFormDataContent();
|
||||
content.Add(new StreamContent(new MemoryStream(payload)), "mx", ".mx.dat");
|
||||
request.Content = content;
|
||||
|
||||
Log.Information("Sending POST Request!");
|
||||
var response = await httpClient.SendAsync(request);
|
||||
|
||||
// Response
|
||||
Log.Information("Response Details:");
|
||||
Log.Information($"Status Code: {response.StatusCode}");
|
||||
string responseBody = await response.Content.ReadAsStringAsync();
|
||||
Log.Information("Response Body:");
|
||||
Log.Information(responseBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:22994",
|
||||
"sslPort": 44306
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "http://localhost:5141",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"applicationUrl": "https://localhost:7267;http://localhost:5141",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
|
@ -1,161 +0,0 @@
|
|||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding.Binders;
|
||||
using MX.Core.Crypto;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using SCHALE.Common.Crypto;
|
||||
using SCHALE.Common.Crypto.XXHash;
|
||||
using SCHALE.Common.FlatData;
|
||||
using SCHALE.Common.NetworkProtocol;
|
||||
using SCHALE.GameServer.Utils;
|
||||
using Serilog;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text.Json;
|
||||
|
||||
namespace SCHALE.GameServer.Services
|
||||
{
|
||||
public class PrivateClientService : BackgroundService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
|
||||
public static readonly string PS_URL = "http://10.0.0.149/api/gateway";
|
||||
public static readonly string MITM_URL = "http://10.0.0.149:8080";
|
||||
public static readonly string OFFICIAL_API_URL = "http://prod-gateway.bluearchiveyostar.com:5100/api/";
|
||||
|
||||
private readonly long AccountServerId = -1;
|
||||
private readonly string MxToken = "";
|
||||
private readonly long Hash = 0;
|
||||
|
||||
public PrivateClientService(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
//await SendPostRequestAsync(OFFICIAL_API_URL, new AcademyGetInfoRequest(){ });
|
||||
|
||||
await SendPostRequestAsync(OFFICIAL_API_URL, new ShopBuyGacha3Request()
|
||||
{
|
||||
FreeRecruitId = 0,
|
||||
Cost = new()
|
||||
{
|
||||
ParcelInfos = [
|
||||
new()
|
||||
{
|
||||
Key = new()
|
||||
{
|
||||
Type = ParcelType.Currency,
|
||||
Id = 4,
|
||||
},
|
||||
Amount = 120,
|
||||
Multiplier = new(10000),
|
||||
Probability = new(10000)
|
||||
}
|
||||
],
|
||||
|
||||
Currency = new()
|
||||
{
|
||||
currencyValue = new()
|
||||
{
|
||||
Values = new()
|
||||
{
|
||||
{ CurrencyTypes.Gem, 120 }
|
||||
},
|
||||
Tickets = new() { },
|
||||
Property = new() { },
|
||||
Gem = 120,
|
||||
IsEmpty = false
|
||||
},
|
||||
|
||||
Gold = 0,
|
||||
Gem = 120,
|
||||
|
||||
},
|
||||
EquipmentDBs = [],
|
||||
ItemDBs = [],
|
||||
FurnitureDBs = [],
|
||||
ConsumeCondition = 0,
|
||||
},
|
||||
GoodsId = 35840,
|
||||
ShopUniqueId = 50668,
|
||||
});
|
||||
}
|
||||
|
||||
public async Task SendPostRequestAsync<T>(string url, T requestPacket) where T : RequestPacket
|
||||
{
|
||||
requestPacket.SessionKey = new()
|
||||
{
|
||||
MxToken = this.MxToken,
|
||||
AccountServerId = this.AccountServerId,
|
||||
};
|
||||
|
||||
requestPacket.Hash = this.Hash;
|
||||
requestPacket.Resendable = true;
|
||||
requestPacket.ClientUpTime = 0;
|
||||
requestPacket.IsTest = false;
|
||||
|
||||
string packetJsonStr = JsonSerializer.Serialize((T)requestPacket);
|
||||
|
||||
Log.Information("Sending Post Request to " + url);
|
||||
Log.Information($"Payload: {packetJsonStr}");
|
||||
|
||||
byte[] payload = PacketCryptManager.Instance.RequestToBinary(requestPacket.Protocol, packetJsonStr);
|
||||
|
||||
File.WriteAllBytes("./mx.dat", payload);
|
||||
Log.Information("Writeen All Bytes");
|
||||
|
||||
return;
|
||||
|
||||
using var fileStream = new FileStream("./mx.dat", FileMode.Create, FileAccess.Write);
|
||||
using var binaryWriterFile = new BinaryWriter(fileStream);
|
||||
|
||||
binaryWriterFile.Write(payload);
|
||||
|
||||
var mxFile = new StreamContent(binaryWriterFile.BaseStream);
|
||||
|
||||
mxFile.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
|
||||
|
||||
// Add the in-memory content as a file with a name
|
||||
var boundary = "BestHTTP_HTTPMultiPartForm_328B5160";
|
||||
using var content = new MultipartFormDataContent(boundary);
|
||||
|
||||
content.Add(mxFile, "mx", "1");
|
||||
|
||||
content.Headers.ContentType = new MediaTypeHeaderValue("multipart/form-data");
|
||||
content.Headers.ContentType.Parameters.Add(new NameValueHeaderValue("boundary", boundary));
|
||||
|
||||
// Set up custom headers to match the request shown
|
||||
_httpClient.DefaultRequestHeaders.AcceptEncoding.Add(new StringWithQualityHeaderValue("gzip"));
|
||||
_httpClient.DefaultRequestHeaders.Add("Bundle-Version", "li3pmyogha");
|
||||
_httpClient.DefaultRequestHeaders.Connection.Add("Keep-Alive");
|
||||
_httpClient.DefaultRequestHeaders.Connection.Add("TE");
|
||||
_httpClient.DefaultRequestHeaders.Add("Keep-Alive", "timeout=21");
|
||||
//_httpClient.DefaultRequestHeaders.Add("TE", "identity");
|
||||
_httpClient.DefaultRequestHeaders.UserAgent.ParseAdd("BestHTTP/2 v2.4.0");
|
||||
|
||||
|
||||
// Send the POST request
|
||||
HttpResponseMessage response = await _httpClient.PostAsync(url, content);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
string responseData = await response.Content.ReadAsStringAsync();
|
||||
Log.Information("Success: " + responseData);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
Log.Information($"Error: {response.StatusCode}");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
internal static class PrivateClientServiceExtensions
|
||||
{
|
||||
public static void AddPrivateClientService(this IServiceCollection services)
|
||||
{
|
||||
services.AddHostedService<PrivateClientService>();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Information",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
{
|
||||
"Serilog": {
|
||||
"MinimumLevel": {
|
||||
"Default": "Information",
|
||||
"Override": {
|
||||
"Microsoft": "Warning",
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
|
@ -7,7 +7,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SCHALE.GameServer", "SCHALE
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SCHALE.Common", "SCHALE.Common\SCHALE.Common.csproj", "{D8ED8CB5-EA39-46BE-9236-7FC1F46FE15B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SCHALE.GameClient", "SCHALE.GameClient\SCHALE.GameClient.csproj", "{EBA95AE2-BBCA-4386-ADB3-FC6EC2102E88}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SCHALE.GameClient", "SCHALE.GameClient\SCHALE.GameClient.csproj", "{27F99AC7-2101-48F3-AF4E-8AC1AA78FB32}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -23,10 +23,10 @@ Global
|
|||
{D8ED8CB5-EA39-46BE-9236-7FC1F46FE15B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D8ED8CB5-EA39-46BE-9236-7FC1F46FE15B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D8ED8CB5-EA39-46BE-9236-7FC1F46FE15B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EBA95AE2-BBCA-4386-ADB3-FC6EC2102E88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EBA95AE2-BBCA-4386-ADB3-FC6EC2102E88}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EBA95AE2-BBCA-4386-ADB3-FC6EC2102E88}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EBA95AE2-BBCA-4386-ADB3-FC6EC2102E88}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{27F99AC7-2101-48F3-AF4E-8AC1AA78FB32}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{27F99AC7-2101-48F3-AF4E-8AC1AA78FB32}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{27F99AC7-2101-48F3-AF4E-8AC1AA78FB32}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{27F99AC7-2101-48F3-AF4E-8AC1AA78FB32}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Loading…
Reference in New Issue