Skip to content
Open
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
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,26 @@ In few:




## Sound files verification checklist
Use this quick process when HUD/chat says a song is playing but no audio is heard:

1. **Copy the exact path from server logs**
- Example from logs: `play sounds/my_sound_pack/gdzie.vsnd_c`

2. **Check that this exact path exists inside your workshop addon/VPK**
- Path must match exactly (folder names and letter case).
- Linux servers are case-sensitive.

3. **Verify config paths**
- Every `music_list[].path` must point to a `.vsnd_c` file that exists in the mounted addon.

4. **Verify addon is mounted on the server**
- Ensure MultiAddonManager mounted your workshop addon and search path points to your addon VPK.

5. **Verify client can receive/use the resource**
- Join with a real player (not only bots) and test after one full round end.

6. **Cross-check plugin diagnostics**
- If you see `PlaySound: executing 'play ...'` but still no sound, issue is usually missing/wrong resource path in addon.

42 changes: 40 additions & 2 deletions RoundEndSound.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace RoundEndSound
public class RoundEndSound : BasePlugin, IPluginConfig<Config.Config>
{
public override string ModuleName => "Round End Sound";
public override string ModuleVersion => "1.0.2";
public override string ModuleVersion => "1.0.3";
public override string ModuleAuthor => "gleb_khlebov";
public override string ModuleDescription => "Plays a sound at the end of the round";

Expand Down Expand Up @@ -125,6 +125,8 @@ public void OnConfigParsed(Config.Config config)
_tracks = config.MusicList;
_trackCount = _tracks.Count;
Config = config;

_logUtils.Log($"Configuration loaded. Tracks count: {_trackCount}, random mode: {Config.RandomSelectionMode}, default music enabled: {Config.DefaultEnableMusic}");
}

[GameEventHandler]
Expand All @@ -137,6 +139,8 @@ public HookResult OnPlayerConnectFull(EventPlayerConnectFull @event, GameEventIn
if (_playerUtils.IsInvalidPlayer(player))
return HookResult.Continue;

_logUtils.Log($"Player connected: {player.PlayerName} ({player.SteamID})");

ResPlayer resPlayer = new ResPlayer
{
SteamId = player.SteamID.ToString(),
Expand All @@ -158,6 +162,8 @@ public HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInfo
if (_playerUtils.IsInvalidPlayer(player))
return HookResult.Continue;

_logUtils.Log($"Player disconnected: {player.PlayerName} ({player.SteamID})");

if (!_players.ContainsKey(steamId))
return HookResult.Continue;

Expand Down Expand Up @@ -187,10 +193,16 @@ public HookResult OnServerShutdown(EventServerShutdown @event, GameEventInfo inf
public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info)
{
if (_players.Count < 1)
{
_logUtils.Log("Round end: skipped because no players are tracked.");
return HookResult.Continue;
}

if (_trackCount < 1)
{
_logUtils.Log("Round end: skipped because music list is empty.");
return HookResult.Continue;
}

int trackIndex;
Sound currentSound;
Expand Down Expand Up @@ -226,6 +238,8 @@ public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info)
PlaySound(player, currentSound);
}

_logUtils.Log($"Round end: selected track [{trackIndex}] '{currentSound.Name}' ({currentSound.Path}) for {_players.Count} player(s).");

_lastPlayedTrack = currentSound;

return HookResult.Continue;
Expand All @@ -234,20 +248,44 @@ public HookResult OnRoundEnd(EventRoundEnd @event, GameEventInfo info)
private void PlaySound(ResPlayer? resPlayer, Sound sound)
{
CCSPlayerController? player = Utils.PlayerUtils.GetPlayerFromSteamId(resPlayer!.SteamId);

if (player == null)
{
_logUtils.Log($"PlaySound: player with SteamID {resPlayer.SteamId} was not found on server.");
return;
}

Server.NextFrame(() =>
{
if (resPlayer.SoundEnabled)
{
_logUtils.Log($"PlaySound: executing 'play {sound.Path}' for {player.PlayerName} ({player.SteamID}).");
player?.ExecuteClientCommand($"play {sound.Path}");
}
else
{
_logUtils.Log($"PlaySound: sound disabled for {player.PlayerName} ({player.SteamID}).");
}

if (resPlayer.ChatEnabled)
{
_logUtils.Log($"PlaySound: sending chat notification for {player.PlayerName} ({player.SteamID}) about '{sound.Name}'.");
player?.PrintToChat($"{Localizer["chat.Prefix"]}{Localizer["chat.PlayedSong", sound.Name]}{NewLine}{Localizer["chat.Settings"]}");
}
});
}

private void PlayLastSound(CCSPlayerController player)
{
if (_lastPlayedTrack == null)
{
_logUtils.Log($"PlayLastSound: requested by {player.PlayerName} ({player.SteamID}) but there is no previously played track.");
return;
}

Server.NextFrame(() =>
{
_logUtils.Log($"PlayLastSound: executing 'play {_lastPlayedTrack!.Path}' for {player.PlayerName} ({player.SteamID}).");
player.ExecuteClientCommand($"play {_lastPlayedTrack!.Path}");
player.PrintToChat($"{Localizer["chat.Prefix"]}{Localizer["chat.PlayedSong", _lastPlayedTrack.Name]}{NewLine}{Localizer["chat.Settings"]}");
});
Expand Down Expand Up @@ -403,4 +441,4 @@ private string BoolStateToString(bool state)
};
}
}
}
}
22 changes: 22 additions & 0 deletions RoundEndSound.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<AssemblyName>RoundEndSound</AssemblyName>
<RootNamespace>RoundEndSound</RootNamespace>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="*" />
<PackageReference Include="Dapper" Version="*" />
<PackageReference Include="MySqlConnector" Version="*" />
</ItemGroup>

<ItemGroup>
<Content Include="lang\**\*.json" CopyToOutputDirectory="PreserveNewest" />
<Content Include="workshop\**\*" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions Utils/PlayerUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ public static List<CCSPlayerController> GetOnlinePlayers(bool getBots = false)

public bool IsInvalidPlayer(CCSPlayerController player)
{
return player is { IsBot: true, IsHLTV: true, IsValid: false };
return !player.IsValid || player.IsBot || player.IsHLTV;
}
}
}