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
Original file line number Diff line number Diff line change
@@ -1,100 +1,102 @@
using SwiftlyS2.Core.Natives;
using SwiftlyS2.Core.Schemas;
using SwiftlyS2.Shared.EntitySystem;
using SwiftlyS2.Shared.Natives;
using SwiftlyS2.Shared.SchemaDefinitions;
using SwiftlyS2.Shared.Schemas;

namespace SwiftlyS2.Core.SchemaDefinitions;

internal partial class CEntityInstanceImpl : CEntityInstance {
internal partial class CEntityInstanceImpl : CEntityInstance
{
public uint Index => Entity?.EntityHandle.EntityIndex ?? uint.MaxValue;
public string DesignerName => Entity?.DesignerName ?? string.Empty;

public uint Index => Entity?.EntityHandle.EntityIndex ?? uint.MaxValue;

public string DesignerName => Entity?.DesignerName ?? string.Empty;

public void AcceptInput<T>(string input, T value, CEntityInstance? activator = null, CEntityInstance? caller = null, int outputID = 0) {
switch (value) {
case bool boolValue:
NativeEntitySystem.AcceptInputBool(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, boolValue, outputID);
break;
case int intValue:
NativeEntitySystem.AcceptInputInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, intValue, outputID);
break;
case uint uintValue:
NativeEntitySystem.AcceptInputUInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, uintValue, outputID);
break;
case long longValue:
NativeEntitySystem.AcceptInputInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, longValue, outputID);
break;
case ulong ulongValue:
NativeEntitySystem.AcceptInputUInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, ulongValue, outputID);
break;
case float floatValue:
NativeEntitySystem.AcceptInputFloat(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, floatValue, outputID);
break;
case double doubleValue:
NativeEntitySystem.AcceptInputDouble(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, doubleValue, outputID);
break;
case string stringValue:
NativeEntitySystem.AcceptInputString(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, stringValue, outputID);
break;
default:
throw new InvalidOperationException($"Unsupported type: {typeof(T).Name}");
public void AcceptInput<T>( string input, T value, CEntityInstance? activator = null, CEntityInstance? caller = null, int outputID = 0 )
{
switch (value)
{
case bool boolValue:
NativeEntitySystem.AcceptInputBool(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, boolValue, outputID);
break;
case int intValue:
NativeEntitySystem.AcceptInputInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, intValue, outputID);
break;
case uint uintValue:
NativeEntitySystem.AcceptInputUInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, uintValue, outputID);
break;
case long longValue:
NativeEntitySystem.AcceptInputInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, longValue, outputID);
break;
case ulong ulongValue:
NativeEntitySystem.AcceptInputUInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, ulongValue, outputID);
break;
case float floatValue:
NativeEntitySystem.AcceptInputFloat(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, floatValue, outputID);
break;
case double doubleValue:
NativeEntitySystem.AcceptInputDouble(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, doubleValue, outputID);
break;
case string stringValue:
NativeEntitySystem.AcceptInputString(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, stringValue, outputID);
break;
default:
throw new InvalidOperationException($"Unsupported type: {typeof(T).Name}");
}
}
}

public void AddEntityIOEvent<T>(string input, T value, CEntityInstance? activator = null, CEntityInstance? caller = null, float delay = 0f) {
switch (value) {
case bool boolValue:
NativeEntitySystem.AddEntityIOEventBool(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, boolValue, delay);
break;
case int intValue:
NativeEntitySystem.AddEntityIOEventInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, intValue, delay);
break;
case uint uintValue:
NativeEntitySystem.AddEntityIOEventUInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, uintValue, delay);
break;
case long longValue:
NativeEntitySystem.AddEntityIOEventInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, longValue, delay);
break;
case ulong ulongValue:
NativeEntitySystem.AddEntityIOEventUInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, ulongValue, delay);
break;
case float floatValue:
NativeEntitySystem.AddEntityIOEventFloat(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, floatValue, delay);
break;
case double doubleValue:
NativeEntitySystem.AddEntityIOEventDouble(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, doubleValue, delay);
break;
case string stringValue:
NativeEntitySystem.AddEntityIOEventString(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, stringValue, delay);
break;
default:
throw new InvalidOperationException($"Unsupported type: {typeof(T).Name}");
public void AddEntityIOEvent<T>( string input, T value, CEntityInstance? activator = null, CEntityInstance? caller = null, float delay = 0f )
{
switch (value)
{
case bool boolValue:
NativeEntitySystem.AddEntityIOEventBool(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, boolValue, delay);
break;
case int intValue:
NativeEntitySystem.AddEntityIOEventInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, intValue, delay);
break;
case uint uintValue:
NativeEntitySystem.AddEntityIOEventUInt32(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, uintValue, delay);
break;
case long longValue:
NativeEntitySystem.AddEntityIOEventInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, longValue, delay);
break;
case ulong ulongValue:
NativeEntitySystem.AddEntityIOEventUInt64(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, ulongValue, delay);
break;
case float floatValue:
NativeEntitySystem.AddEntityIOEventFloat(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, floatValue, delay);
break;
case double doubleValue:
NativeEntitySystem.AddEntityIOEventDouble(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, doubleValue, delay);
break;
case string stringValue:
NativeEntitySystem.AddEntityIOEventString(Address, input, activator?.Address ?? nint.Zero, caller?.Address ?? nint.Zero, stringValue, delay);
break;
default:
throw new InvalidOperationException($"Unsupported type: {typeof(T).Name}");
}
}
}

public void SetTransmitState( bool transmitting , int playerId ) {
NativePlayer.ShouldBlockTransmitEntity(playerId, (int)Index, transmitting);
public void SetTransmitState( bool transmitting, int playerId )
{
NativePlayer.ShouldBlockTransmitEntity(playerId, (int)Index, !transmitting);
}

}
public void SetTransmitState( bool transmitting )
{
NativePlayerManager.ShouldBlockTransmitEntity((int)Index, !transmitting);
}

public void SetTransmitState( bool transmitting )
{
NativePlayerManager.ShouldBlockTransmitEntity((int)Index, transmitting);
}

public bool IsTransmitting( int playerId )
{
return NativePlayer.IsTransmitEntityBlocked(playerId, (int)Index);
}
public bool IsTransmitting( int playerId )
{
return !NativePlayer.IsTransmitEntityBlocked(playerId, (int)Index);
}

public void DispatchSpawn(CEntityKeyValues? entityKV = null) {
NativeEntitySystem.Spawn(Address, entityKV?.Address ?? nint.Zero);
}
public void DispatchSpawn( CEntityKeyValues? entityKV = null )
{
NativeEntitySystem.Spawn(Address, entityKV?.Address ?? nint.Zero);
}

public void Despawn() {
NativeEntitySystem.Despawn(Address);
}
public void Despawn()
{
NativeEntitySystem.Despawn(Address);
}
}
35 changes: 34 additions & 1 deletion managed/src/TestPlugin/TestPlugin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -639,10 +639,43 @@ public void GetIpCommand( ICommandContext context )
// }

[Command("ed")]
public void EmitGrenadeCommand( ICommandContext _ )
public void EmitGrenadeCommand( ICommandContext context )
{
var smoke = CSmokeGrenadeProjectile.EmitGrenade(new(0, 0, 0), new(0, 0, 0), new(0, 0, 0), Team.CT, null);
smoke.Despawn();
smoke.SetTransmitState(true, context.Sender!.PlayerID);
}

[Command("hbw")]
public void HideBotWeapon( ICommandContext context )
{
Core.PlayerManager.GetAlive()
.Where(player => player.PlayerID != context.Sender!.PlayerID && player.IsValid && player.IsFakeClient)
.ToList()
.ForEach(player => player.PlayerPawn!.WeaponServices!.ActiveWeapon.Value!.SetTransmitState(false, context.Sender!.PlayerID));
}

[Command("sihb")]
public void ShowIfHideBot( ICommandContext context )
{
Core.PlayerManager.GetAlive()
.Where(player => player.PlayerID != context.Sender!.PlayerID && player.IsValid && player.IsFakeClient)
.ToList()
.ForEach(player => Console.WriteLine($"{player.Controller!.PlayerName} -> {(!player.PlayerPawn!.IsTransmitting(context.Sender!.PlayerID) ? "Hide" : "V")}"));
}

[Command("hb")]
public void HideBot( ICommandContext context )
{
Core.PlayerManager.GetAlive()
.Where(player => player.PlayerID != context.Sender!.PlayerID && player.IsValid && player.IsFakeClient)
.ToList()
.ForEach(player =>
{
// Console.WriteLine($"{player.Controller!.PlayerName}(B) -> {player.PlayerPawn!.IsTransmitting(context.Sender!.PlayerID)}({player.PlayerPawn!.IsTransmitting(player.PlayerID)})");
player.PlayerPawn!.SetTransmitState(!player.PlayerPawn!.IsTransmitting(context.Sender!.PlayerID), context.Sender!.PlayerID);
// Console.WriteLine($"{player.Controller!.PlayerName} -> {player.PlayerPawn!.IsTransmitting(context.Sender!.PlayerID)}({player.PlayerPawn!.IsTransmitting(player.PlayerID)})");
});
}

[Command("ss")]
Expand Down
24 changes: 20 additions & 4 deletions src/scripting/server/player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,43 +160,59 @@ void Bridge_Player_Kick(int playerid, const char* reason, int gamereason)
void Bridge_Player_ShouldBlockTransmitEntity(int playerid, int entityidx, bool shouldBlockTransmit)
{
if (playerid + 1 == entityidx)
{
return;
}

static auto playerManager = g_ifaceService.FetchInterface<IPlayerManager>(PLAYERMANAGER_INTERFACE_VERSION);
auto player = playerManager->GetPlayer(playerid);
if (!player)
{
return;
}

auto& bv = player->GetBlockedTransmittingBits();

auto dword = entityidx / 64;
if (shouldBlockTransmit)
{
bool wasEmpty = (bv.blockedMask[dword] == 0);
bv.blockedMask[dword] |= (1 << (entityidx % 64));
bv.blockedMask[dword] |= (1ULL << (entityidx % 64));
if (wasEmpty)
{
bv.activeMasks.push_back(dword);
}
}
else
{
bv.blockedMask[dword] &= ~(1 << (entityidx % 64));
bv.blockedMask[dword] &= ~(1ULL << (entityidx % 64));
if (bv.blockedMask[dword] == 0)
bv.activeMasks.erase(std::find(bv.activeMasks.begin(), bv.activeMasks.end(), dword));
{
auto it = std::find(bv.activeMasks.begin(), bv.activeMasks.end(), dword);
if (it != bv.activeMasks.end())
{
bv.activeMasks.erase(it);
}
}
}
}

bool Bridge_Player_IsTransmitEntityBlocked(int playerid, int entityidx)
{
if (playerid + 1 == entityidx)
{
return false;
}

static auto playerManager = g_ifaceService.FetchInterface<IPlayerManager>(PLAYERMANAGER_INTERFACE_VERSION);
auto player = playerManager->GetPlayer(playerid);
if (!player)
{
return false;
}

auto& bv = player->GetBlockedTransmittingBits();
return (bv.blockedMask[entityidx / 64] & (1 << (entityidx % 64))) != 0;
return (bv.blockedMask[entityidx / 64] & (1ULL << (entityidx % 64))) != 0;
}

void Bridge_Player_ClearTransmitEntityBlocked(int playerid)
Expand Down
4 changes: 1 addition & 3 deletions src/server/players/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,23 +213,21 @@ void CheckTransmitHook(void* _this, CCheckTransmitInfo** ppInfoList, int infoCou
{
continue;
}

auto player = playermanager->GetPlayer(playerid);
if (!player)
{
continue;
}

auto& blockedBits = player->GetBlockedTransmittingBits();

uint64_t* base = reinterpret_cast<uint64_t*>(pInfo->m_pTransmitEntity->Base());
uint64_t* baseAlways = reinterpret_cast<uint64_t*>(pInfo->m_pTransmitAlways->Base());
auto& activeMasks = blockedBits.activeMasks;

// NUM_MASKS_ACTIVE ops = NUM_MASKS_ACTIVE*64 bits -> 64 players -> NUM_MASKS_ACTIVE*64 ops
for (auto& dword : activeMasks)
{
base[dword] &= ~blockedBits.blockedMask[dword];
baseAlways[dword] &= ~blockedBits.blockedMask[dword];
}

// 512 ops = 16k bits -> 64 players -> 32k ops
Expand Down
Loading