Skip to content

Commit

Permalink
Merge pull request #4 from zkhssb/new
Browse files Browse the repository at this point in the history
Group Update
  • Loading branch information
zkhssb authored Aug 28, 2023
2 parents 066e912 + 1bc41f0 commit 9d25bc0
Show file tree
Hide file tree
Showing 72 changed files with 2,655 additions and 569 deletions.
73 changes: 73 additions & 0 deletions .github/workflows/dotnet-desktop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.

# This workflow will build, test, sign and package a WPF or Windows Forms desktop application
# built on .NET Core.
# To learn how to migrate your existing application to .NET Core,
# refer to https://docs.microsoft.com/en-us/dotnet/desktop-wpf/migration/convert-project-from-net-framework
#
# To configure this workflow:
#
# 1. Configure environment variables
# GitHub sets default environment variables for every workflow run.
# Replace the variables relative to your project in the "env" section below.
#
# 2. Signing
# Generate a signing certificate in the Windows Application
# Packaging Project or add an existing signing certificate to the project.
# Next, use PowerShell to encode the .pfx file using Base64 encoding
# by running the following Powershell script to generate the output string:
#
# $pfx_cert = Get-Content '.\SigningCertificate.pfx' -Encoding Byte
# [System.Convert]::ToBase64String($pfx_cert) | Out-File 'SigningCertificate_Encoded.txt'
#
# Open the output file, SigningCertificate_Encoded.txt, and copy the
# string inside. Then, add the string to the repo as a GitHub secret
# and name it "Base64_Encoded_Pfx."
# For more information on how to configure your signing certificate for
# this workflow, refer to https://github.com/microsoft/github-actions-for-desktop-apps#signing
#
# Finally, add the signing certificate password to the repo as a secret and name it "Pfx_Key".
# See "Build the Windows Application Packaging project" below to see how the secret is used.
#
# For more information on GitHub Actions, refer to https://github.com/features/actions
# For a complete CI/CD sample to get started with GitHub Action workflows for Desktop Applications,
# refer to https://github.com/microsoft/github-actions-for-desktop-apps

name: .NET Core Desktop

on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]

jobs:

build:

strategy:
matrix:
configuration: [Debug, Release]

runs-on: windows-latest # For a list of available runner types, refer to
# https://help.github.com/en/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on

steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Install .NET Core
uses: actions/setup-dotnet@v3
with:
dotnet-version: 7.0.x

- name: Restore dependencies
run: dotnet restore

- name: Build
run: dotnet build --no-restore
94 changes: 94 additions & 0 deletions NectarRCON.Adapter.Minecraft/MinecraftRconClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using NectarRCON.Export.Client;
using NectarRCON.Export.Interfaces;
using System.ComponentModel;

namespace NectarRCON.Adapter.Minecraft
{
[Description("rcon.minecraft")]
public class MinecraftRconClient : BaseTcpClient, IRconAdapter
{
// https://wiki.vg/RCON #Fragmentation
private static readonly int MaxMessageSize = 4110;

private readonly MemoryStream _buffer = new();
private readonly SemaphoreSlim _semaphore = new SemaphoreSlim(1);
private int lastId = 0;

public void Disconnect()
{
_semaphore.Wait();
try
{
Stop();
}
finally
{
_semaphore.Release();
}
}

public override void Dispose()
{
_semaphore.Dispose();
_buffer.Dispose();
base.Dispose();
}

public override byte[] Read(StreamReader reader)
{
byte[] buffer = new byte[MaxMessageSize];
int len = reader.BaseStream.Read(buffer, 0, buffer.Length);
Array.Resize(ref buffer, len);
return buffer;
}

public string Run(string command)
{
_semaphore.Wait();
try
{
Packet response = Send(new Packet(PacketType.Command, command));
return response.Body;
}
finally
{
_semaphore.Release();
}
}

public bool Connect(string address, int port)
{
_semaphore.Wait();
try
{
Start(address, port);
return IsConnected;
}
finally
{
_semaphore.Release();
}
}

public bool Authenticate(string password)
{
_semaphore.Wait();
try
{
Packet packet = Send(new Packet(PacketType.Authenticate, password));
return packet.Id == lastId;
}
finally
{
_semaphore.Release();
}
}

private Packet Send(Packet packet)
{
Interlocked.Increment(ref lastId);
packet.SetId(lastId);
return PacketEncoder.Decode(Send(packet.Encode()));
}
}
}
13 changes: 13 additions & 0 deletions NectarRCON.Adapter.Minecraft/NectarRCON.Adapter.Minecraft.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\NectarRCON.Export\NectarRCON.Export.csproj" />
</ItemGroup>

</Project>
41 changes: 41 additions & 0 deletions NectarRCON.Adapter.Minecraft/Packet.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Text;

namespace NectarRCON.Adapter.Minecraft;
public class Packet
{
public readonly int Length;
public int Id;
public readonly PacketType Type;
public readonly string Body;

public Packet(int length, int id, PacketType type, string body)
{
Length = length;
Id = id;
Type = type;
Body = body;
}

public Packet(PacketType type, string body)
{
Type = type;
Body = body;
}

public void SetId(int id)
{
Id = id;
}

public byte[] Encode()
{
List<byte> bytes = new List<byte>();
var data = Encoding.UTF8.GetBytes(Body);
bytes.AddRange(BitConverter.GetBytes(PacketEncoder.HeaderLength + data.Length));
bytes.AddRange(BitConverter.GetBytes(Id));
bytes.AddRange(BitConverter.GetBytes((int)Type));
bytes.AddRange(data);
bytes.AddRange(new byte[] { 0, 0 });
return bytes.ToArray();
}
}
45 changes: 45 additions & 0 deletions NectarRCON.Adapter.Minecraft/PacketEncoder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Text;

namespace NectarRCON.Adapter.Minecraft
{
public enum PacketType : int
{
Response, // 0: Command response
_,
Command, // 2: Command
Authenticate // 3: Login
}

public class PacketEncoder
{
public const int HeaderLength = 10;

public static byte[] Encode(Packet msg)
{
List<byte> bytes = new List<byte>();

bytes.AddRange(BitConverter.GetBytes(msg.Length));
bytes.AddRange(BitConverter.GetBytes(msg.Id));
bytes.AddRange(BitConverter.GetBytes((int)msg.Type));
bytes.AddRange(Encoding.UTF8.GetBytes(msg.Body));
bytes.AddRange(new byte[] { 0, 0 });

return bytes.ToArray();
}

public static Packet Decode(byte[] bytes)
{
if (bytes.Length < HeaderLength) { throw new ArgumentException("packet length too short"); }
int len = BitConverter.ToInt32(bytes, 0);
int id = BitConverter.ToInt32(bytes, 4);
int type = BitConverter.ToInt32(bytes, 8);
int bodyLen = bytes.Length - (HeaderLength + 4);
string body = string.Empty;
if (bodyLen > 0)
{
body = Encoding.UTF8.GetString(bytes, 12, bodyLen);
}
return new Packet(len, id, (PacketType)type, body);
}
}
}
3 changes: 3 additions & 0 deletions NectarRCON.Adapter.Minecraft/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Adapter

MinecraftRcon实现
12 changes: 12 additions & 0 deletions NectarRCON.Core/Helper/AdapterHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using NectarRCON.Adapter.Minecraft;
using NectarRCON.Export.Interfaces;
namespace NectarRCON.Core.Helper
{
public static class AdapterHelpers
{
public static IRconAdapter? CreateAdapterInstance(string adapter)
{
return new MinecraftRconClient(); // 暂时这么写
}
}
}
33 changes: 33 additions & 0 deletions NectarRCON.Core/Helper/DNSHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using DnsClient;

namespace NectarRCON.Core.Helper
{
public class DNSHelpers
{
public static string AQuery(string host)
{
var lookup = new LookupClient();
var result = lookup.Query(host, QueryType.A);
var record = result.Answers.ARecords().FirstOrDefault();
return record?.Address.ToString() ?? string.Empty;
}

/// <summary>
/// MinecraftSRV解析
/// </summary>
/// <returns>成功返回ip:port</returns>
public static string SRVQuery(string host)
{
// Minecraft特有的srv
string srvAddress = $"_minecraft._tcp.{host}";
var lookup = new LookupClient();
var result = lookup.Query(srvAddress, QueryType.SRV);
var record = result.Answers.SrvRecords().FirstOrDefault();
if (record != null)
{
return $"{record.Target.Value}:{record.Port}";
}
return string.Empty;
}
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace NectarRCON.Helper;
namespace NectarRCON.Core.Helper;
public static class Win32Helper
{
public static bool GetWindowsTheme()
Expand Down
18 changes: 18 additions & 0 deletions NectarRCON.Core/NectarRCON.Core.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="DnsClient" Version="1.7.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\NectarRCON.Adapter.Minecraft\NectarRCON.Adapter.Minecraft.csproj" />
<ProjectReference Include="..\NectarRCON.Export\NectarRCON.Export.csproj" />
</ItemGroup>

</Project>
Loading

0 comments on commit 9d25bc0

Please sign in to comment.