mirror of
https://github.com/roflmuffin/CounterStrikeSharp.git
synced 2025-12-06 08:03:12 -08:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32c99b2e49 | ||
|
|
5c9d38b2b0 | ||
|
|
b54f5c3dee | ||
|
|
761380dff6 | ||
|
|
71ae253e5e |
@@ -84,22 +84,22 @@
|
||||
"CCSPlayer_WeaponServices_CanUse": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 56 48 83 EC 30 48 8B 01",
|
||||
"windows": "48 89 5C 24 ? 48 89 6C 24 ? 56 57 41 56 48 83 EC ? 48 8B 01 48 8B FA",
|
||||
"linux": "55 48 8D 15 ? ? ? ? 48 89 E5 41 55 49 89 FD 41 54 49 89 F4"
|
||||
}
|
||||
},
|
||||
"CCSPlayer_ItemServices_CanAcquire": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 8B C4 44 89 40 18 48 89 48 08 55 56",
|
||||
"linux": " 55 48 89 E5 41 57 41 56 48 8D 45 CC"
|
||||
"windows": "48 8B C4 44 89 40 ? 48 89 50 ? 48 89 48",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 55 49 89 CD 41 54 53 48 83 EC"
|
||||
}
|
||||
},
|
||||
"GetCSWeaponDataFromKey": {
|
||||
"signatures": {
|
||||
"library": "server",
|
||||
"windows": "48 89 5C 24 CC 48 89 74 24 CC 57 48 83 EC 20 48 8B FA 8B",
|
||||
"linux": " 55 48 89 E5 41 57 41 56 41 89 FE 41 55 41 54 45"
|
||||
"windows": "48 89 5C 24 ? 48 89 74 24 ? 57 48 83 EC ? 48 8B FA 8B F1 48 85 D2 0F 84",
|
||||
"linux": "55 48 89 E5 41 57 41 56 41 89 FE 41 55 41 54 45"
|
||||
}
|
||||
},
|
||||
"CCSPlayer_ItemServices_GiveNamedItem": {
|
||||
@@ -170,8 +170,8 @@
|
||||
},
|
||||
"CBasePlayerPawn_CommitSuicide": {
|
||||
"offsets": {
|
||||
"windows": 377,
|
||||
"linux": 377
|
||||
"windows": 380,
|
||||
"linux": 380
|
||||
}
|
||||
},
|
||||
"CBasePlayerPawn_RemovePlayerItem": {
|
||||
@@ -253,5 +253,11 @@
|
||||
"windows": 2,
|
||||
"linux": 0
|
||||
}
|
||||
},
|
||||
"CheckTransmitPlayerSlot": {
|
||||
"offsets": {
|
||||
"windows": 584,
|
||||
"linux": 584
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
2
examples/WithCheckTransmit/README.md
Normal file
2
examples/WithCheckTransmit/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# With CheckTransmit
|
||||
This example shows how to work with the `CheckTransmit` listener.
|
||||
13
examples/WithCheckTransmit/WithCheckTransmit.csproj
Normal file
13
examples/WithCheckTransmit/WithCheckTransmit.csproj
Normal file
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\managed\CounterStrikeSharp.API\CounterStrikeSharp.API.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
115
examples/WithCheckTransmit/WithCheckTransmitPlugin.cs
Normal file
115
examples/WithCheckTransmit/WithCheckTransmitPlugin.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using CounterStrikeSharp.API;
|
||||
using CounterStrikeSharp.API.Core;
|
||||
using CounterStrikeSharp.API.Core.Attributes;
|
||||
|
||||
namespace WithCheckTransmit;
|
||||
|
||||
[MinimumApiVersion(276)]
|
||||
public class WithCheckTransmitPlugin : BasePlugin
|
||||
{
|
||||
public override string ModuleName => "Example: With CheckTransmit";
|
||||
public override string ModuleVersion => "1.0.0";
|
||||
public override string ModuleAuthor => "CounterStrikeSharp & Contributors";
|
||||
public override string ModuleDescription => "A simple plugin that uses the CheckTransmit listener!";
|
||||
|
||||
private Dictionary<int, bool> ShouldSeeDoors = new Dictionary<int, bool>();
|
||||
|
||||
public override void Load(bool hotReload)
|
||||
{
|
||||
// This command is related to the following example.
|
||||
AddCommand("nodoors", "Toggle door transmit", (player, info) =>
|
||||
{
|
||||
if (player == null)
|
||||
return;
|
||||
|
||||
if (ShouldSeeDoors.ContainsKey(player.Slot))
|
||||
{
|
||||
ShouldSeeDoors[player.Slot] = !ShouldSeeDoors[player.Slot];
|
||||
} else
|
||||
{
|
||||
ShouldSeeDoors.Add(player.Slot, false);
|
||||
}
|
||||
|
||||
info.ReplyToCommand($"You should {(ShouldSeeDoors[player.Slot] ? "see" : "not see")} doors");
|
||||
});
|
||||
|
||||
// In this example, we will hide every door for players that have enabled the option with the command 'nodoors'
|
||||
RegisterListener<Listeners.CheckTransmit>((CCheckTransmitInfoList infoList) =>
|
||||
{
|
||||
// Get the list of the currently available doors (prop_door_rotating)
|
||||
IEnumerable<CPropDoorRotating> doors = Utilities.FindAllEntitiesByDesignerName<CPropDoorRotating>("prop_door_rotating");
|
||||
|
||||
// Do nothing if there is none.
|
||||
if (!doors.Any())
|
||||
return;
|
||||
|
||||
// Go through every received info
|
||||
foreach ((CCheckTransmitInfo info, CCSPlayerController? player) in infoList)
|
||||
{
|
||||
// If no player is found, we can continue
|
||||
if (player == null)
|
||||
continue;
|
||||
|
||||
// Otherwise, lets do the work:
|
||||
|
||||
// Check if we should clear or not:
|
||||
|
||||
// If we have no data saved for this player, then we should not continue
|
||||
if (!ShouldSeeDoors.ContainsKey(player.Slot))
|
||||
continue;
|
||||
|
||||
// If this value is true, then this player should see doors
|
||||
if (ShouldSeeDoors[player.Slot])
|
||||
continue;
|
||||
|
||||
// Otherwise, lets remove the door entity indexes from the info list so they won't be transmitted
|
||||
foreach (CPropDoorRotating door in doors)
|
||||
{
|
||||
info.TransmitEntities.Remove(door);
|
||||
}
|
||||
|
||||
// NOTE: this is a barebone example, saving data and doing sanity checks is up to you.
|
||||
}
|
||||
});
|
||||
|
||||
// In this example, we will hide other players in the same team as the player.
|
||||
// NOTE: 'Hiding' players requires extra work to do, killing non-transmitted players results in crash.
|
||||
RegisterListener<Listeners.CheckTransmit>((CCheckTransmitInfoList infoList) =>
|
||||
{
|
||||
// Get the list of the current players, we only work with this value later on
|
||||
List<CCSPlayerController> players = Utilities.GetPlayers();
|
||||
|
||||
// Go through every received info
|
||||
foreach ((CCheckTransmitInfo info, CCSPlayerController? player) in infoList)
|
||||
{
|
||||
// If no player is found, we can continue
|
||||
if (player == null)
|
||||
continue;
|
||||
|
||||
// Otherwise, lets do the work:
|
||||
|
||||
// as an example, lets hide everyone for this player who is in the same team.
|
||||
IEnumerable<CCSPlayerController> targetPlayers = players.Where(p =>
|
||||
// is the player and its pawn valid
|
||||
p.IsValid && p.Pawn.IsValid &&
|
||||
|
||||
// we shouldn't hide ourselves
|
||||
p.Slot != player.Slot &&
|
||||
|
||||
// is the player is in the same team
|
||||
p.Team == player.Team &&
|
||||
|
||||
// is alive
|
||||
p.PlayerPawn.Value?.LifeState == (byte)LifeState_t.LIFE_ALIVE
|
||||
);
|
||||
|
||||
foreach (CCSPlayerController targetPlayer in targetPlayers)
|
||||
{
|
||||
// Calling 'Remove' will clear the entity index of the target player pawn from the transmission list
|
||||
// so it won't be transmitted for the 'player'.
|
||||
info.TransmitEntities.Remove(targetPlayer.Pawn);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -337,6 +337,16 @@ namespace CounterStrikeSharp.API.Core
|
||||
}
|
||||
}
|
||||
|
||||
public static float GetGameFrameTime(){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
ScriptContext.GlobalScriptContext.SetIdentifier(0x97E331CA);
|
||||
ScriptContext.GlobalScriptContext.Invoke();
|
||||
ScriptContext.GlobalScriptContext.CheckErrors();
|
||||
return (float)ScriptContext.GlobalScriptContext.GetResult(typeof(float));
|
||||
}
|
||||
}
|
||||
|
||||
public static void IssueServerCommand(string command){
|
||||
lock (ScriptContext.GlobalScriptContext.Lock) {
|
||||
ScriptContext.GlobalScriptContext.Reset();
|
||||
|
||||
@@ -163,5 +163,12 @@ namespace CounterStrikeSharp.API.Core
|
||||
/// <param name="manifest">Resource Manifest</param>
|
||||
[ListenerName("OnServerPrecacheResources")]
|
||||
public delegate void OnServerPrecacheResources(ResourceManifest manifest);
|
||||
|
||||
/// <summary>
|
||||
/// Called when checking transmit on entities.
|
||||
/// </summary>
|
||||
/// <param name="infoList">Transmit info list</param>
|
||||
[ListenerName("CheckTransmit")]
|
||||
public delegate void CheckTransmit([CastFrom(typeof(nint))]CCheckTransmitInfoList infoList);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
106
managed/CounterStrikeSharp.API/Core/Model/CCheckTransmitInfo.cs
Normal file
106
managed/CounterStrikeSharp.API/Core/Model/CCheckTransmitInfo.cs
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* This file is part of CounterStrikeSharp.
|
||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
using System.Collections;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public struct CCheckTransmitInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Entity n is already marked for transmission
|
||||
/// </summary>
|
||||
[FieldOffset(0x0)]
|
||||
public CFixedBitVecBase TransmitEntities;
|
||||
|
||||
/// <summary>
|
||||
/// Entity n is always send even if not in PVS (HLTV and Replay only)
|
||||
/// </summary>
|
||||
[FieldOffset(0x8)]
|
||||
public CFixedBitVecBase TransmitAlways;
|
||||
};
|
||||
|
||||
public sealed class CCheckTransmitInfoList : NativeObject, IReadOnlyList<(CCheckTransmitInfo info, CCSPlayerController? player)>
|
||||
{
|
||||
private int CheckTransmitPlayerSlotOffset = GameData.GetOffset("CheckTransmitPlayerSlot");
|
||||
|
||||
private unsafe nint* Inner => (nint*)base.Handle;
|
||||
|
||||
public unsafe int Count { get => (int)(*(this.Inner + 1)); }
|
||||
|
||||
public unsafe CCheckTransmitInfoList(IntPtr pointer) : base(pointer)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Get transmit info for the given index.
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the info you want to retrieve from the list, should be between 0 and '<see cref="Count"/>' - 1</param>
|
||||
/// <returns></returns>
|
||||
public (CCheckTransmitInfo info, CCSPlayerController? player) this[int index]
|
||||
{
|
||||
get
|
||||
{
|
||||
var (transmit, slot) = this.Get(index);
|
||||
CCSPlayerController? player = Utilities.GetPlayerFromSlot(slot);
|
||||
return (transmit, player);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get transmit info for the given index.
|
||||
/// </summary>
|
||||
/// <param name="index">Index of the info you want to retrieve from the list, should be between 0 and '<see cref="Count"/>' - 1</param>
|
||||
/// <returns></returns>
|
||||
private unsafe (CCheckTransmitInfo, int) Get(int index)
|
||||
{
|
||||
if (index < 0 || index >= this.Count)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
}
|
||||
|
||||
// 'base.Handle' holds the pointer for our 'CCheckTransmitInfoList' wrapper class
|
||||
|
||||
// Get the pointer to the array of 'CCheckTransmitInfo'
|
||||
nint* infoListPtr = *(nint**)this.Inner; // Dereference 'Inner' to get the pointer to the array
|
||||
|
||||
// Access the specific 'CCheckTransmitInfo*'
|
||||
nint infoPtr = *(infoListPtr + index);
|
||||
|
||||
// Retrieve the 'CCheckTransmitInfo' from the pointer
|
||||
CCheckTransmitInfo info = Marshal.PtrToStructure<CCheckTransmitInfo>(infoPtr);
|
||||
|
||||
// Get player slot from the 'infoPtr' using the 'CheckTransmitPlayerSlotOffset' offset
|
||||
int playerSlot = *(int*)((byte*)infoPtr + CheckTransmitPlayerSlotOffset);
|
||||
|
||||
return (info, playerSlot);
|
||||
}
|
||||
|
||||
public IEnumerator<(CCheckTransmitInfo, CCSPlayerController?)> GetEnumerator()
|
||||
{
|
||||
for (int i = 0; i < this.Count; i++)
|
||||
{
|
||||
yield return this[i];
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return this.GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* This file is part of CounterStrikeSharp.
|
||||
* CounterStrikeSharp is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* CounterStrikeSharp is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with CounterStrikeSharp. If not, see <https://www.gnu.org/licenses/>. *
|
||||
*/
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace CounterStrikeSharp.API.Core
|
||||
{
|
||||
// credits: qstage
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
public unsafe struct CFixedBitVecBase
|
||||
{
|
||||
private const int LOG2_BITS_PER_INT = 5;
|
||||
private const int BITS_PER_INT = 32;
|
||||
|
||||
private readonly uint* m_Ints;
|
||||
|
||||
public void Add(CEntityInstance entityInstance) => Write(entityInstance.Index);
|
||||
|
||||
public void Add(int bitNum) => Write(bitNum);
|
||||
|
||||
public void Add(uint bitNum) => Write(bitNum);
|
||||
|
||||
public void Remove(CEntityInstance entityInstance) => Clear(entityInstance.Index);
|
||||
|
||||
public void Remove(int bitNum) => Clear(bitNum);
|
||||
|
||||
public void Remove(uint bitNum) => Clear(bitNum);
|
||||
|
||||
public bool Contains(CEntityInstance entityInstance) => Contains(entityInstance.Index);
|
||||
|
||||
public bool Contains(uint bitNum) => Contains((int)bitNum);
|
||||
|
||||
private void Clear(uint bitNum) => Clear((int)bitNum);
|
||||
|
||||
private void Write(uint bitNum) => Write((int)bitNum);
|
||||
|
||||
private void Clear(int bitNum)
|
||||
{
|
||||
if (!(bitNum >= 0 && bitNum < Utilities.MaxEdicts))
|
||||
return;
|
||||
|
||||
uint* pInt = m_Ints + BitVec_Int(bitNum);
|
||||
*pInt &= ~(uint)BitVec_Bit(bitNum);
|
||||
}
|
||||
|
||||
private void Write(int bitNum)
|
||||
{
|
||||
if (!(bitNum >= 0 && bitNum < Utilities.MaxEdicts))
|
||||
return;
|
||||
|
||||
uint* pInt = m_Ints + BitVec_Int(bitNum);
|
||||
*pInt |= (uint)BitVec_Bit(bitNum);
|
||||
}
|
||||
|
||||
public bool Contains(int bitNum)
|
||||
{
|
||||
if (!(bitNum >= 0 && bitNum < Utilities.MaxEdicts))
|
||||
return false;
|
||||
|
||||
uint* pInt = m_Ints + BitVec_Int(bitNum);
|
||||
return (*pInt & (uint)BitVec_Bit(bitNum)) != 0;
|
||||
}
|
||||
|
||||
private int BitVec_Int(int bitNum) => bitNum >> LOG2_BITS_PER_INT;
|
||||
|
||||
private int BitVec_Bit(int bitNum) => 1 << (bitNum & (BITS_PER_INT - 1));
|
||||
}
|
||||
}
|
||||
@@ -90,6 +90,7 @@ public abstract class BaseMenuInstance : IMenuInstance
|
||||
|
||||
protected bool HasPrevButton => Page > 0;
|
||||
protected bool HasNextButton => Menu.MenuOptions.Count > NumPerPage && CurrentOffset + NumPerPage < Menu.MenuOptions.Count;
|
||||
protected bool HasExitButton => Menu.ExitButton;
|
||||
protected virtual int MenuItemsPerPage => NumPerPage;
|
||||
|
||||
public virtual void Display()
|
||||
@@ -113,7 +114,7 @@ public abstract class BaseMenuInstance : IMenuInstance
|
||||
return;
|
||||
}
|
||||
|
||||
if (key == 9)
|
||||
if (key == 9 && HasExitButton)
|
||||
{
|
||||
Close();
|
||||
return;
|
||||
@@ -174,4 +175,4 @@ public abstract class BaseMenuInstance : IMenuInstance
|
||||
CurrentOffset = PrevPageOffsets.Pop();
|
||||
Display();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,28 +46,33 @@ namespace CounterStrikeSharp.API
|
||||
/// </summary>
|
||||
/// <remarks>Does not increment when server is hibernating</remarks>
|
||||
public static double TickedTime => NativeAPI.GetTickedTime();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current map time in seconds, as an interval of the server's tick interval.
|
||||
/// e.g. 70.046875 would represent 70 seconds of map time and the 4483rd tick of the server (70.046875 / 0.015625).
|
||||
/// </summary>
|
||||
/// <remarks>Increments even when server is hibernating</remarks>
|
||||
public static float CurrentTime => NativeAPI.GetCurrentTime();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current map tick count.
|
||||
/// CS2 is a 64 tick server, so the value will increment by 64 every second.
|
||||
/// </summary>
|
||||
public static int TickCount => NativeAPI.GetTickCount();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the total time the server has been running in seconds.
|
||||
/// </summary>
|
||||
/// <remarks>Increments even when server is hibernating</remarks>
|
||||
public static double EngineTime => NativeAPI.GetEngineTime();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the time spent on last server or client frame
|
||||
/// </summary>
|
||||
public static float FrameTime => NativeAPI.GetGameFrameTime();
|
||||
|
||||
public static void PrecacheModel(string name) => NativeAPI.PrecacheModel(name);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="RunOnTick"/>
|
||||
/// Returns Task that completes once the synchronous task has been completed.
|
||||
@@ -78,7 +83,7 @@ namespace CounterStrikeSharp.API
|
||||
NativeAPI.QueueTaskForFrame(tick, functionReference);
|
||||
return functionReference.CompletionTask;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Queue a task to be executed on the specified tick.
|
||||
/// See <see cref="TickCount"/> to retrieve the current tick.
|
||||
@@ -108,7 +113,7 @@ namespace CounterStrikeSharp.API
|
||||
{
|
||||
NextFrameAsync(task);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="NextWorldUpdate"/>
|
||||
/// Returns Task that completes once the synchronous task has been completed.
|
||||
@@ -119,7 +124,7 @@ namespace CounterStrikeSharp.API
|
||||
NativeAPI.QueueTaskForNextWorldUpdate(functionReference);
|
||||
return functionReference.CompletionTask;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Queue a task to be executed on the next pre world update.
|
||||
/// <remarks>Executes if the server is hibernating.</remarks>
|
||||
@@ -157,4 +162,4 @@ namespace CounterStrikeSharp.API
|
||||
|
||||
public static void PrintToConsole(string s) => NativeAPI.PrintToServerConsole($"{s}\n\0");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.12.35309.182
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestPlugin", "TestPlugin\TestPlugin.csproj", "{57E64289-5D69-4AA1-BEF0-D0D96A55EE8F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CounterStrikeSharp.API", "CounterStrikeSharp.API\CounterStrikeSharp.API.csproj", "{55B47E41-61AA-4D75-9069-CB14328107B7}"
|
||||
@@ -42,6 +45,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WithSharedTypesConsumer", "
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WithUserMessages", "..\examples\WithUserMessages\WithUserMessages.csproj", "{A14029BA-CADE-4F25-ADC5-48CF14332F61}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WithCheckTransmit", "..\examples\WithCheckTransmit\WithCheckTransmit.csproj", "{854B06B5-0E7B-438A-BA51-3F299557F884}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -108,14 +113,14 @@ Global
|
||||
{6FA3107D-42AF-42A0-BF51-2230D13268B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6FA3107D-42AF-42A0-BF51-2230D13268B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6FA3107D-42AF-42A0-BF51-2230D13268B5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1309954E-FAF7-47A5-9FF9-C7263B33E4E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1309954E-FAF7-47A5-9FF9-C7263B33E4E3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1309954E-FAF7-47A5-9FF9-C7263B33E4E3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1309954E-FAF7-47A5-9FF9-C7263B33E4E3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A37676EA-CF2F-424D-85A1-C359D07A679D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A37676EA-CF2F-424D-85A1-C359D07A679D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A37676EA-CF2F-424D-85A1-C359D07A679D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -128,6 +133,13 @@ Global
|
||||
{A14029BA-CADE-4F25-ADC5-48CF14332F61}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A14029BA-CADE-4F25-ADC5-48CF14332F61}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A14029BA-CADE-4F25-ADC5-48CF14332F61}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{854B06B5-0E7B-438A-BA51-3F299557F884}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{854B06B5-0E7B-438A-BA51-3F299557F884}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{854B06B5-0E7B-438A-BA51-3F299557F884}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{854B06B5-0E7B-438A-BA51-3F299557F884}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{57E64289-5D69-4AA1-BEF0-D0D96A55EE8F} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
@@ -141,10 +153,14 @@ Global
|
||||
{31EABE0B-871F-497B-BF36-37FFC6FAD15F} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{BB44E08E-CCA8-4E22-A132-11B2F69D1890} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{6FA3107D-42AF-42A0-BF51-2230D13268B5} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{1309954E-FAF7-47A5-9FF9-C7263B33E4E3} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{4E5289B5-E81D-421C-B340-B98B6FFE09D1} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{A37676EA-CF2F-424D-85A1-C359D07A679D} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{76AD7BB0-A096-4336-83E2-B32CAE4E9933} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{A14029BA-CADE-4F25-ADC5-48CF14332F61} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
{854B06B5-0E7B-438A-BA51-3F299557F884} = {7DF99C35-881D-4FF2-B1C9-246BD3DECB9A}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {069C4CD4-BACA-446A-A6B8-0194E4F75355}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
@@ -301,6 +302,26 @@ namespace TestPlugin
|
||||
return;
|
||||
}
|
||||
});
|
||||
|
||||
// Hide every door (prop_door_rotating) for everyone as a test
|
||||
RegisterListener<Listeners.CheckTransmit>((CCheckTransmitInfoList infoList) =>
|
||||
{
|
||||
IEnumerable<CPropDoorRotating> doors = Utilities.FindAllEntitiesByDesignerName<CPropDoorRotating>("prop_door_rotating");
|
||||
|
||||
if (!doors.Any())
|
||||
return;
|
||||
|
||||
foreach ((CCheckTransmitInfo info, CCSPlayerController? player) in infoList)
|
||||
{
|
||||
if (player == null)
|
||||
continue;
|
||||
|
||||
foreach (CPropDoorRotating door in doors)
|
||||
{
|
||||
info.TransmitEntities.Remove(door);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void SetupCommands()
|
||||
|
||||
@@ -78,6 +78,7 @@ ISmmAPI* ismm = nullptr;
|
||||
CGameEntitySystem* entitySystem = nullptr;
|
||||
CCoreConfig* coreConfig = nullptr;
|
||||
CGameConfig* gameConfig = nullptr;
|
||||
ISource2GameEntities* gameEntities = nullptr;
|
||||
|
||||
// Custom Managers
|
||||
CallbackManager callbackManager;
|
||||
|
||||
@@ -94,6 +94,7 @@ extern ISource2Server* server;
|
||||
extern CGlobalEntityList* globalEntityList;
|
||||
extern EntityListener entityListener;
|
||||
extern CGameEntitySystem* entitySystem;
|
||||
extern ISource2GameEntities* gameEntities;
|
||||
|
||||
extern EventManager eventManager;
|
||||
extern UserMessageManager userMessageManager;
|
||||
|
||||
@@ -24,14 +24,24 @@
|
||||
#include <public/eiface.h>
|
||||
#include "scripting/callback_manager.h"
|
||||
|
||||
SH_DECL_HOOK7_void(ISource2GameEntities, CheckTransmit, SH_NOATTRIB, 0, CCheckTransmitInfo**, int, CBitVec<16384>&, const Entity2Networkable_t**, const uint16*, int, bool);
|
||||
|
||||
namespace counterstrikesharp {
|
||||
|
||||
EntityManager::EntityManager() {}
|
||||
EntityManager::EntityManager()
|
||||
{
|
||||
m_profile_name = "EntityManager";
|
||||
}
|
||||
|
||||
EntityManager::~EntityManager() {}
|
||||
|
||||
CCheckTransmitInfoList::CCheckTransmitInfoList(CCheckTransmitInfo** pInfoInfoList, int nInfoCount) : infoList(pInfoInfoList), infoCount(nInfoCount) {}
|
||||
|
||||
void EntityManager::OnAllInitialized()
|
||||
{
|
||||
SH_ADD_HOOK_MEMFUNC(ISource2GameEntities, CheckTransmit, globals::gameEntities, this, &EntityManager::CheckTransmit, true);
|
||||
|
||||
check_transmit = globals::callbackManager.CreateCallback("CheckTransmit");
|
||||
on_entity_spawned_callback = globals::callbackManager.CreateCallback("OnEntitySpawned");
|
||||
on_entity_created_callback = globals::callbackManager.CreateCallback("OnEntityCreated");
|
||||
on_entity_deleted_callback = globals::callbackManager.CreateCallback("OnEntityDeleted");
|
||||
@@ -75,7 +85,10 @@ void EntityManager::OnShutdown()
|
||||
globals::callbackManager.ReleaseCallback(on_entity_created_callback);
|
||||
globals::callbackManager.ReleaseCallback(on_entity_deleted_callback);
|
||||
globals::callbackManager.ReleaseCallback(on_entity_parent_changed_callback);
|
||||
globals::callbackManager.ReleaseCallback(check_transmit);
|
||||
globals::entitySystem->RemoveListenerEntity(&entityListener);
|
||||
|
||||
SH_REMOVE_HOOK_MEMFUNC(ISource2GameEntities, CheckTransmit, globals::gameEntities, this, &EntityManager::CheckTransmit, true);
|
||||
}
|
||||
|
||||
void CEntityListener::OnEntitySpawned(CEntityInstance* pEntity)
|
||||
@@ -156,6 +169,23 @@ void EntityManager::UnhookEntityOutput(const char* szClassname, const char* szOu
|
||||
}
|
||||
}
|
||||
|
||||
void EntityManager::CheckTransmit(CCheckTransmitInfo** pInfoInfoList, int nInfoCount, CBitVec<16384>& unionTransmitEdicts, const Entity2Networkable_t** pNetworkables, const uint16* pEntityIndicies, int nEntityIndices, bool bEnablePVSBits)
|
||||
{
|
||||
VPROF_BUDGET(m_profile_name.c_str(), "CS# CheckTransmit");
|
||||
|
||||
auto callback = globals::entityManager.check_transmit;
|
||||
|
||||
if (callback && callback->GetFunctionCount()) {
|
||||
CCheckTransmitInfoList* infoList = new CCheckTransmitInfoList(pInfoInfoList, nInfoCount);
|
||||
|
||||
callback->ScriptContext().Reset();
|
||||
callback->ScriptContext().Push(infoList);
|
||||
callback->Execute();
|
||||
|
||||
delete infoList;
|
||||
}
|
||||
}
|
||||
|
||||
void DetourFireOutputInternal(CEntityIOOutput* const pThis, CEntityInstance* pActivator,
|
||||
CEntityInstance* pCaller, const CVariant* const value, float flDelay)
|
||||
{
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
|
||||
#include <variant.h>
|
||||
|
||||
#include "vprof.h"
|
||||
|
||||
namespace counterstrikesharp {
|
||||
class ScriptCallback;
|
||||
|
||||
@@ -39,6 +41,14 @@ class CEntityListener : public IEntityListener {
|
||||
void OnEntityParentChanged(CEntityInstance *pEntity, CEntityInstance *pNewParent) override;
|
||||
};
|
||||
|
||||
class CCheckTransmitInfoList {
|
||||
public:
|
||||
CCheckTransmitInfoList(CCheckTransmitInfo** pInfoInfoList, int nInfoCount);
|
||||
private:
|
||||
CCheckTransmitInfo** infoList;
|
||||
int infoCount;
|
||||
};
|
||||
|
||||
class EntityManager : public GlobalClass {
|
||||
friend CEntityListener;
|
||||
public:
|
||||
@@ -51,10 +61,15 @@ public:
|
||||
CEntityListener entityListener;
|
||||
std::map<OutputKey_t, CallbackPair*> m_pHookMap;
|
||||
private:
|
||||
void CheckTransmit(CCheckTransmitInfo** pInfoInfoList, int nInfoCount, CBitVec<16384>& unionTransmitEdicts, const Entity2Networkable_t** pNetworkables, const uint16* pEntityIndicies, int nEntityIndices, bool bEnablePVSBits);
|
||||
|
||||
ScriptCallback *on_entity_spawned_callback;
|
||||
ScriptCallback *on_entity_created_callback;
|
||||
ScriptCallback *on_entity_deleted_callback;
|
||||
ScriptCallback *on_entity_parent_changed_callback;
|
||||
ScriptCallback *check_transmit;
|
||||
|
||||
std::string m_profile_name;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -102,6 +102,7 @@ bool CounterStrikeSharpMMPlugin::Load(PluginId id, ISmmAPI* ismm, char* error, s
|
||||
GET_V_IFACE_ANY(GetEngineFactory, globals::gameEventSystem, IGameEventSystem, GAMEEVENTSYSTEM_INTERFACE_VERSION);
|
||||
GET_V_IFACE_ANY(GetEngineFactory, globals::engineServiceManager, IEngineServiceMgr, ENGINESERVICEMGR_INTERFACE_VERSION);
|
||||
GET_V_IFACE_ANY(GetEngineFactory, globals::networkMessages, INetworkMessages, NETWORKMESSAGES_INTERFACE_VERSION);
|
||||
GET_V_IFACE_ANY(GetServerFactory, globals::gameEntities, ISource2GameEntities, SOURCE2GAMEENTITIES_INTERFACE_VERSION);
|
||||
|
||||
auto coreconfig_path = std::string(utils::ConfigsDirectory() + "/core");
|
||||
globals::coreConfig = new CCoreConfig(coreconfig_path);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
OnEntitySpawned: entity:pointer
|
||||
OnEntityCreated: entity:pointer
|
||||
OnEntityDeleted: entity:pointer
|
||||
OnEntityParentChanged: entity:pointer, newParent:pointer
|
||||
OnEntityParentChanged: entity:pointer, newParent:pointer
|
||||
CheckTransmit: infoList:pointer
|
||||
|
||||
@@ -245,7 +245,7 @@ REGISTER_NATIVES(engine, {
|
||||
ScriptEngine::RegisterNativeHandler("GET_TICK_INTERVAL", GetTickInterval);
|
||||
ScriptEngine::RegisterNativeHandler("GET_TICK_COUNT", GetTickCount);
|
||||
ScriptEngine::RegisterNativeHandler("GET_CURRENT_TIME", GetCurrentTime);
|
||||
ScriptEngine::RegisterNativeHandler("GET_GAMEFRAME_TIME", GetGameFrameTime);
|
||||
ScriptEngine::RegisterNativeHandler("GET_GAME_FRAME_TIME", GetGameFrameTime);
|
||||
ScriptEngine::RegisterNativeHandler("GET_ENGINE_TIME", GetEngineTime);
|
||||
ScriptEngine::RegisterNativeHandler("GET_MAX_CLIENTS", GetMaxClients);
|
||||
ScriptEngine::RegisterNativeHandler("ISSUE_SERVER_COMMAND", ServerCommand);
|
||||
|
||||
@@ -6,6 +6,7 @@ GET_CURRENT_TIME: -> float
|
||||
GET_TICK_COUNT: -> int
|
||||
GET_ENGINE_TIME: -> double
|
||||
GET_MAX_CLIENTS: -> int
|
||||
GET_GAME_FRAME_TIME: -> float
|
||||
ISSUE_SERVER_COMMAND: command:string -> void
|
||||
PRECACHE_MODEL: name:string -> void
|
||||
PRECACHE_SOUND: name:string, preload:bool -> bool
|
||||
|
||||
Reference in New Issue
Block a user