Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #30

Merged
merged 33 commits into from
Oct 29, 2024
Merged

Dev #30

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
dcfc19b
Bump xunit from 2.9.0 to 2.9.1
dependabot[bot] Sep 23, 2024
bea060a
Keep invitation dates consistent
MSWS Sep 24, 2024
a0feca8
Merge pull request #20 from edgegamers/dependabot/nuget/dev/xunit-2.9.1
MSWS Sep 24, 2024
d003ee7
Bump CounterStrikeSharp.API from 1.0.264 to 1.0.266
dependabot[bot] Sep 24, 2024
a92e2e3
Merge pull request #19 from edgegamers/dependabot/nuget/dev/CounterSt…
MSWS Sep 24, 2024
bc1d7fc
Bump xunit from 2.9.1 to 2.9.2
dependabot[bot] Sep 30, 2024
fdd4fb4
Merge pull request #21 from edgegamers/dependabot/nuget/dev/xunit-2.9.2
MSWS Oct 20, 2024
ba297d3
Keep invitation dates consistent
MSWS Sep 24, 2024
09c74e0
Bump xunit from 2.9.0 to 2.9.1
dependabot[bot] Sep 23, 2024
882fc4e
Bump CounterStrikeSharp.API from 1.0.264 to 1.0.266
dependabot[bot] Sep 24, 2024
7f451e1
Resolve
MSWS Oct 20, 2024
cecd484
Feat/raffle (#29)
MSWS Oct 22, 2024
5133337
Bump Xunit.DependencyInjection from 9.4.0 to 9.5.0 (#23)
dependabot[bot] Oct 22, 2024
f668162
Bump CounterStrikeSharp.API from 1.0.266 to 1.0.284 (#28)
dependabot[bot] Oct 22, 2024
6a3581a
Bump Microsoft.Data.Sqlite from 8.0.8 to 8.0.10 (#26)
dependabot[bot] Oct 22, 2024
4c91135
Bump Microsoft.Extensions.DependencyInjection.Abstractions
dependabot[bot] Oct 22, 2024
f0a6813
Merge pull request #25 from edgegamers/dependabot/nuget/dev/Microsoft…
dependabot[bot] Oct 22, 2024
b18eb94
Register commands
MSWS Oct 22, 2024
ccf56ed
Merge branch 'dev' of github.com:edgegamers/Gangs into dev
MSWS Oct 22, 2024
f45d908
Reorganize project
MSWS Oct 22, 2024
867c358
Fix recursion
MSWS Oct 22, 2024
9be360f
Fix coinflipping into negatives
MSWS Oct 22, 2024
f7a9ddf
Fix threading
MSWS Oct 22, 2024
ffbd5b4
Add debugging
MSWS Oct 24, 2024
e8b59da
Add more feedback
MSWS Oct 24, 2024
f620c53
Add credit distribution
MSWS Oct 24, 2024
8e16999
More work
MSWS Oct 24, 2024
82bde11
More work
MSWS Oct 24, 2024
9dd7b36
Add anti-crash
MSWS Oct 24, 2024
4ceb17d
Re-add feedback
MSWS Oct 24, 2024
f2a95eb
Debug
MSWS Oct 25, 2024
47adaec
Add permission feedback
MSWS Oct 25, 2024
ccfe5d7
Update min/max raffle amos
MSWS Oct 25, 2024
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
7 changes: 7 additions & 0 deletions Gangs.sln
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StatsTracker", "src\StatsTr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EcoRewards", "src\EcoRewards\EcoRewards.csproj", "{253C7948-3411-4860-BDDE-B1CA23FCE4DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Raffle", "src\CS2\Raffle\Raffle.csproj", "{05B36B8C-F430-411B-9B8D-61EB14D5E5FC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -78,6 +80,10 @@ Global
{253C7948-3411-4860-BDDE-B1CA23FCE4DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{253C7948-3411-4860-BDDE-B1CA23FCE4DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{253C7948-3411-4860-BDDE-B1CA23FCE4DC}.Release|Any CPU.Build.0 = Release|Any CPU
{05B36B8C-F430-411B-9B8D-61EB14D5E5FC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{05B36B8C-F430-411B-9B8D-61EB14D5E5FC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{05B36B8C-F430-411B-9B8D-61EB14D5E5FC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{05B36B8C-F430-411B-9B8D-61EB14D5E5FC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{74B15261-4B12-4EF6-859A-E46B315E7DD3} = {3AB7703F-880F-4A41-96EE-B891FA888C65}
Expand All @@ -90,5 +96,6 @@ Global
{1899055E-62B8-4907-85A2-DFE22531729E} = {32D392D5-C809-45A1-A5FB-58C941D86057}
{B850CFA3-AFE8-4012-8BC2-9A4BC12B9748} = {AC07CD29-5C9D-4AD1-99C7-01DABAB8D0EC}
{253C7948-3411-4860-BDDE-B1CA23FCE4DC} = {AC07CD29-5C9D-4AD1-99C7-01DABAB8D0EC}
{05B36B8C-F430-411B-9B8D-61EB14D5E5FC} = {AC07CD29-5C9D-4AD1-99C7-01DABAB8D0EC}
EndGlobalSection
EndGlobal
8 changes: 7 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -106,5 +106,11 @@
"rank.cannot.owner": "%prefix%You cannot {0} as the owner, use %color.command%/gang transfer <player>%color.default% to transfer ownership.",
"command.invite.doorpolicy": "%prefix%Your door policy must be set to invite-only to send invites.",
"menu.format.invitation": "%color.special%{0}%color.default% invited %color.target%{1}%color.default% on %color.emph%{2}%color.default%.",
"menu.format.request": "%color.target%{0}%color.default% requested to join on %color.emph%{1}%color.default%."
"menu.format.request": "%color.target%{0}%color.default% requested to join on %color.emph%{1}%color.default%.",
"raffle.begin": "%prefix%A raffle for %color.currency%{0} %currency%%s%%color.default% has begun. Type %color.command%/raffle%color.default% to enter.",
"raffle.preannounce": "%prefix%Raffle closed! Collected %color.currency%{0} %currency%%s%%color.default% across %color.number%{1}%color.default% entrant%s%.",
"raffle.winner": "%prefix%%color.target%{0}%color.default% won the raffle with a %color.number%{1}%color.default% chance!",
"raffle.notactive": "%prefix%There is no active raffle.",
"raffle.notopen": "%prefix%The raffle closed entries and is currently drawing.",
"raffle.noentrants": "%prefix%There are no entrants in the raffle."
}
4 changes: 2 additions & 2 deletions src/CS2/Commands/CoinflipCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,10 @@ await Server.NextFrameAsync(() => {
return CommandResult.SUCCESS;
}

if (!await eco.CanAfford(executor, request.Amount, true)) {
if (!await eco.CanAfford(senderWrapper, request.Amount, true)) {
wrapper.ReplySync(locale.Get(
MSG.COMMAND_COINFLIP_INSUFFICIENT_FUNDS_OTHER,
executor.Name ?? executor.Steam.ToString(), request.Amount));
senderWrapper.Name ?? senderWrapper.Steam.ToString(), request.Amount));
return CommandResult.SUCCESS;
}

Expand Down
2 changes: 1 addition & 1 deletion src/CS2/Commands/Commands.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.1"/>
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2"/>
</ItemGroup>

<ItemGroup>
Expand Down
2 changes: 2 additions & 0 deletions src/CS2/Gangs/GangServiceCollection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Localization;
using Mock;
using Raffle;
using SQLImpl;
using Stats.Perk;
using StatsTracker;
Expand Down Expand Up @@ -41,6 +42,7 @@ public void ConfigureServices(IServiceCollection serviceCollection) {
serviceCollection.RegisterStatsTracker();
serviceCollection.RegisterPerks();
serviceCollection.RegisterRewards();
serviceCollection.RegisterRaffle();

serviceCollection.AddPluginBehavior<PlayerJoinCreationListener>();
serviceCollection
Expand Down
6 changes: 4 additions & 2 deletions src/CS2/Gangs/Gangs.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\Raffle\Raffle.csproj" />
<ProjectReference Include="..\..\EcoRewards\EcoRewards.csproj"/>
<ProjectReference Include="..\..\StatsTracker\StatsTracker.csproj"/>
<ProjectReference Include="..\Commands\Commands.csproj"/>
<ProjectReference Include="..\..\GangsAPI\GangsAPI.csproj"/>
<ProjectReference Include="..\..\GangsImpl\MySQL\MySQL.csproj"/>
<ProjectReference Include="..\Raffle\Raffle.csproj" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.264"/>
<PackageReference Include="xunit" Version="2.9.0"/>
<PackageReference Include="CounterStrikeSharp.API" Version="1.0.284"/>
<PackageReference Include="xunit" Version="2.9.2"/>
</ItemGroup>

<ItemGroup>
Expand Down
10 changes: 10 additions & 0 deletions src/CS2/Raffle/IRaffleManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace Raffle;

public interface IRaffleManager {
Raffle? Raffle { get; }

bool StartRaffle(int buyIn);
bool AreEntriesOpen();
void SetEntriesOpen(float seconds);
void DrawWinner();
}
27 changes: 27 additions & 0 deletions src/CS2/Raffle/Raffle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Raffle;

public class Raffle(int buyIn) {
private readonly HashSet<ulong> players = [];

public int BuyIn => buyIn;

public int Value => players.Count * buyIn;

public int TotalPlayers => players.Count;

public void AddPlayer(ulong player) { players.Add(player); }

/// <summary>
/// Get the winner of the raffle
/// </summary>
/// <returns>The winner, or null if there are no players</returns>
public ulong? GetWinner() {
if (players.Count == 0) return null;
var random = new Random();
var winnerIndex = random.Next(players.Count);
// remove the winner from the list of players
var winner = players.ElementAt(winnerIndex);
players.Remove(winner);
return winner;
}
}
13 changes: 13 additions & 0 deletions src/CS2/Raffle/Raffle.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\GangsAPI\GangsAPI.csproj"/>
</ItemGroup>

</Project>
10 changes: 10 additions & 0 deletions src/CS2/Raffle/RaffleCollection.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using GangsAPI.Extensions;
using Microsoft.Extensions.DependencyInjection;

namespace Raffle;

public static class RaffleCollection {
public static void RegisterRaffle(this IServiceCollection provider) {
provider.AddPluginBehavior<IRaffleManager, RaffleManager>();
}
}
45 changes: 45 additions & 0 deletions src/CS2/Raffle/RaffleCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using CounterStrikeSharp.API.Core;
using GangsAPI;
using GangsAPI.Data;
using GangsAPI.Data.Command;
using GangsAPI.Services;
using GangsAPI.Services.Commands;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;

namespace Raffle;

public class RaffleCommand(IServiceProvider provider) : ICommand {
private readonly IEcoManager eco = provider.GetRequiredService<IEcoManager>();

private readonly IRaffleManager raffle =
provider.GetRequiredService<IRaffleManager>();

private readonly IStringLocalizer locale =
provider.GetRequiredService<IStringLocalizer>();

public string Name => "css_raffle";

public async Task<CommandResult> Execute(PlayerWrapper? executor,
CommandInfoWrapper info) {
if (executor == null) return CommandResult.PLAYER_ONLY;
if (info.ArgCount != 1) return CommandResult.PRINT_USAGE;

if (raffle.Raffle == null) {
info.ReplySync(locale.Get(MSG.RAFFLE_NOTACTIVE));
return CommandResult.SUCCESS;
}

if (!raffle.AreEntriesOpen()) {
info.ReplySync(locale.Get(MSG.RAFFLE_NOTOPEN));
return CommandResult.SUCCESS;
}

if (await eco.TryPurchase(executor, raffle.Raffle.BuyIn, true,
"Raffle Ticket", true) < 0)
return CommandResult.SUCCESS;

raffle.Raffle.AddPlayer(executor.Steam);
return CommandResult.SUCCESS;
}
}
129 changes: 129 additions & 0 deletions src/CS2/Raffle/RaffleManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Cvars;
using GangsAPI;
using GangsAPI.Data;
using GangsAPI.Services;
using GangsAPI.Services.Commands;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Localization;
using Timer = CounterStrikeSharp.API.Modules.Timers.Timer;

namespace Raffle;

public class RaffleManager(IServiceProvider provider)
: IPluginBehavior, IRaffleManager {
public static FakeConVar<float> CV_RAFFLE_CHANCE =
new("cs2_gangs_raffle_chance", "The chance of a raffle starting per round",
0.1f);

public static FakeConVar<int> CV_RAFFLE_COOLDOWN =
new("cs2_gangs_raffle_cooldown", "Minimum number of rounds between raffles",
2);

public static FakeConVar<int> CV_RAFFLE_MINIMUM =
new("cs2_gangs_raffle_min", "Minimum amount per player", 20);

public static FakeConVar<int> CV_RAFFLE_MAXIMUM =
new("cs2_gangs_raffle_max", "Maximum amount per player", 500);

public static FakeConVar<float> CV_RAFFLE_DURATION =
new("cs2_gangs_raffle_duration", "Time to give playeres to enter raffle",
30);

private static readonly Random rng = new();
private int cooldownRounds;

private Timer? entryTimer;
private BasePlugin? plugin;

private readonly IStringLocalizer locale =
provider.GetRequiredService<IStringLocalizer>();

private readonly IEcoManager eco = provider.GetRequiredService<IEcoManager>();

public void Start(BasePlugin? plugin, bool hotReload) {
if (plugin == null) return;
this.plugin = plugin;
var cmd = provider.GetRequiredService<ICommandManager>();
cmd.RegisterCommand(new RaffleCommand(provider));
cmd.RegisterCommand(new StartRaffleCommand(provider));
}

public Raffle? Raffle { get; private set; }

public bool StartRaffle(int buyIn) {
if (Raffle != null || plugin == null) return false;
Raffle = new Raffle(buyIn);

SetEntriesOpen(CV_RAFFLE_DURATION.Value);
return true;
}

public bool AreEntriesOpen() { return entryTimer != null; }

public void SetEntriesOpen(float seconds) {
entryTimer?.Kill();
if (plugin == null || Raffle == null) return;
Server.PrintToChatAll(locale.Get(MSG.RAFFLE_BEGIN, Raffle?.BuyIn ?? 0));

entryTimer = plugin.AddTimer(seconds, () => {
entryTimer = null;
if (Raffle == null) return;

Server.PrintToChatAll(locale.Get(MSG.RAFFLE_PRE_ANNOUNCE, Raffle.Value,
Raffle.TotalPlayers));

plugin.AddTimer(5, DrawWinner);
});
}

public void DrawWinner() {
if (Raffle == null || plugin == null) return;
var players = Raffle.TotalPlayers;
if (players <= 0) {
Server.PrintToChatAll(locale.Get(MSG.RAFFLE_NOENTRANTS));
Raffle = null;
return;
}

var total = Raffle.Value;
ulong? winner;
do { winner = Raffle.GetWinner(); } while (winner != null
&& Raffle.TotalPlayers > 0);

if (winner == null) {
Server.PrintToChatAll(locale.Get(MSG.GENERIC_ERROR_INFO,
"Could not find a winner"));
Raffle = null;
return;
}

var name = Utilities.GetPlayerFromSteamId(winner.Value)?.PlayerName
?? winner.ToString() ?? "";

var wrapper = new PlayerWrapper(winner.Value, name);

Task.Run(async () => await eco.Grant(wrapper, total, true, "Raffle"));

Server.PrintToChatAll(locale.Get(MSG.RAFFLE_WINNER, name,
(1.0f / players).ToString("P1")));
Raffle = null;
}

[GameEventHandler]
public HookResult OnRoundStart(EventRoundStart ev, GameEventInfo info) {
if (RoundUtil.IsWarmup()) return HookResult.Continue;
if (cooldownRounds > 0) {
cooldownRounds--;
return HookResult.Continue;
}

if (rng.NextDouble() > CV_RAFFLE_CHANCE.Value) return HookResult.Continue;
var amo = rng.Next(CV_RAFFLE_MINIMUM.Value, CV_RAFFLE_MAXIMUM.Value);
StartRaffle(amo);
cooldownRounds = CV_RAFFLE_COOLDOWN.Value;
return HookResult.Continue;
}
}
42 changes: 42 additions & 0 deletions src/CS2/Raffle/RoundUtil.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using CounterStrikeSharp.API;

namespace Raffle;

public static class RoundUtil {
public static int GetTimeElapsed() {
var gamerules = ServerExtensions.GetGameRules();
if (gamerules == null) return 0;
var freezeTime = gamerules.FreezeTime;
return (int)(Server.CurrentTime - gamerules.RoundStartTime - freezeTime);
}

public static int GetTimeRemaining() {
var gamerules = ServerExtensions.GetGameRules();
if (gamerules == null) return 0;
return gamerules.RoundTime - GetTimeElapsed();
}

public static void SetTimeRemaining(int seconds) {
var gamerules = ServerExtensions.GetGameRules();
if (gamerules == null) return;
gamerules.RoundTime = GetTimeElapsed() + seconds;
var proxy = ServerExtensions.GetGameRulesProxy();
if (proxy == null) return;
Utilities.SetStateChanged(proxy, "CCSGameRulesProxy", "m_pGameRules");
}

public static void AddTimeRemaining(int time) {
var gamerules = ServerExtensions.GetGameRules();
if (gamerules == null) return;
gamerules.RoundTime += time;

var proxy = ServerExtensions.GetGameRulesProxy();
if (proxy == null) return;
Utilities.SetStateChanged(proxy, "CCSGameRulesProxy", "m_pGameRules");
}

public static bool IsWarmup() {
var rules = ServerExtensions.GetGameRules();
return rules == null || rules.WarmupPeriod;
}
}
Loading
Loading