Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
a092b20
feat: enhance player country information with country code and name
wiruwiru May 30, 2025
baf896c
docs: include the country code in the join message as an example
wiruwiru May 30, 2025
d52027b
fix: update plugin versión
wiruwiru May 30, 2025
634c440
feat: implementation of the multi-lang system; fix: several miscellan…
wiruwiru May 30, 2025
7506714
feat: enhance player management with caching and country info updates
wiruwiru May 30, 2025
664f4a6
update(docs): added new settings and a new multilang example
wiruwiru May 30, 2025
113a357
fix: crash caused by joinleave
wiruwiru May 30, 2025
a5613b5
feat: Added GlobalInterval to avoid configuring individual intervals …
wiruwiru May 30, 2025
f39ea8b
fix: fixed bugs when detecting the player's region in multi-lang
wiruwiru May 31, 2025
e9f4e38
fix: multi-lang bug in HandleTriggerCommand
wiruwiru May 31, 2025
8597002
fix: execution problems outside main thread
wiruwiru May 31, 2025
0dcd022
feat: add DisableOrder property to AdConfig and implement ordered ad …
wiruwiru May 31, 2025
ea975c2
fix: solutions to the errors of execution outside the main thread
wiruwiru May 31, 2025
593910b
docs: added `disableOrder` to the list of ads configurations
wiruwiru May 31, 2025
e49b95f
fix: exclude spectators from OnDead ad
wiruwiru Jun 1, 2025
cb4b5fc
fix: correct JSON property name and update condition for sending OnDe…
wiruwiru Jun 1, 2025
86cf052
docs: update readme to reorder ad configuration parameters
wiruwiru Jun 1, 2025
04aed4c
fix: update json property names to follow PascalCase convention
wiruwiru Jun 1, 2025
2e7993d
docs: fix configuration parameters in example
wiruwiru Jun 2, 2025
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
127 changes: 114 additions & 13 deletions AutomaticAds.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace AutomaticAds;
public class AutomaticAdsBase : BasePlugin, IPluginConfig<BaseConfigs>
{
public override string ModuleName => "AutomaticAds";
public override string ModuleVersion => "1.2.2";
public override string ModuleVersion => "1.2.3";
public override string ModuleAuthor => "luca.uy";
public override string ModuleDescription => "Send automatic messages to the chat and play a sound alert for users to see the message.";

Expand Down Expand Up @@ -70,7 +70,7 @@ private void InitializeServices()
_playerManager = new PlayerManager(this);
_ipQueryService = new IPQueryService();

_adService = new AdService(Config, _messageFormatter, _timerManager, _playerManager);
_adService = new AdService(Config, _messageFormatter, _timerManager, _playerManager, _ipQueryService);
_welcomeService = new WelcomeService(Config, _messageFormatter, _timerManager, _playerManager);
_joinLeaveService = new JoinLeaveService(Config, _messageFormatter, _playerManager, _ipQueryService, _timerManager);
}
Expand Down Expand Up @@ -120,7 +120,7 @@ private void RegisterReloadCommand()

try
{
Server.ExecuteCommand("css_plugins reload AutomaticAds");
Server.ExecuteCommand($"css_plugins reload {ModuleName}");
string formattedPrefix = _messageFormatter!.FormatMessage(Config.ChatPrefix);
commandInfo.ReplyToCommand($"{formattedPrefix} {Localizer["Reloaded"]}");
}
Expand Down Expand Up @@ -149,16 +149,49 @@ private void HandleTriggerCommand(CCSPlayerController? player, AdConfig ad)
if (!player.IsValidPlayer())
return;

string formattedPrefix = _messageFormatter!.FormatMessage(Config.ChatPrefix);
string formattedMessage = _messageFormatter.FormatMessage(ad.Message, player!.PlayerName, formattedPrefix);
Server.NextFrame(async () =>
{
try
{
string formattedPrefix = _messageFormatter!.FormatMessage(Config.ChatPrefix);
string formattedMessage;

if (Config.UseMultiLang)
{
Models.PlayerInfo playerInfo;

if (_playerManager!.NeedsCountryUpdate(player!.SteamID))
{
playerInfo = await _playerManager.GetOrCreatePlayerInfoAsync(player!, _ipQueryService);
}
else
{
playerInfo = _playerManager.GetBasicPlayerInfo(player!);
}

formattedMessage = _messageFormatter.FormatAdMessage(ad, playerInfo, formattedPrefix);
}
else
{
formattedMessage = _messageFormatter.FormatAdMessage(ad, player?.PlayerName ?? "Unknown", "", formattedPrefix);
}

_playerManager!.SendMessageToPlayer(player, formattedMessage, ad.DisplayType);
if (!string.IsNullOrWhiteSpace(formattedMessage))
{
_playerManager!.SendMessageToPlayer(player!, formattedMessage, ad.DisplayType);

string soundToPlay = ad.PlaySoundName ?? Config.GlobalPlaySound ?? string.Empty;
if (!ad.DisableSound && !string.IsNullOrWhiteSpace(soundToPlay))
{
_playerManager.PlaySoundToPlayer(player, soundToPlay);
}
string soundToPlay = ad.PlaySoundName ?? Config.GlobalPlaySound ?? string.Empty;
if (!ad.DisableSound && !string.IsNullOrWhiteSpace(soundToPlay))
{
_playerManager.PlaySoundToPlayer(player!, soundToPlay);
}
}
}
catch (Exception ex)
{
Console.WriteLine($"[AutomaticAds] Error in HandleTriggerCommand: {ex.Message}");
}
});
}

private bool HasReloadPermission(CCSPlayerController player)
Expand Down Expand Up @@ -254,12 +287,79 @@ public HookResult OnPlayerFullConnect(EventPlayerConnectFull @event, GameEventIn
if (@event.Userid?.IsValidPlayer() != true)
return HookResult.Continue;

_joinLeaveService?.HandlePlayerJoin(@event.Userid);
_welcomeService?.SendWelcomeMessage(@event.Userid);
var player = @event.Userid;

if (Config.EnableJoinLeaveMessages || Config.UseMultiLang)
{
HandlePlayerConnectWithCountryInfo(player);
}
else
{
HandlePlayerConnectBasic(player);
}

return HookResult.Continue;
}

private async void HandlePlayerConnectWithCountryInfo(CCSPlayerController player)
{
try
{
var playerInfo = await _playerManager!.GetOrCreatePlayerInfoAsync(player, _ipQueryService);
Server.NextFrame(() =>
{
try
{
if (player.IsValidPlayer())
{
if (Config.EnableJoinLeaveMessages)
{
_joinLeaveService?.HandlePlayerJoin(player);
}

_welcomeService?.SendWelcomeMessage(player);
}
}
catch (Exception ex)
{
Console.WriteLine($"[AutomaticAds] Error in HandlePlayerConnectWithCountryInfo NextFrame: {ex.Message}");
}
});
}
catch (Exception ex)
{
Console.WriteLine($"[AutomaticAds] Error in HandlePlayerConnectWithCountryInfo: {ex.Message}");
HandlePlayerConnectBasic(player);
}
}

private void HandlePlayerConnectBasic(CCSPlayerController player)
{
try
{
_playerManager!.GetBasicPlayerInfo(player);

Server.NextFrame(() =>
{
try
{
if (player.IsValidPlayer())
{
_welcomeService?.SendWelcomeMessage(player);
}
}
catch (Exception ex)
{
Console.WriteLine($"[AutomaticAds] Error in HandlePlayerConnectBasic NextFrame: {ex.Message}");
}
});
}
catch (Exception ex)
{
Console.WriteLine($"[AutomaticAds] Error in HandlePlayerConnectBasic: {ex.Message}");
}
}

[GameEventHandler]
private HookResult OnPlayerDisconnectPre(EventPlayerDisconnect @event, GameEventInfo info)
{
Expand All @@ -279,6 +379,7 @@ private HookResult OnPlayerDisconnect(EventPlayerDisconnect @event, GameEventInf

StopCenterHtmlMessage(player!);

_playerManager?.ClearPlayerCache(player!);
_joinLeaveService?.HandlePlayerLeave(player!);
_welcomeService?.OnPlayerDisconnect(player!);
_joinLeaveService?.OnPlayerDisconnect(player!);
Expand Down
16 changes: 13 additions & 3 deletions Config/BaseConfigs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,13 @@ public class BaseConfigs : BasePluginConfig
[JsonPropertyName("GlobalPlaySound")]
public string? GlobalPlaySound { get; set; } = "ui/panorama/popup_reveal_01";

[JsonPropertyName("GlobalInterval")]
public float GlobalInterval { get; set; } = 30.0f;

[JsonPropertyName("AdminFlag")]
public string? AdminFlag { get; set; } = "@css/generic";

[JsonPropertyName("sendAdsInOrder")]
[JsonPropertyName("SendAdsInOrder")]
public bool SendAdsInOrder { get; set; } = true;

[JsonPropertyName("UseWelcomeMessage")]
Expand All @@ -27,9 +30,15 @@ public class BaseConfigs : BasePluginConfig
[JsonPropertyName("WelcomeDelay")]
public float WelcomeDelay { get; set; } = 3.0f;

[JsonPropertyName("centerHtmlDisplayTime")]
[JsonPropertyName("CenterHtmlDisplayTime")]
public float centerHtmlDisplayTime { get; set; } = 5.0f;

[JsonPropertyName("UseMultiLang")]
public bool UseMultiLang { get; set; } = true;

[JsonPropertyName("DefaultLanguage")]
public string DefaultLanguage { get; set; } = "en";

[JsonPropertyName("Welcome")]
public List<WelcomeConfig> Welcome { get; set; } = new()
{
Expand All @@ -47,7 +56,7 @@ public class BaseConfigs : BasePluginConfig
{
new JoinLeaveConfig
{
JoinMessage = "{BLUE}{playername} ({id64}) joined the server from {country}! {RED}Online: {players}/{maxplayers}.",
JoinMessage = "{BLUE}{playername} ({id64}) joined the server from {country} ({country_code})! {RED}Online: {players}/{maxplayers}.",
LeaveMessage = "{BLUE}{playername} ({id64}) left the server!",
}
};
Expand Down Expand Up @@ -77,6 +86,7 @@ public class BaseConfigs : BasePluginConfig
Map = "all",
Interval = 1000,
DisableSound = true,
DisableOrder = true,
ViewFlag = "@css/vip"
},
new AdConfig
Expand Down
44 changes: 36 additions & 8 deletions Config/ConfigValidator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,60 @@ public static class ConfigValidator
{
public static void ValidateConfig(BaseConfigs config)
{
ValidateAds(config.Ads);
ValidateGlobalInterval(config);
ValidateAds(config.Ads, config.GlobalInterval);
ValidateChatPrefix(config);
ValidateGlobalPlaySound(config);
ValidateCenterHtmlDisplayTime(config);
}

private static void ValidateAds(List<AdConfig> ads)
private static void ValidateGlobalInterval(BaseConfigs config)
{
if (config.GlobalInterval > Constants.MaxInterval)
{
config.GlobalInterval = Constants.MaxInterval;
}

if (config.GlobalInterval < Constants.MinInterval)
{
config.GlobalInterval = Constants.MinInterval;
}
}

private static void ValidateAds(List<AdConfig> ads, float globalInterval)
{
foreach (var ad in ads)
{
ValidateAdInterval(ad);
ValidateAdInterval(ad, globalInterval);
ValidateTriggerAd(ad);
}
}

private static void ValidateAdInterval(AdConfig ad)
private static void ValidateAdInterval(AdConfig ad, float globalInterval)
{
if (ad.Interval > Constants.MaxInterval)
float effectiveInterval = ad.GetEffectiveInterval(globalInterval);

if (effectiveInterval > Constants.MaxInterval)
{
ad.Interval = Constants.MaxInterval;
if (ad.HasCustomInterval)
{
ad.IntervalRaw = Constants.MaxInterval;
}
else
{

}
}

if (ad.Interval < Constants.MinInterval)
if (effectiveInterval < Constants.MinInterval)
{
ad.Interval = Constants.MinInterval;
if (ad.HasCustomInterval)
{
ad.IntervalRaw = Constants.MinInterval;
}
}

ad.Interval = ad.GetEffectiveInterval(globalInterval);
}

private static void ValidateTriggerAd(AdConfig ad)
Expand Down
Loading