Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,16 @@ jobs:
- name: Build Ptr
run: dotnet build src/Ptr/Ptr.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:VersionSuffix=${{ steps.get_version.outputs.commit_count }}

- name: Build modules
run: |
dotnet build src/Ptr.Modules.MapManager/Ptr.Modules.MapManager.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:VersionSuffix=${{ steps.get_version.outputs.commit_count }}
dotnet build src/Sharp.Modules.AdminManager/Sharp.Modules.AdminManager.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:VersionSuffix=${{ steps.get_version.outputs.commit_count }}
dotnet build src/Sharp.Modules.CommandManager/Sharp.Modules.CommandManager.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:VersionSuffix=${{ steps.get_version.outputs.commit_count }}

- name: Build Ptr.Shared
run: dotnet build src/Ptr.Shared/Ptr.Shared.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:VersionSuffix=${{ steps.get_version.outputs.commit_count }}
run: dotnet build src/Sharp.Modules.AdminManager.Shared/Sharp.Modules.AdminManager.Shared.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:VersionSuffix=${{ steps.get_version.outputs.commit_count }}
run: dotnet build src/Sharp.Modules.CommandManager.Shared/Sharp.Modules.CommandManager.Shared.csproj --configuration ${{ env.CONFIGURATION }} --no-restore /p:VersionSuffix=${{ steps.get_version.outputs.commit_count }}

# Prepare release artifacts
- name: Prepare Ptr module artifact
Expand All @@ -55,6 +63,24 @@ jobs:
if [ -f src/Ptr/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.pdb ]; then
cp src/Ptr/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.pdb release/sharp/modules/Ptr/
fi

mkdir -p release/sharp/modules/Ptr.Modules.MapManager
cp src/Ptr.Modules.MapManager/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Modules.MapManager.dll release/sharp/modules/Ptr.Modules.MapManager/
if [ -f src/Ptr.Modules.MapManager/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Modules.MapManager.pdb ]; then
cp src/Ptr.Modules.MapManager/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Modules.MapManager.pdb release/sharp/modules/Ptr.Modules.MapManager/
fi

mkdir -p release/sharp/modules/Sharp.Modules.AdminManager
cp src/Sharp.Modules.AdminManager/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.AdminManager.dll release/sharp/modules/Sharp.Modules.AdminManager/
if [ -f src/Sharp.Modules.AdminManager/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.AdminManager.pdb ]; then
cp src/Sharp.Modules.AdminManager/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.AdminManager.pdb release/sharp/modules/Sharp.Modules.AdminManager/
fi

mkdir -p release/sharp/modules/Sharp.Modules.CommandManager
cp src/Sharp.Modules.CommandManager/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.CommandManager.dll release/sharp/modules/Sharp.Modules.CommandManager/
if [ -f src/Sharp.Modules.CommandManager/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.CommandManager.pdb ]; then
cp src/Sharp.Modules.CommandManager/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.CommandManager.pdb release/sharp/modules/Sharp.Modules.CommandManager/
fi

- name: Prepare Ptr.Shared artifact
run: |
Expand All @@ -64,6 +90,25 @@ jobs:
if [ -f src/Ptr.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Shared.pdb ]; then
cp src/Ptr.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Shared.pdb release/sharp/shared/Ptr.Shared/
fi

mkdir -p release/sharp/shared/Ptr.Modules.MapManager.Shared
cp src/Ptr.Modules.MapManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Modules.MapManager.Shared.dll release/sharp/shared/Ptr.Modules.MapManager.Shared/
if [ -f src/Ptr.Modules.MapManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Modules.MapManager.Shared.pdb ]; then
cp src/Ptr.Modules.MapManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Ptr.Modules.MapManager.Shared.pdb release/sharp/shared/Ptr.Modules.MapManager.Shared/
fi

mkdir -p release/sharp/shared/Sharp.Modules.AdminManager.Shared
cp src/Sharp.Modules.AdminManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.AdminManager.Shared.dll release/sharp/shared/Sharp.Modules.AdminManager.Shared/
if [ -f src/Sharp.Modules.AdminManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.AdminManager.Shared.pdb ]; then
cp src/Sharp.Modules.AdminManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.AdminManager.Shared.pdb release/sharp/shared/Sharp.Modules.AdminManager.Shared/
fi

mkdir -p release/sharp/shared/Sharp.Modules.CommandManager.Shared
cp src/Sharp.Modules.CommandManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.CommandManager.Shared.dll release/sharp/shared/Sharp.Modules.CommandManager.Shared/
if [ -f src/Sharp.Modules.CommandManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.CommandManager.Shared.pdb ]; then
cp src/Sharp.Modules.CommandManager.Shared/bin/${{ env.CONFIGURATION }}/net10.0/Sharp.Modules.CommandManager.Shared.pdb release/sharp/shared/Sharp.Modules.CommandManager.Shared/
fi


# Copy assets (gamedata, configs, etc.)
- name: Copy assets
Expand Down
6 changes: 6 additions & 0 deletions Ptr.slnx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
<Solution>
<Folder Name="/src/">
<File Path="src/Directory.Build.props" />
<Project Path="src/Ptr.Modules.MapManager.Shared/Ptr.Modules.MapManager.Shared.csproj" />
<Project Path="src/Ptr.Modules.MapManager/Ptr.Modules.MapManager.csproj" />
<Project Path="src/Ptr.Shared/Ptr.Shared.csproj" />
<Project Path="src/Ptr/Ptr.csproj" />
<Project Path="src/Sharp.Modules.AdminManager.Shared/Sharp.Modules.AdminManager.Shared.csproj" />
<Project Path="src/Sharp.Modules.AdminManager/Sharp.Modules.AdminManager.csproj" />
<Project Path="src/Sharp.Modules.CommandManager.Shared/Sharp.Modules.CommandManager.Shared.csproj" />
<Project Path="src/Sharp.Modules.CommandManager/Sharp.Modules.CommandManager.csproj" />
</Folder>
</Solution>
78 changes: 78 additions & 0 deletions src/Ptr.Modules.MapManager.Shared/IMapManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
namespace Ptr.Modules.MapManager.Shared;

/// <summary>
/// Map voting style
/// </summary>
public enum EMapVoteStyle
{
/// <summary>
/// Native CS2 Endgame panorama vote
/// </summary>
Native,

/// <summary>
/// Menu vote
/// </summary>
Menu,

/// <summary>
/// Custom voting style
/// </summary>
Custom
}

/// <summary>
/// Game Map
/// </summary>
public interface IGameMap
{
/// <summary>
/// Map name, for example: de_dust2. <br />
/// For workshop map, you have to inspect the actual map name by yourself.
/// </summary>
string MapName { get; }

/// <summary>
/// Countdown.
/// </summary>
int Countdown { get; }

/// <summary>
/// Minimal players that you can vote.
/// </summary>
int MinPlayers { get; }

/// <summary>
/// Maximum players that you can vote.
/// </summary>
int MaxPlayers { get; }

/// <summary>
/// Is this map workshop map?
/// </summary>
bool IsWorkshopMap { get; }

/// <summary>
/// Map workshop id.
/// </summary>
ulong? WorkshopId { get; }
}

public delegate void DelegateOnMapConfigLoaded();

public interface IMapManager
{
const string Identity = nameof(IMapManager);

event DelegateOnMapConfigLoaded? MapConfigLoaded;

IEnumerable<IGameMap> GetMaps();

void SetMapVoteStyle(EMapVoteStyle style);

bool IsWorkshopMap(string mapName);

void ChangeLevel(string mapName);

void ChangeLevel(IGameMap map);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Ptr.Shared\Ptr.Shared.csproj" Private="false" ExcludeAssets="all"/>
</ItemGroup>

</Project>
64 changes: 64 additions & 0 deletions src/Ptr.Modules.MapManager/Hooks/ApplyGameSettingsHook.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging;
using Ptr.Shared.Hooks.Abstractions;
using Sharp.Shared;
using Sharp.Shared.Hooks;
using Sharp.Shared.Objects;

namespace Ptr.Modules.MapManager.Hooks;

public unsafe class ApplyGameSettingsHook : AbstractVirtualHook<ApplyGameSettingsHook>
{
private static ApplyGameSettingsHook _sInstance = null!;
private static nint _sTrampoline = nint.Zero;
private readonly ISharedSystem _sharedSystem;

public ApplyGameSettingsHook(IModSharpModule module, string name, ISharedSystem sharedSystem,
ILogger<ApplyGameSettingsHook> logger) : base(
module, name, sharedSystem, logger)
{
_sharedSystem = sharedSystem;
_sInstance = this;
}

protected override void Prepare(IVirtualHook hook)
{
hook.Prepare(Dll, Class, Function, (nint)(delegate* unmanaged<nint, nint, void>)&Hook);
}

protected override void InternalShutdown()
{
_sTrampoline = nint.Zero;
}

protected override void InternalPostInstall(IntPtr trampoline)
{
_sTrampoline = trampoline;
}

private void ReadConfig(IKeyValues kv)
{
var mapGroup = kv.FindKey("launchoptions")?.GetString("mapgroup") ?? string.Empty;
InterfaceBridge.Instance.CurrentMapGroup = mapGroup;
}

[UnmanagedCallersOnly]
public static void Hook(nint pService, nint pKeyValues)
{
var trampoline = (delegate* unmanaged<nint, nint, void>)_sTrampoline;

if (_sInstance.CreateKeyValues(pKeyValues) is { } kv)
{
_sInstance.ReadConfig(kv);
}

trampoline(pService, pKeyValues);
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private IKeyValues? CreateKeyValues(nint ptr)
{
return ptr == nint.Zero ? null : _sharedSystem.GetModSharp().CreateNativeObject<IKeyValues>(ptr);
}
}
145 changes: 145 additions & 0 deletions src/Ptr.Modules.MapManager/InterfaceBridge.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// ReSharper disable UnusedParameter.Local

#pragma warning disable IDE0290

using Microsoft.Extensions.Configuration;
using Ptr.Modules.MapManager.Shared;
using Ptr.Shared.Misc;
using Sharp.Modules.CommandManager.Shared;
using Sharp.Shared;
using Sharp.Shared.Managers;
using Sharp.Shared.Objects;

namespace Ptr.Modules.MapManager;

internal record GameMapManifest(string MapName, int? Countdown, int? MinPlayers, int? MaxPlayers, ulong? WorkshopId);

internal class GameMap : IGameMap
{
public GameMap(string name, int countdown, int minPlayers, int maxPlayers)
{
MapName = name;
Countdown = countdown;
MinPlayers = minPlayers;
MaxPlayers = maxPlayers;
}

public string MapName { get; init; }
public int Countdown { get; init; }
public int MinPlayers { get; init; }
public int MaxPlayers { get; init; }

public bool IsWorkshopMap => WorkshopId is not null;

public ulong? WorkshopId { get; set; }
}

internal class PreviousGameMap
{
public PreviousGameMap(string mapName)
{
MapName = mapName;
}

public string MapName { get; }
public int RemainingTimes { get; set; }
}

/// <summary>
/// Global context.
/// </summary>
internal class InterfaceBridge
{
private readonly ISharedSystem _sharedSystem;


public InterfaceBridge(ISharedSystem sharedSystem,
string dllPath,
string sharpPath,
Version version,
IConfiguration coreConfiguration,
bool hotReload,
ChatMessageFormatter formatter, MapManager mapManager)
{
_sharedSystem = sharedSystem;
MapManager = mapManager;
DllPath = dllPath;
SharpPath = sharpPath;
Version = version;
CoreConfiguration = coreConfiguration;
IsHotReload = hotReload;
ChatFormatter = formatter;
ModuleIdentity = Path.GetFileName(dllPath);
Instance = this;
}

public MapManager MapManager { get; init; }
public string ModuleIdentity { get; init; }

/// <summary>
/// 开洞,一般情况下别用!
/// </summary>
internal static InterfaceBridge Instance { get; private set; } = null!;

public ISteamApi SteamApi => ModSharp.GetSteamGameServer();

public IEntityManager EntityManager => _sharedSystem.GetEntityManager();
public IClientManager ClientManager => _sharedSystem.GetClientManager();
public IConVarManager ConVarManager => _sharedSystem.GetConVarManager();
public ITransmitManager TransmitManager => _sharedSystem.GetTransmitManager();
public IHookManager HookManager => _sharedSystem.GetHookManager();
public IEventManager EventManager => _sharedSystem.GetEventManager();
public IFileManager FileManager => _sharedSystem.GetFileManager();
public ISchemaManager SchemaManager => _sharedSystem.GetSchemaManager();
public IEconItemManager EconItemManager => _sharedSystem.GetEconItemManager();
public ILibraryModuleManager LibraryModuleManager => _sharedSystem.GetLibraryModuleManager();
public ISoundManager SoundManager => _sharedSystem.GetSoundManager();
public IPhysicsQueryManager PhysicsQueryManager => _sharedSystem.GetPhysicsQueryManager();

public IModSharp ModSharp => _sharedSystem.GetModSharp();

/// <summary>
/// CGlobalVars* gpGlobals,没什么好说的。<br />
/// 注意,一定要在地图加载之后调用!不然服务器第一次加载的时候是拿不到的!
/// </summary>
public IGlobalVars GlobalVars => ModSharp.GetGlobals();

/// <summary>
/// CGameRules* g_pGameRules <br />
/// 注意,一定要在地图加载之后调用!不然服务器第一次加载的时候是拿不到的!
/// </summary>
public IGameRules GameRules => ModSharp.GetGameRules();

public INetworkServer Server => ModSharp.GetIServer();
public IGameData GameData => ModSharp.GetGameData();
public ISharpModuleManager SharpModuleManager => _sharedSystem.GetSharpModuleManager();

public ChatMessageFormatter ChatFormatter { get; init; }

public string DllPath { get; init; }

public string SharpPath { get; init; }

public Version? Version { get; init; }

public IConfiguration? CoreConfiguration { get; init; }

public bool IsHotReload { get; init; }

public List<PreviousGameMap> PreviousGameMaps { get; init; } = [];

public List<IGameMap> Maps { get; init; } = [];

public List<string> NominatedMaps { get; init; } = [];

public EMapVoteStyle MapVoteStyle { get; set; } = EMapVoteStyle.Native;

public DateTime AllowVoteTime { get; set; }

/// <summary>
/// 开洞,一般情况下别用!
/// </summary>
public string CurrentMapGroup { get; set; } = string.Empty;

//public ICommandRegistry CommandRegistry { get; set; } = null!;
}
Loading