-
Notifications
You must be signed in to change notification settings - Fork 1
/
RaidAlarm.cs
218 lines (176 loc) · 8.52 KB
/
RaidAlarm.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
using System;
using System.Collections.Generic;
using CompanionServer;
using Oxide.Core;
using ProtoBuf;
using UnityEngine;
namespace Oxide.Plugins
{
[Info("Raid Alarm", "haggbart", "0.4.0")]
[Description("Receive raid notifications through the official Rust companion mobile app")]
internal class RaidAlarm : RustPlugin
{
#region init, data and cleanup
private static HashSet<ulong> disabled = new HashSet<ulong>();
private const string PERMISSION = "raidalarm.use";
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, disabled);
private void ReadData() => disabled = Interface.Oxide.DataFileSystem.ReadObject<HashSet<ulong>>(Name);
private void Init()
{
config = Config.ReadObject<PluginConfig>();
SaveConfig();
permission.RegisterPermission(PERMISSION, this);
ReadData();
}
private void OnServerSave() => SaveData();
private void Unload() => SaveData();
#endregion
#region config
private PluginConfig config;
private class PluginConfig
{
public bool usePermissions;
}
protected override void LoadDefaultConfig() => Config.WriteObject(GetDefaultConfig(), true);
private new void SaveConfig() => Config.WriteObject(config, true);
private static PluginConfig GetDefaultConfig()
{
return new PluginConfig
{
usePermissions = false
};
}
#endregion config
#region localization
private static class Loc
{
public const string TITLE = "AlarmTitle";
public const string BODY = "AlarmBody";
public const string HELP = "AlarmHelp";
public const string HELP_COMMANDS = "AlarmHelpCommands";
public const string STATUS_ENABLED = "AlarmStatusEnabled";
public const string STATUS_DISABLED = "AlarmStatusDisabled";
public const string TEST_SENT = "AlarmTestSent";
public const string TEST_DESTROYED = "AlarmTestDestroyedItem";
public const string NO_PERMISSION = "NoPermission";
}
private string GetStatusText(BasePlayer player)
{
return lang.GetMessage(disabled.Contains(player.userID) ? Loc.STATUS_DISABLED : Loc.STATUS_ENABLED, this, player.UserIDString);
}
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
[Loc.TITLE] = "You're getting raided!",
[Loc.BODY] = "{0} destroyed at {1}",
[Loc.HELP] = "To receive Raid Alarm notifications, " +
"you need the official Rust+ companion app on your mobile device and pair it this server. " +
"To do this, press Esc and click \"Rust+\" in main menu.\n\n" +
"Use /raidalarm test to test your alarm. To do disable, use /raidalarm disable",
[Loc.HELP_COMMANDS] = "Available commands: \n/raidalarm status|enable|disable|test",
[Loc.STATUS_ENABLED] = "Raid Alarm is enabled.",
[Loc.STATUS_DISABLED] = "Raid Alarm is disabled.",
[Loc.TEST_SENT] = "Test notification sent. If you don't receive it, make sure you're paired with the server.",
[Loc.TEST_DESTROYED] = "chair",
[Loc.NO_PERMISSION] = "You don't have the permission to use this command."
}, this);
}
#endregion
private readonly Dictionary<string, DateTime> raidblocked = new Dictionary<string, DateTime>();
private DateTime lastAttack = DateTime.Now;
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
{
if (info == null) return;
if (!IsRaidEntity(entity)) return;
if (info.InitiatorPlayer == null) return;
// prevent spam
TimeSpan timesince = DateTime.Now - lastAttack;
if (timesince.TotalSeconds < 1) return;
lastAttack = DateTime.Now;
var buildingPrivilege = entity.GetBuildingPrivilege();
if (buildingPrivilege == null || buildingPrivilege.authorizedPlayers.IsEmpty()) return;
var victims = new List<ulong>(buildingPrivilege.authorizedPlayers.Count);
foreach (PlayerNameID victim in buildingPrivilege.authorizedPlayers)
{
if (victim == null) continue;
if (config.usePermissions && !permission.UserHasPermission(victim.userid.ToString(), PERMISSION)) continue;
if (victim.userid == info.InitiatorPlayer.userID) return;
if (disabled.Contains(victim.userid)) continue;
victims.Add(victim.userid);
}
// raidblock
String grid = GetGrid(entity.transform.position);
raidblocked[grid] = lastAttack;
NotificationList.SendNotificationTo(victims, NotificationChannel.SmartAlarm, lang.GetMessage(Loc.TITLE, this),
string.Format(lang.GetMessage(Loc.BODY, this), entity.ShortPrefabName, grid), Util.GetServerPairingData());
}
private static bool IsRaidEntity(BaseCombatEntity entity)
{
if (entity is Door) return true;
if (!(entity is BuildingBlock)) return false;
return ((BuildingBlock) entity).grade != BuildingGrade.Enum.Twigs;
}
private static string GetGrid(Vector3 pos)
{
const float scale = 150f;
float x = pos.x + World.Size / 2f;
float z = pos.z + World.Size / 2f;
int lat = (int) (x / scale);
char latChar = (char) ('A' + lat);
int lon = (int) (World.Size / scale - z / scale);
return latChar + lon.ToString();
}
[ChatCommand("raidalarm")]
private void ChatRaidAlarm(BasePlayer player, string command, string[] args)
{
if (config.usePermissions && !permission.UserHasPermission(player.UserIDString, PERMISSION))
{
SendReply(player, lang.GetMessage(Loc.NO_PERMISSION, this, player.UserIDString));
return;
}
if (args.Length == 0)
{
SendReply(player, lang.GetMessage(Loc.HELP, this, player.UserIDString));
return;
}
switch (args[0].ToLower())
{
case "status":
SendReply(player, GetStatusText(player));
break;
case "enable":
disabled.Remove(player.userID);
SendReply(player, lang.GetMessage(Loc.STATUS_ENABLED, this, player.UserIDString));
break;
case "disable":
disabled.Add(player.userID);
SendReply(player, lang.GetMessage(Loc.STATUS_DISABLED, this, player.UserIDString));
break;
case "test":
if (disabled.Contains(player.userID))
{
SendReply(player, lang.GetMessage(Loc.STATUS_DISABLED, this, player.UserIDString));
return;
}
NotificationList.SendNotificationTo(player.userID, NotificationChannel.SmartAlarm,
lang.GetMessage(Loc.TITLE, this, player.UserIDString),
string.Format(lang.GetMessage(Loc.BODY, this, player.UserIDString),
string.Format(lang.GetMessage(Loc.TEST_DESTROYED, this, player.UserIDString)),
GetGrid(player.transform.position)), Util.GetServerPairingData());
SendReply(player, lang.GetMessage(Loc.TEST_SENT, this, player.UserIDString));
break;
default:
SendReply(player, lang.GetMessage(Loc.HELP_COMMANDS, this, player.UserIDString));
break;
}
}
#region Dev API
private bool IsRaidBlocked(BasePlayer player)
{
DateTime now;
return raidblocked.TryGetValue(GetGrid(player.transform.position), out now) && (DateTime.Now - now).TotalHours < 1;
}
#endregion Dev API
}
}