Skip to content

Commit 60157ba

Browse files
Add Automatic Bans feature (disabled by default)
1 parent a47cb32 commit 60157ba

File tree

8 files changed

+228
-17
lines changed

8 files changed

+228
-17
lines changed
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
using RestoreMonarchy.PlayerStats.Models;
2+
using SDG.NetTransport;
3+
using SDG.Unturned;
4+
using Steamworks;
5+
using System.Collections.Generic;
6+
7+
namespace RestoreMonarchy.PlayerStats.Components
8+
{
9+
public partial class PlayerStatsComponent
10+
{
11+
internal void CheckAutomaticBan()
12+
{
13+
if (!configuration.EnableAutomaticBans)
14+
{
15+
return;
16+
}
17+
18+
foreach (AutomaticBan ban in configuration.AutomaticBans)
19+
{
20+
if (ban.CheckConditions(PlayerData))
21+
{
22+
ITransportConnection transportConnection = Player.channel.owner.transportConnection;
23+
uint ipAddress = 0;
24+
transportConnection?.TryGetIPv4Address(out ipAddress);
25+
26+
IEnumerable<byte[]> hwids = Player.channel.owner.playerID.GetHwids();
27+
Provider.requestBanPlayer(CSteamID.Nil, SteamID, ipAddress, hwids, ban.Reason, uint.MaxValue);
28+
}
29+
}
30+
}
31+
}
32+
}

PlayerStats/Components/PlayerStatsComponent.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Rocket.Core;
66
using Rocket.Unturned.Player;
77
using SDG.Unturned;
8+
using Steamworks;
89
using System;
910
using System.Collections.Generic;
1011
using System.Linq;
@@ -20,6 +21,7 @@ public partial class PlayerStatsComponent : MonoBehaviour
2021

2122
public Player Player { get; private set; }
2223
public string Name => Player.channel.owner.playerID.characterName;
24+
public CSteamID SteamID => Player.channel.owner.playerID.steamID;
2325
public ulong SteamId => Player.channel.owner.playerID.steamID.m_SteamID;
2426
public PlayerStatsData PlayerData { get; private set; }
2527
public PlayerStatsData SessionPlayerData { get; private set; }
@@ -202,6 +204,8 @@ internal void OnPlayerDeath(Player killer, ELimb limb, EDeathCause cause)
202204
}
203205
killerComponent.UpdateUIEffect();
204206
killerComponent.CheckGiveReward();
207+
208+
killerComponent.CheckAutomaticBan();
205209
}
206210
UpdateUIEffect();
207211
} else
@@ -213,6 +217,8 @@ internal void OnPlayerDeath(Player killer, ELimb limb, EDeathCause cause)
213217
UpdateUIEffect();
214218
}
215219
}
220+
221+
CheckAutomaticBan();
216222
}
217223

218224
internal void CheckGiveReward()

PlayerStats/Models/AutomaticBan.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System.Xml.Serialization;
2+
3+
namespace RestoreMonarchy.PlayerStats.Models
4+
{
5+
public class AutomaticBan
6+
{
7+
[XmlAttribute]
8+
public string Reason { get; set; }
9+
[XmlArrayItem("Condition")]
10+
public AutomaticBanCondition[] Conditions { get; set; }
11+
12+
public bool CheckConditions(PlayerStatsData data)
13+
{
14+
if (Conditions == null || Conditions.Length == 0)
15+
{
16+
return false;
17+
}
18+
19+
foreach (AutomaticBanCondition condition in Conditions)
20+
{
21+
long statValue = data.GetStatValue(condition.Stat);
22+
switch (condition.Comparer.ToLower())
23+
{
24+
case "greater":
25+
if (statValue <= condition.Value) return false;
26+
break;
27+
case "less":
28+
if (statValue >= condition.Value) return false;
29+
break;
30+
case "equal":
31+
if (statValue != condition.Value) return false;
32+
break;
33+
default:
34+
return false;
35+
}
36+
}
37+
38+
return true;
39+
}
40+
}
41+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
using System.Xml.Serialization;
2+
3+
namespace RestoreMonarchy.PlayerStats.Models
4+
{
5+
public class AutomaticBanCondition
6+
{
7+
[XmlAttribute]
8+
public string Comparer { get; set; }
9+
[XmlAttribute]
10+
public string Stat { get; set; }
11+
[XmlAttribute]
12+
public long Value { get; set; }
13+
}
14+
}

PlayerStats/Models/PlayerStatsData.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Newtonsoft.Json;
2+
using Rocket.Core.Logging;
23
using System;
34

45
namespace RestoreMonarchy.PlayerStats.Models
@@ -38,5 +39,44 @@ public int Deaths
3839
}
3940
}
4041
}
42+
43+
public long GetStatValue(string name)
44+
{
45+
switch (name?.ToLower())
46+
{
47+
case "kills":
48+
return Kills;
49+
case "headshots":
50+
return Headshots;
51+
case "pvpdeaths":
52+
return PVPDeaths;
53+
case "pvedeaths":
54+
return PVEDeaths;
55+
case "zombies":
56+
return Zombies;
57+
case "megazombies":
58+
return MegaZombies;
59+
case "animals":
60+
return Animals;
61+
case "resources":
62+
return Resources;
63+
case "harvests":
64+
return Harvests;
65+
case "fish":
66+
return Fish;
67+
case "structures":
68+
return Structures;
69+
case "barricades":
70+
return Barricades;
71+
case "playtime":
72+
return (long)Playtime; // Assuming Playtime is in seconds
73+
case "accuracy":
74+
return Kills > 0 ? (long)((Headshots / (double)Kills) * 100) : 0; // Calculate accuracy as percentage of headshots to kills
75+
case "deaths":
76+
return Deaths; // Returns combined deaths if configured
77+
default:
78+
return 0;
79+
}
80+
}
4181
}
4282
}

PlayerStats/PlayerStats.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<TargetFramework>net48</TargetFramework>
55
<LangVersion>latest</LangVersion>
66
<RootNamespace>RestoreMonarchy.PlayerStats</RootNamespace>
7-
<Version>1.1.3</Version>
7+
<Version>1.2.0</Version>
88
</PropertyGroup>
99

1010
<ItemGroup>

PlayerStats/PlayerStatsConfiguration.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,35 @@ public class PlayerStatsConfiguration : IRocketPluginConfiguration
3939
public int MinimumRankingTreshold { get; set; }
4040
public bool EnableRewards { get; set; }
4141
public Reward[] Rewards { get; set; }
42+
public bool EnableAutomaticBans { get; set; } = false;
43+
public AutomaticBan[] AutomaticBans { get; set; } =
44+
[
45+
new AutomaticBan
46+
{
47+
Reason = "Cheating (AB)",
48+
Conditions =
49+
[
50+
new AutomaticBanCondition
51+
{
52+
Comparer = "greater",
53+
Stat = nameof(PlayerStatsData.Kills),
54+
Value = 30
55+
},
56+
new AutomaticBanCondition
57+
{
58+
Comparer = "greater",
59+
Stat = "Accuracy",
60+
Value = 80
61+
},
62+
new AutomaticBanCondition
63+
{
64+
Comparer = "less",
65+
Stat = nameof(PlayerStatsData.Playtime),
66+
Value = 3600
67+
}
68+
]
69+
},
70+
];
4271

4372
// Only hide legacy properties when using new StatsMode
4473
public bool ShouldSerializeEnablePVPStats() => StatsMode == null;

README.md

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@ Player Stats is a plugin that tracks various player statistics and provides rank
1616
| 🔄 Migration | Automatic migration from Arechi PlayerStats plugin |
1717
| 🖥️ User Interface | Optional UI for viewing PVP/PVE stats |
1818

19+
## Workshop (Optional)
20+
The UI is optional and provides a visual display for PVP stats.
21+
22+
- **Workshop Item**: [Player Stats UI](https://steamcommunity.com/sharedfiles/filedetails/?id=3352126593)
23+
- **ID**: `3352126593`
24+
25+
> 💡 **PRO TIP**
26+
> Remember to set `<EnableUIEffect>true</EnableUIEffect>` in the configuration file to activate the UI.
27+
1928
## Tracked Statistics
2029

2130
### PVP Stats
@@ -25,12 +34,12 @@ Player Stats is a plugin that tracks various player statistics and provides rank
2534
- HS% (Headshot Percentage)
2635

2736
### PVE Stats
28-
- Zombies
29-
- Mega Zombies
30-
- Animals
31-
- Resources
32-
- Harvests
33-
- Fish
37+
- Zombies (zombies killed)
38+
- Mega Zombies (mega zombies killed)
39+
- Animals (animals killed)
40+
- Resources (resources gathered)
41+
- Harvests (plant harvests)
42+
- Fish (fish caught)
3443

3544
---
3645

@@ -44,6 +53,45 @@ Player Stats is a plugin that tracks various player statistics and provides rank
4453
| `PVP` | The `/stats` command displays only PVP stats, and ranking, rewards and UI are based on PVP stats |
4554
| `PVE` | The `/stats` command displays only PVE stats, and ranking, rewards and UI are based on PVE stats |
4655

56+
### Automatic Bans
57+
58+
The Automatic Bans feature allows server owners to automatically ban players who meet suspicious statistical patterns, helping detect potential cheaters or rule violators. Bans are triggered when players die or eliminate other players, checking their overall statistics against configured thresholds.
59+
60+
**How it works:**
61+
- Conditions are checked whenever a player kills someone or dies
62+
- Multiple conditions can be combined - ALL conditions must be met to trigger a ban
63+
- Supports custom ban reasons that will be displayed to the banned player
64+
- Uses the player's total statistics (not session stats) for evaluation
65+
66+
**Available Statistics:**
67+
- `Kills` - Total player kills
68+
- `Deaths` - Total deaths (PVP and/or PVE based on ShowCombinedDeaths setting)
69+
- `PVPDeaths` - Deaths caused by other players only
70+
- `Headshots` - Total headshot kills
71+
- `Accuracy` - Headshot percentage (0-100)
72+
- `Playtime` - Total time played on the server (in seconds)
73+
74+
**Supported Comparers:**
75+
- `greater` - Greater than the specified value
76+
- `less` - Less than the specified value
77+
- `equal` - Equal to the specified value
78+
79+
**Example Configuration:**
80+
The default configuration automatically bans players who achieve more than 30 kills with over 80% headshot accuracy within their first hour of playtime - a pattern typically indicating cheating:
81+
82+
```xml
83+
<AutomaticBan Reason="Cheating (AB)">
84+
<Conditions>
85+
<Condition Comparer="greater" Stat="Kills" Value="30" />
86+
<Condition Comparer="greater" Stat="Accuracy" Value="80" />
87+
<Condition Comparer="less" Stat="Playtime" Value="3600" />
88+
</Conditions>
89+
</AutomaticBan>
90+
```
91+
92+
> ⚠️ **Warning**
93+
> Use this feature carefully and test your conditions thoroughly. Consider your server's gameplay style and player skill levels when setting thresholds to avoid false positives.
94+
4795
### Other Options
4896

4997
The plugin offers several additional options to customize functionality:
@@ -61,15 +109,6 @@ The plugin offers several additional options to customize functionality:
61109

62110
---
63111

64-
## Workshop (Optional)
65-
The UI is optional and provides a visual display for PVP stats.
66-
67-
- **Workshop Item**: [Player Stats UI](https://steamcommunity.com/sharedfiles/filedetails/?id=3352126593)
68-
- **ID**: `3352126593`
69-
70-
> 💡 **PRO TIP**
71-
> Remember to set `<EnableUIEffect>true</EnableUIEffect>` in the configuration file to activate the UI.
72-
73112
---
74113

75114
## Commands
@@ -123,6 +162,16 @@ The UI is optional and provides a visual display for PVP stats.
123162
<Reward Name="VIP Rank" Treshold="50" PermissionGroup="vip" />
124163
<Reward Name="MVP Rank" Treshold="125" PermissionGroup="mvp" />
125164
</Rewards>
165+
<EnableAutomaticBans>false</EnableAutomaticBans>
166+
<AutomaticBans>
167+
<AutomaticBan Reason="Cheating (AB)">
168+
<Conditions>
169+
<Condition Comparer="greater" Stat="Kills" Value="30" />
170+
<Condition Comparer="greater" Stat="Accuracy" Value="80" />
171+
<Condition Comparer="less" Stat="Playtime" Value="3600" />
172+
</Conditions>
173+
</AutomaticBan>
174+
</AutomaticBans>
126175
</PlayerStatsConfiguration>
127176
```
128177

@@ -145,7 +194,7 @@ UI made by **💪 Soer (Unbeaten)**. He also sponsored the creation of this plug
145194
Edit the `<Rewards>` section in the configuration file with your desired thresholds and permission groups.
146195

147196
4. **How can I create a custom UI?**
148-
You can download the `statsui.unitypackage` from the [All versions](versions) page and import it into your Unity project. Then, customize the UI as needed and reupload it to the workshop.
197+
You can download the `statsui.unitypackage` from the **All versions** page and import it into your Unity project. Then, customize the UI as needed and reupload it to the workshop. Remember in Unity do not rename any of the objects in the hierarchy, as the plugin uses the object names to find them. When reuploading, make sure to use a unique GUID and ID.
149198

150199
---
151200

0 commit comments

Comments
 (0)