mirror of
https://github.com/creazy231/cs2-css-flashlight.git
synced 2026-09-27 20:17:04 +02:00
🔦 Modernize flashlight for CSS/.NET 10
Bump to CounterStrikeSharp 1.0.371 and .NET 10, replace per-tick light spawns with a parented light_barn, add plugin config, real unit tests, and refresh CI plus docs. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
081278a8ae
commit
a0ef6311ee
13 changed files with 847 additions and 434 deletions
|
|
@ -1,7 +1,7 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
|
|
@ -9,21 +9,20 @@
|
|||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="xunit" Version="2.6.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.4">
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1" />
|
||||
<PackageReference Include="xunit" Version="2.9.3" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.1">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Moq" Version="4.20.69" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="../Flashlight/Flashlight.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
using System.Numerics;
|
||||
using Xunit;
|
||||
|
||||
namespace Flashlight.Tests;
|
||||
|
|
@ -5,137 +6,119 @@ namespace Flashlight.Tests;
|
|||
public class FlashlightLogicTests
|
||||
{
|
||||
[Fact]
|
||||
public void FlashlightState_TogglesCorrectly()
|
||||
public void TryToggle_TogglesWhenAllowed()
|
||||
{
|
||||
// Test the core logic of flashlight state toggling
|
||||
var playerKey = "test_player_1";
|
||||
var flashlightState = new Dictionary<string, bool>();
|
||||
|
||||
// Initial state should be off
|
||||
flashlightState[playerKey] = false;
|
||||
Assert.False(flashlightState[playerKey]);
|
||||
|
||||
// Toggle on
|
||||
flashlightState[playerKey] = !flashlightState[playerKey];
|
||||
Assert.True(flashlightState[playerKey]);
|
||||
|
||||
// Toggle off
|
||||
flashlightState[playerKey] = !flashlightState[playerKey];
|
||||
Assert.False(flashlightState[playerKey]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FlashlightState_TracksMultiplePlayers()
|
||||
{
|
||||
var playerStates = new Dictionary<string, bool>();
|
||||
var player1 = "player_1";
|
||||
var player2 = "player_2";
|
||||
var player3 = "player_3";
|
||||
|
||||
// Initialize all off
|
||||
playerStates[player1] = false;
|
||||
playerStates[player2] = false;
|
||||
playerStates[player3] = false;
|
||||
|
||||
// Toggle player 1 on
|
||||
playerStates[player1] = !playerStates[player1];
|
||||
Assert.True(playerStates[player1]);
|
||||
Assert.False(playerStates[player2]);
|
||||
Assert.False(playerStates[player3]);
|
||||
|
||||
// Toggle player 2 on
|
||||
playerStates[player2] = !playerStates[player2];
|
||||
Assert.True(playerStates[player1]);
|
||||
Assert.True(playerStates[player2]);
|
||||
Assert.False(playerStates[player3]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToggleCooldown_PreventsRapidToggling()
|
||||
{
|
||||
// Simulate the cooldown mechanism
|
||||
var isOn = false;
|
||||
var canToggle = true;
|
||||
|
||||
// First toggle - should work
|
||||
Assert.True(canToggle);
|
||||
canToggle = false; // Simulate setting cooldown
|
||||
|
||||
// Second toggle - should be blocked
|
||||
|
||||
Assert.True(FlashlightLogic.TryToggle(ref isOn, ref canToggle));
|
||||
Assert.True(isOn);
|
||||
Assert.False(canToggle);
|
||||
|
||||
// After cooldown expires
|
||||
canToggle = true;
|
||||
Assert.True(canToggle);
|
||||
}
|
||||
|
||||
|
||||
[Fact]
|
||||
public void CrouchState_UpdatesCorrectly()
|
||||
public void TryToggle_BlockedDuringCooldown()
|
||||
{
|
||||
var isCrouching = false;
|
||||
var buttons = 0;
|
||||
const int DuckButton = 1 << 2; // Typical duck button bit
|
||||
|
||||
// Not crouching initially
|
||||
Assert.False(isCrouching);
|
||||
|
||||
// Press duck button
|
||||
buttons |= DuckButton;
|
||||
if ((buttons & DuckButton) != 0)
|
||||
var isOn = true;
|
||||
var canToggle = false;
|
||||
|
||||
Assert.False(FlashlightLogic.TryToggle(ref isOn, ref canToggle));
|
||||
Assert.True(isOn);
|
||||
Assert.False(canToggle);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void IsUsePressedEdge_OnlyTrueOnRisingEdge()
|
||||
{
|
||||
Assert.True(FlashlightLogic.IsUsePressedEdge(true, false));
|
||||
Assert.False(FlashlightLogic.IsUsePressedEdge(true, true));
|
||||
Assert.False(FlashlightLogic.IsUsePressedEdge(false, true));
|
||||
Assert.False(FlashlightLogic.IsUsePressedEdge(false, false));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, 64f, 46f, 64f)]
|
||||
[InlineData(true, 64f, 46f, 46f)]
|
||||
public void GetEyeOffsetZ_UsesCrouchWhenDucking(
|
||||
bool crouching,
|
||||
float stand,
|
||||
float crouch,
|
||||
float expected)
|
||||
{
|
||||
Assert.Equal(expected, FlashlightLogic.GetEyeOffsetZ(crouching, stand, crouch));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void CalculateLightOrigin_AppliesEyeAndForwardOffsets()
|
||||
{
|
||||
var origin = FlashlightLogic.CalculateLightOrigin(
|
||||
new Vector3(10f, 20f, 30f),
|
||||
new Vector3(1f, 0f, 0f),
|
||||
eyeOffsetZ: 64f,
|
||||
forwardDistance: 54f);
|
||||
|
||||
Assert.Equal(new Vector3(64f, 20f, 94f), origin);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ForwardFromAnglesDegrees_YawZeroLooksAlongX()
|
||||
{
|
||||
var forward = FlashlightLogic.ForwardFromAnglesDegrees(0f, 0f);
|
||||
|
||||
Assert.Equal(1f, forward.X, 3);
|
||||
Assert.Equal(0f, forward.Y, 3);
|
||||
Assert.Equal(0f, forward.Z, 3);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ShouldCreateAndDestroyLight_Policies()
|
||||
{
|
||||
Assert.True(FlashlightLogic.ShouldCreateLight(isOn: true, hasValidLight: false));
|
||||
Assert.False(FlashlightLogic.ShouldCreateLight(isOn: true, hasValidLight: true));
|
||||
Assert.True(FlashlightLogic.ShouldDestroyLight(isOn: false, hasValidLight: true));
|
||||
Assert.False(FlashlightLogic.ShouldDestroyLight(isOn: false, hasValidLight: false));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ConfigClamp_FixesInvalidValues()
|
||||
{
|
||||
var config = new FlashlightConfig
|
||||
{
|
||||
isCrouching = true;
|
||||
}
|
||||
Assert.True(isCrouching);
|
||||
|
||||
// Release duck button
|
||||
buttons &= ~DuckButton;
|
||||
if ((buttons & DuckButton) == 0)
|
||||
{
|
||||
isCrouching = false;
|
||||
}
|
||||
Assert.False(isCrouching);
|
||||
ToggleCooldownSeconds = -1f,
|
||||
Brightness = -5f,
|
||||
Range = 0f,
|
||||
ColorTemperature = 50f,
|
||||
SoftX = -1f,
|
||||
SoftY = -1f,
|
||||
Skirt = -1f,
|
||||
SkirtNear = -1f,
|
||||
SizeX = -1f,
|
||||
SizeY = -1f,
|
||||
SizeZ = -1f,
|
||||
ForwardDistance = -10f,
|
||||
StandEyeOffsetZ = -1f,
|
||||
CrouchEyeOffsetZ = -1f,
|
||||
AttachmentName = " ",
|
||||
LightCookie = ""
|
||||
};
|
||||
|
||||
config.Clamp();
|
||||
|
||||
Assert.Equal(0f, config.ToggleCooldownSeconds);
|
||||
Assert.Equal(0f, config.Brightness);
|
||||
Assert.Equal(1f, config.Range);
|
||||
Assert.Equal(1000f, config.ColorTemperature);
|
||||
Assert.Equal(0f, config.SoftX);
|
||||
Assert.Equal(0f, config.SoftY);
|
||||
Assert.Equal(0f, config.Skirt);
|
||||
Assert.Equal(0f, config.SkirtNear);
|
||||
Assert.Equal(0f, config.SizeX);
|
||||
Assert.Equal(0f, config.SizeY);
|
||||
Assert.Equal(0f, config.SizeZ);
|
||||
Assert.Equal(0f, config.ForwardDistance);
|
||||
Assert.Equal(0f, config.StandEyeOffsetZ);
|
||||
Assert.Equal(0f, config.CrouchEyeOffsetZ);
|
||||
Assert.Equal("axis_of_intent", config.AttachmentName);
|
||||
Assert.Equal("materials/effects/lightcookies/flashlight.vtex", config.LightCookie);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void LightPosition_CalculatesCrouchOffsetCorrectly()
|
||||
{
|
||||
// Test the position calculation logic
|
||||
var baseZ = 100f;
|
||||
var standOffset = 64.03f;
|
||||
var crouchOffset = 46.03f;
|
||||
|
||||
// Standing position
|
||||
var standPosition = baseZ + standOffset;
|
||||
Assert.Equal(164.03f, standPosition);
|
||||
|
||||
// Crouching position
|
||||
var crouchPosition = baseZ + crouchOffset;
|
||||
Assert.Equal(146.03f, crouchPosition);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FlashlightEntity_Management()
|
||||
{
|
||||
// Test entity tracking dictionary behavior
|
||||
var playerEntities = new Dictionary<string, FakeLightEntity>();
|
||||
var playerKey = "test_player";
|
||||
|
||||
// No entity initially
|
||||
Assert.False(playerEntities.TryGetValue(playerKey, out _));
|
||||
|
||||
// Add entity
|
||||
var light = new FakeLightEntity { IsValid = true };
|
||||
playerEntities[playerKey] = light;
|
||||
Assert.True(playerEntities.TryGetValue(playerKey, out var retrieved));
|
||||
Assert.True(retrieved?.IsValid);
|
||||
|
||||
// Remove entity
|
||||
playerEntities.Remove(playerKey);
|
||||
Assert.False(playerEntities.TryGetValue(playerKey, out _));
|
||||
}
|
||||
|
||||
private class FakeLightEntity
|
||||
{
|
||||
public bool IsValid { get; set; }
|
||||
public void Remove() => IsValid = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue