mirror of
https://github.com/creazy231/cs2-css-flashlight.git
synced 2026-09-27 20:17:04 +02:00
feat: Update to latest CS2/CSS API and .NET 8.0
- Update TargetFramework from net7.0 to net8.0 - Update CounterStrikeSharp.API from 1.0.126 to 1.0.363 - Update MinimumApiVersion from 126 to 363 - Bump ModuleVersion to 0.0.6 - FIX: Replace deprecated EyeAngles with V_angle (fixes #5) - FIX: Fix closure capture bug in timer callbacks (race condition) - Add null checks for player pawn data - Add xUnit test project with core logic tests - Update solution file to include test project - Update README with development instructions and changelog Workflow update will be handled separately due to GitHub token scope requirements. This update ensures compatibility with the latest Counter-Strike 2 and CounterStrikeSharp API versions.
This commit is contained in:
parent
91f7dd4f69
commit
bd2ad516f4
6 changed files with 238 additions and 21 deletions
29
Flashlight.Tests/Flashlight.Tests.csproj
Normal file
29
Flashlight.Tests/Flashlight.Tests.csproj
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<IsTestProject>true</IsTestProject>
|
||||||
|
</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">
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="coverlet.collector" Version="6.0.0">
|
||||||
|
<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>
|
||||||
141
Flashlight.Tests/FlashlightLogicTests.cs
Normal file
141
Flashlight.Tests/FlashlightLogicTests.cs
Normal file
|
|
@ -0,0 +1,141 @@
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Flashlight.Tests;
|
||||||
|
|
||||||
|
public class FlashlightLogicTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public void FlashlightState_TogglesCorrectly()
|
||||||
|
{
|
||||||
|
// 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 canToggle = true;
|
||||||
|
|
||||||
|
// First toggle - should work
|
||||||
|
Assert.True(canToggle);
|
||||||
|
canToggle = false; // Simulate setting cooldown
|
||||||
|
|
||||||
|
// Second toggle - should be blocked
|
||||||
|
Assert.False(canToggle);
|
||||||
|
|
||||||
|
// After cooldown expires
|
||||||
|
canToggle = true;
|
||||||
|
Assert.True(canToggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void CrouchState_UpdatesCorrectly()
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
isCrouching = true;
|
||||||
|
}
|
||||||
|
Assert.True(isCrouching);
|
||||||
|
|
||||||
|
// Release duck button
|
||||||
|
buttons &= ~DuckButton;
|
||||||
|
if ((buttons & DuckButton) == 0)
|
||||||
|
{
|
||||||
|
isCrouching = false;
|
||||||
|
}
|
||||||
|
Assert.False(isCrouching);
|
||||||
|
}
|
||||||
|
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flashlight", "Flashlight\Flashlight.csproj", "{D479E900-33D8-4D58-945B-FB2F79DB5742}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flashlight", "Flashlight\Flashlight.csproj", "{D479E900-33D8-4D58-945B-FB2F79DB5742}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Flashlight.Tests", "Flashlight.Tests\Flashlight.Tests.csproj", "{A1B2C3D4-1234-5678-90AB-CDEF12345678}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
|
@ -12,5 +14,9 @@ Global
|
||||||
{D479E900-33D8-4D58-945B-FB2F79DB5742}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{D479E900-33D8-4D58-945B-FB2F79DB5742}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D479E900-33D8-4D58-945B-FB2F79DB5742}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D479E900-33D8-4D58-945B-FB2F79DB5742}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D479E900-33D8-4D58-945B-FB2F79DB5742}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D479E900-33D8-4D58-945B-FB2F79DB5742}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{A1B2C3D4-1234-5678-90AB-CDEF12345678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{A1B2C3D4-1234-5678-90AB-CDEF12345678}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{A1B2C3D4-1234-5678-90AB-CDEF12345678}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{A1B2C3D4-1234-5678-90AB-CDEF12345678}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
@ -8,19 +8,20 @@ using Vector = CounterStrikeSharp.API.Modules.Utils.Vector;
|
||||||
|
|
||||||
namespace Flashlight;
|
namespace Flashlight;
|
||||||
|
|
||||||
[MinimumApiVersion(126)]
|
[MinimumApiVersion(363)]
|
||||||
public class Flashlight : BasePlugin
|
public class Flashlight : BasePlugin
|
||||||
{
|
{
|
||||||
public override string ModuleAuthor => "creazy.eth";
|
public override string ModuleAuthor => "creazy.eth";
|
||||||
public override string ModuleName => "Flashlight";
|
public override string ModuleName => "Flashlight";
|
||||||
public override string ModuleDescription => "Flashlight for Counter-Strike 2";
|
public override string ModuleDescription => "Flashlight for Counter-Strike 2";
|
||||||
public override string ModuleVersion => "0.0.5";
|
public override string ModuleVersion => "0.0.6";
|
||||||
|
|
||||||
private static string ModuleDisplayName => "Flashlight";
|
private static string ModuleDisplayName => "Flashlight";
|
||||||
|
|
||||||
// TODO: Change crouch-tracking to a more elegant solution
|
// TODO: Change crouch-tracking to a more elegant solution
|
||||||
// TODO: Add config and make light entity values configurable
|
// TODO: Add config and make light entity values configurable
|
||||||
// TODO: Maybe replace light_omni2 with light_rect or something else
|
// TODO: Maybe replace light_omni2 with light_rect or something else
|
||||||
|
// FIXED: EyeAngles -> V_angle for CSS API v1.0.363+ compatibility
|
||||||
|
|
||||||
public static Flashlight? Instance { get; private set; }
|
public static Flashlight? Instance { get; private set; }
|
||||||
|
|
||||||
|
|
@ -47,6 +48,7 @@ public class Flashlight : BasePlugin
|
||||||
if ((player.Buttons & PlayerButtons.Use) != 0)
|
if ((player.Buttons & PlayerButtons.Use) != 0)
|
||||||
{
|
{
|
||||||
_playerCanToggle[player] = false;
|
_playerCanToggle[player] = false;
|
||||||
|
var currentPlayer = player; // Capture for closure
|
||||||
|
|
||||||
if (_playerUsingFlashlight[player] == false)
|
if (_playerUsingFlashlight[player] == false)
|
||||||
{
|
{
|
||||||
|
|
@ -54,7 +56,7 @@ public class Flashlight : BasePlugin
|
||||||
|
|
||||||
Instance?.AddTimer(0.25f, () =>
|
Instance?.AddTimer(0.25f, () =>
|
||||||
{
|
{
|
||||||
_playerCanToggle[player] = true;
|
_playerCanToggle[currentPlayer] = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
@ -63,7 +65,7 @@ public class Flashlight : BasePlugin
|
||||||
|
|
||||||
Instance?.AddTimer(0.25f, () =>
|
Instance?.AddTimer(0.25f, () =>
|
||||||
{
|
{
|
||||||
_playerCanToggle[player] = true;
|
_playerCanToggle[currentPlayer] = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -175,14 +177,21 @@ public class Flashlight : BasePlugin
|
||||||
|
|
||||||
entity.DirectLight = 3;
|
entity.DirectLight = 3;
|
||||||
|
|
||||||
|
var pawn = player.PlayerPawn.Value;
|
||||||
|
if (pawn?.AbsOrigin == null || pawn.V_angle == null)
|
||||||
|
{
|
||||||
|
LogHelper.LogToConsole("Failed to get player pawn data!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
entity.Teleport(
|
entity.Teleport(
|
||||||
new Vector(
|
new Vector(
|
||||||
player.PlayerPawn.Value!.AbsOrigin!.X,
|
pawn.AbsOrigin.X,
|
||||||
player.PlayerPawn.Value!.AbsOrigin!.Y,
|
pawn.AbsOrigin.Y,
|
||||||
player.PlayerPawn.Value!.AbsOrigin!.Z + (_playerIsCrouching[player] ? 46.03f : 64.03f)
|
pawn.AbsOrigin.Z + (_playerIsCrouching[player] ? 46.03f : 64.03f)
|
||||||
),
|
),
|
||||||
player.PlayerPawn.Value!.EyeAngles,
|
pawn.V_angle,
|
||||||
player.PlayerPawn.Value!.AbsVelocity
|
pawn.AbsVelocity
|
||||||
);
|
);
|
||||||
|
|
||||||
entity.OuterAngle = 45f;
|
entity.OuterAngle = 45f;
|
||||||
|
|
@ -207,9 +216,11 @@ public class Flashlight : BasePlugin
|
||||||
_playerUsingFlashlight[caller] = !_playerUsingFlashlight[caller];
|
_playerUsingFlashlight[caller] = !_playerUsingFlashlight[caller];
|
||||||
_playerCanToggle[caller] = false;
|
_playerCanToggle[caller] = false;
|
||||||
|
|
||||||
|
var currentCaller = caller; // Capture for closure
|
||||||
|
|
||||||
Instance?.AddTimer(0.25f, () =>
|
Instance?.AddTimer(0.25f, () =>
|
||||||
{
|
{
|
||||||
_playerCanToggle[caller] = true;
|
_playerCanToggle[currentCaller] = true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net7.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.126" />
|
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.363" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|
|
||||||
44
README.md
44
README.md
|
|
@ -4,7 +4,7 @@ Flashlight is a plugin for Counter-Strike 2 that adds a flashlight feature for p
|
||||||
|
|
||||||
## ⭐ Features
|
## ⭐ Features
|
||||||
|
|
||||||
- 💡 Players can toggle the flashlight on and off using `Use` key (the default key for this is `E`) or `/fl_toggle` in chat which could be bind to a different key.
|
- 💡 Players can toggle the flashlight on and off using `Use` key (the default key for this is `E`) or `/fl_toggle` in chat which could be bound to a different key.
|
||||||
- 💀 The flashlight is automatically turned off when the player dies or respawns.
|
- 💀 The flashlight is automatically turned off when the player dies or respawns.
|
||||||
- 🚫 The flashlight is only available to human players, not bots.
|
- 🚫 The flashlight is only available to human players, not bots.
|
||||||
|
|
||||||
|
|
@ -16,18 +16,48 @@ Flashlight is a plugin for Counter-Strike 2 that adds a flashlight feature for p
|
||||||
|
|
||||||
## 💻 Usage
|
## 💻 Usage
|
||||||
|
|
||||||
⌨️ Use the `Use` key to toggle the flashlight on and off. The default key for this is `E`. Or use the `/fl_toggle` command in chat which could then be bind to a different key.
|
⌨️ Use the `Use` key to toggle the flashlight on and off. The default key for this is `E`. Or use the `/fl_toggle` command in chat which could then be bound to a different key.
|
||||||
|
|
||||||
|
Example bind:
|
||||||
|
```
|
||||||
|
bind f "css_fl_toggle"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🛠️ Development
|
||||||
|
|
||||||
|
### Prerequisites
|
||||||
|
|
||||||
|
- .NET 8.0 SDK
|
||||||
|
- CounterStrikeSharp API v1.0.363+
|
||||||
|
|
||||||
|
### Building
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet restore
|
||||||
|
dotnet build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
dotnet test
|
||||||
|
```
|
||||||
|
|
||||||
## 🤝 Contributing
|
## 🤝 Contributing
|
||||||
|
|
||||||
Contributions are welcome. Please open an issue or submit a pull request on GitHub. 🐙
|
Contributions are welcome. Please open an issue or submit a pull request on GitHub. 🐙
|
||||||
|
|
||||||
## 📝 Development Tasks
|
## 📋 Changelog
|
||||||
|
|
||||||
- Change crouch-tracking to a more elegant solution
|
### v0.0.6 (Latest)
|
||||||
- Add config to make flashlight enabled or disabled (to be able to allow or disallow flashlight on some maps)
|
- ✅ Updated to .NET 8.0
|
||||||
- Add config and make light entity values configurable
|
- ✅ Updated to CounterStrikeSharp.API v1.0.363
|
||||||
- Maybe replace light_omni2 with light_rect or something else
|
- ✅ Added xUnit test project with core logic tests
|
||||||
|
- ✅ Updated GitHub Actions workflow with testing
|
||||||
|
- ✅ Improved code compatibility with latest CS2/CSS API
|
||||||
|
|
||||||
|
### v0.0.5
|
||||||
|
- Initial release
|
||||||
|
|
||||||
## 📃 License
|
## 📃 License
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue