Skip to content

Commit 4ac29a6

Browse files
committed
Initial commit
0 parents  commit 4ac29a6

20 files changed

+915
-0
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.idea
2+
CS2-CustomVotes/bin
3+
CS2-CustomVotes/obj
4+
CS2-CustomVotes.Shared/bin
5+
CS2-CustomVotes.Shared/obj
6+
Public
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net7.0</TargetFramework>
5+
<RootNamespace>CS2_CustomVotes.Shared</RootNamespace>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
</Project>
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
using CS2_CustomVotes.Shared.Models;
2+
3+
namespace CS2_CustomVotes.Shared;
4+
5+
public interface ICustomVoteApi
6+
{
7+
public void AddCustomVote(string name, string description, string defaultOption, float timeToVote, Dictionary<string, VoteOption> options, string style);
8+
public void AddCustomVote(string name, List<string> aliases, string description, string defaultOption, float timeToVote, Dictionary<string, VoteOption> options, string style);
9+
public void RemoveCustomVote(string name);
10+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
using System.Text.Json.Serialization;
2+
3+
namespace CS2_CustomVotes.Shared.Models;
4+
5+
public class VoteOption
6+
{
7+
public VoteOption(string text, List<string> commands)
8+
{
9+
Text = text;
10+
Commands = commands;
11+
}
12+
13+
[JsonPropertyName("Text")] public string Text { get; set; } = null!;
14+
15+
[JsonPropertyName("Commands")] public List<string> Commands { get; set; } = new();
16+
}

CS2-CustomVotes.sln

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
Microsoft Visual Studio Solution File, Format Version 12.00
3+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS2-CustomVotes", "CS2-CustomVotes\CS2-CustomVotes.csproj", "{D7805B32-A457-4DFE-A955-920F4A39F506}"
4+
EndProject
5+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CS2-CustomVotes.Shared", "CS2-CustomVotes.Shared\CS2-CustomVotes.Shared.csproj", "{31457B2B-09A2-48F9-98EA-F30F22732BC6}"
6+
EndProject
7+
Global
8+
GlobalSection(SolutionConfigurationPlatforms) = preSolution
9+
Debug|Any CPU = Debug|Any CPU
10+
Release|Any CPU = Release|Any CPU
11+
EndGlobalSection
12+
GlobalSection(ProjectConfigurationPlatforms) = postSolution
13+
{D7805B32-A457-4DFE-A955-920F4A39F506}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
14+
{D7805B32-A457-4DFE-A955-920F4A39F506}.Debug|Any CPU.Build.0 = Debug|Any CPU
15+
{D7805B32-A457-4DFE-A955-920F4A39F506}.Release|Any CPU.ActiveCfg = Release|Any CPU
16+
{D7805B32-A457-4DFE-A955-920F4A39F506}.Release|Any CPU.Build.0 = Release|Any CPU
17+
{31457B2B-09A2-48F9-98EA-F30F22732BC6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
18+
{31457B2B-09A2-48F9-98EA-F30F22732BC6}.Debug|Any CPU.Build.0 = Debug|Any CPU
19+
{31457B2B-09A2-48F9-98EA-F30F22732BC6}.Release|Any CPU.ActiveCfg = Release|Any CPU
20+
{31457B2B-09A2-48F9-98EA-F30F22732BC6}.Release|Any CPU.Build.0 = Release|Any CPU
21+
EndGlobalSection
22+
EndGlobal
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net7.0</TargetFramework>
5+
<RootNamespace>CS2_CustomVotes</RootNamespace>
6+
<ImplicitUsings>enable</ImplicitUsings>
7+
<Nullable>enable</Nullable>
8+
</PropertyGroup>
9+
10+
<ItemGroup>
11+
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.191" />
12+
</ItemGroup>
13+
14+
<ItemGroup>
15+
<ProjectReference Include="..\CS2-CustomVotes.Shared\CS2-CustomVotes.Shared.csproj" />
16+
</ItemGroup>
17+
18+
</Project>
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using CounterStrikeSharp.API.Core;
2+
using CounterStrikeSharp.API.Modules.Utils;
3+
4+
namespace CS2_CustomVotes.Extensions;
5+
6+
public static class PlayerControllerExtensions
7+
{
8+
internal static bool IsPlayer(this CCSPlayerController? player)
9+
{
10+
return player is { IsValid: true, IsHLTV: false, IsBot: false, UserId: not null, SteamID: >0 };
11+
}
12+
13+
internal static string GetTeamString(this CCSPlayerController? player, bool abbreviate = false)
14+
{
15+
var teamNum = player != null ? (int)player.Team : -1;
16+
var teamStr = teamNum switch
17+
{
18+
(int)CsTeam.None => "team.none",
19+
(int)CsTeam.CounterTerrorist => "team.ct",
20+
(int)CsTeam.Terrorist => "team.t",
21+
(int)CsTeam.Spectator => "team.spec",
22+
_ => ""
23+
};
24+
25+
return abbreviate ? teamStr + ".short" : teamStr + ".long";
26+
}
27+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
using CounterStrikeSharp.API.Core;
2+
using CounterStrikeSharp.API.Modules.Menu;
3+
using CS2_CustomVotes.Helpers;
4+
using CS2_CustomVotes.Models;
5+
using Microsoft.Extensions.Localization;
6+
7+
namespace CS2_CustomVotes.Factories;
8+
9+
public interface IActiveVoteFactory
10+
{
11+
public ActiveVote Create(CustomVote vote, Action<string> onEndVote, Action<CCSPlayerController?, string> onPlayerVoted);
12+
}
13+
14+
public class ActiveVoteFactory : IActiveVoteFactory
15+
{
16+
private readonly CustomVotes _plugin;
17+
private readonly IStringLocalizer _localizer;
18+
19+
public ActiveVoteFactory(CustomVotes plugin, IStringLocalizer localizer)
20+
{
21+
_plugin = plugin;
22+
_localizer = localizer;
23+
}
24+
25+
public ActiveVote Create(CustomVote vote, Action<string> onEndVote, Action<CCSPlayerController?, string> onPlayerVoted)
26+
{
27+
var activeVote = new ActiveVote(_plugin, vote);
28+
29+
// start vote timeout and save handle
30+
activeVote.VoteTimeout = _plugin.AddTimer(activeVote.Vote.TimeToVote, () => onEndVote(vote.Command));
31+
32+
// set vote style (global override always takes priority)
33+
var style = _plugin.Config.ForceStyle == "none" ? vote.Style : _plugin.Config.ForceStyle;
34+
35+
if (style == "center")
36+
activeVote.VoteMenu = new CenterHtmlMenu(activeVote.Vote.Description);
37+
else
38+
activeVote.VoteMenu = new ChatMenu(activeVote.Vote.Description);
39+
40+
foreach (var voteOption in activeVote.Vote.Options)
41+
activeVote.VoteMenu.AddMenuOption(style == "center" ? _localizer[voteOption.Key] : Chat.FormatMessage(_localizer[voteOption.Value.Text]),
42+
(caller, option) => onPlayerVoted(caller, option.Text));
43+
44+
return activeVote;
45+
}
46+
}

CS2-CustomVotes/Helpers/Chat.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using System.Reflection;
2+
using CounterStrikeSharp.API.Modules.Utils;
3+
4+
namespace CS2_CustomVotes.Helpers;
5+
6+
public static class Chat
7+
{
8+
private static readonly Dictionary<string, char> PredefinedColors = typeof(ChatColors)
9+
.GetFields(BindingFlags.Public | BindingFlags.Static)
10+
.ToDictionary(
11+
field => $"{{{field.Name}}}",
12+
field => (char)(field.GetValue(null) ?? '\x01')
13+
);
14+
15+
public static string FormatMessage(string message)
16+
{
17+
foreach (var color in PredefinedColors)
18+
message = message.Replace(color.Key, $"{color.Value}");
19+
20+
return message;
21+
}
22+
23+
public static string CleanMessage(string message)
24+
{
25+
foreach (var color in PredefinedColors)
26+
{
27+
message = message.Replace(color.Key, "");
28+
message = message.Replace(color.Value.ToString(), "");
29+
}
30+
31+
return message;
32+
}
33+
}

CS2-CustomVotes/Helpers/Config.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System.Reflection;
2+
using System.Text.Json;
3+
using CounterStrikeSharp.API;
4+
using CounterStrikeSharp.API.Core;
5+
6+
namespace CS2_CustomVotes.Helpers;
7+
8+
public static class Config
9+
{
10+
private static readonly string AssemblyName = Assembly.GetExecutingAssembly().GetName().Name ?? "";
11+
private static readonly string CfgPath = $"{Server.GameDirectory}/csgo/addons/counterstrikesharp/configs/plugins/{AssemblyName}/{AssemblyName}.json";
12+
13+
public static void Update<T>(this T config) where T : BasePluginConfig, new()
14+
{
15+
// get current config version
16+
var newCfgVersion = new T().Version;
17+
18+
// loaded config is up to date
19+
if (config.Version == newCfgVersion)
20+
return;
21+
22+
// update the version
23+
config.Version = newCfgVersion;
24+
25+
// serialize the updated config back to json
26+
var updatedJsonContent = JsonSerializer.Serialize(config, new JsonSerializerOptions { WriteIndented = true });
27+
File.WriteAllText(CfgPath, updatedJsonContent);
28+
}
29+
}

0 commit comments

Comments
 (0)