Skip to content

Commit

Permalink
Merge branch 'main' into virtual-hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
KillStr3aK authored Nov 26, 2024
2 parents 78639d4 + b2046b2 commit e56eb54
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 6 deletions.
1 change: 1 addition & 0 deletions .github/workflows/publish-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ on:
push:
branches:
- main
workflow_dispatch:

permissions:
contents: read
Expand Down
3 changes: 3 additions & 0 deletions docfx/docs/features/game-events.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ The specific subclass of `GameEvent` will provide strongly typed parameters from

These event properties are mutable so you can update them as normal and they will update in the event instance.

> [!CAUTION]
> `GameEvent` instances and their properties will cease to exist after the event listener function is called, which means that you will encounter errors when accessing properties in timers and functions like `Server.NextFrame()`. You should store the value of properties in variables before calling functions like `Server.NextFrame()` so you can read the data safely.
## Preventing Broadcast

You can modify a game event so that it does not get broadcast to clients by modifying the `bool info.DontBroadcast` property. e.g.
Expand Down
File renamed without changes.
3 changes: 3 additions & 0 deletions docfx/docs/guides/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@

- name: Dependency Injection
href: dependency-injection.md

- name: Referencing Players
href: referencing-players.md
5 changes: 1 addition & 4 deletions docfx/docs/reference/toc.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,2 @@
- name: Core Configuration
href: core-configuration.md

- name: Referencing Players
href: referencing-players.md
href: core-configuration.md
10 changes: 8 additions & 2 deletions managed/CounterStrikeSharp.API/Core/Model/CBaseEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,14 @@ public void Teleport(Vector? position = null, QAngle? angles = null, Vector? vel
nint _position = position?.Handle ?? 0;
nint _angles = angles?.Handle ?? 0;
nint _velocity = velocity?.Handle ?? 0;

VirtualFunction.CreateVoid<IntPtr, IntPtr, IntPtr, IntPtr>(Handle, GameData.GetOffset("CBaseEntity_Teleport"))(Handle, _position, _angles, _velocity);
nint _handle = Handle;

if (this is CCSPlayerController player && player.PlayerPawn.Value is CCSPlayerPawn playerPawn)
{
_handle = playerPawn.Handle;
}

VirtualFunction.CreateVoid<IntPtr, IntPtr, IntPtr, IntPtr>(_handle, GameData.GetOffset("CBaseEntity_Teleport"))(_handle, _position, _angles, _velocity);
}

/// <exception cref="InvalidOperationException">Entity is not valid</exception>
Expand Down
32 changes: 32 additions & 0 deletions managed/CounterStrikeSharp.API/Core/Model/CTakeDamageInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System.Runtime.InteropServices;

namespace CounterStrikeSharp.API.Core;

public partial class CTakeDamageInfo
{
/// <summary>
/// Retrieves the hitgroup
/// </summary>
/// <returns>
/// Returns a <see cref="HitGroup_t"/> enumeration representing the player's current hit group,
/// or <see cref="HitGroup_t.HITGROUP_INVALID"/> if the hit group cannot be determined.
/// </returns>
public HitGroup_t GetHitGroup()
{
IntPtr v4 = Marshal.ReadIntPtr(Handle, 0x78);

if (v4 == nint.Zero)
{
return HitGroup_t.HITGROUP_INVALID;
}

IntPtr v1 = Marshal.ReadIntPtr(v4, 16);

if (v1 == nint.Zero)
{
return HitGroup_t.HITGROUP_GENERIC;
}

return (HitGroup_t)Marshal.ReadInt32(v1, 56);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Text.Json;
using System.Reflection;

namespace CounterStrikeSharp.API.Modules.Extensions;

public static class PluginConfigExtensions
{
private static readonly JsonSerializerOptions _jsonSerializerOptions = new()
{
WriteIndented = true
};

public static JsonSerializerOptions JsonSerializerOptions => _jsonSerializerOptions;

/// <summary>
/// Gets the configuration file path
/// </summary>
/// <typeparam name="T">Type of the plugin configuration.</typeparam>
/// <param name="_">Current configuration instance</param>
public static string GetConfigPath<T>(this T _) where T : BasePluginConfig, new()
{
string assemblyName = typeof(T).Assembly.GetName().Name ?? string.Empty;
return Path.Combine(Server.GameDirectory, "csgo", "addons", "counterstrikesharp", "configs", "plugins", assemblyName, $"{assemblyName}.json");
}

/// <summary>
/// Updates the configuration file
/// </summary>
/// <typeparam name="T">Type of the plugin configuration.</typeparam>
/// <param name="config">Current configuration instance</param>
public static void Update<T>(this T config) where T : BasePluginConfig, new()
{
var configPath = config.GetConfigPath();

try
{
using var stream = new FileStream(configPath, FileMode.Create, FileAccess.Write, FileShare.None);
using var writer = new StreamWriter(stream);
writer.Write(JsonSerializer.Serialize(config, JsonSerializerOptions));
}
catch (Exception ex)
{
throw new Exception($"Failed to update configuration file at '{configPath}'.", ex);
}
}

/// <summary>
/// Reloads the configuration file and updates current configuration instance.
/// </summary>
/// <typeparam name="T">Type of the plugin configuration.</typeparam>
/// <param name="config">Current configuration instance</param>
public static void Reload<T>(this T config) where T : BasePluginConfig, new()
{
var configPath = config.GetConfigPath();

try
{
if (!File.Exists(configPath))
{
throw new FileNotFoundException($"Configuration file '{configPath} not found.");
}

var configContent = File.ReadAllText(configPath);

var newConfig = JsonSerializer.Deserialize<T>(configContent)
?? throw new JsonException($"Deserialization failed for configuration file '{configPath}'.");

foreach (var property in typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
if (property.CanWrite)
{
property.SetValue(config, property.GetValue(newConfig));
}
}
}
catch (Exception ex)
{
throw new Exception($"Failed to reload configuration file at '{configPath}'.", ex);
}
}
}

0 comments on commit e56eb54

Please sign in to comment.