C#:
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using UnityEngine;
using Newtonsoft.Json;
using Oxide.Core.Libraries.Covalence;
namespace Oxide.Plugins
{
[Info("RaidAlerts", "King", "1.0.0")]
class RaidAlerts : RustPlugin
{
#region [Vars]
static readonly DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0);
static double CurrentTime() { return DateTime.UtcNow.Subtract(epoch).TotalSeconds; }
public Dictionary<ulong, DateTime> cooldownNotify = new Dictionary<ulong, DateTime>();
public DateTime DateTime;
string Layer = "NotifyLayer";
string LayerMenu = "NotifyLayer_Menu";
#endregion
#region [Config]
private PluginConfig config;
protected override void LoadDefaultConfig()
{
config = PluginConfig.DefaultConfig();
}
protected override void LoadConfig()
{
base.LoadConfig();
config = Config.ReadObject<PluginConfig>();
if (config.PluginVersion < Version)
UpdateConfigValues();
Config.WriteObject(config, true);
}
private void UpdateConfigValues()
{
PluginConfig baseConfig = PluginConfig.DefaultConfig();
if (config.PluginVersion < Version)
{
config.PluginVersion = Version;
if (Version == new VersionNumber(1, 0, 0))
{
//
}
PrintWarning("Config checked completed!");
}
config.PluginVersion = Version;
}
protected override void SaveConfig()
{
Config.WriteObject(config);
}
public class PluginSettings
{
[JsonProperty("Кд на отправку оповещений")]
public float cooldown;
[JsonProperty("Время, через которое пропадает UI [секунды]")]
public float destroy;
[JsonProperty("Изображение какого shortName будет на оповещение")]
public string Image;
}
private class PluginConfig
{
[JsonProperty("Основная настройка плагина")]
public PluginSettings _Settings = new PluginSettings();
[JsonProperty("Config version")]
public VersionNumber PluginVersion = new VersionNumber();
public static PluginConfig DefaultConfig()
{
return new PluginConfig()
{
_Settings = new PluginSettings()
{
cooldown = 60f,
destroy = 15f,
Image = "grenade.f1",
},
PluginVersion = new VersionNumber()
};
}
}
#endregion
#region [Data]
private void LoadData()
{
try
{
data = Interface.Oxide.DataFileSystem.ReadObject<PluginData>("RaidAlerts");
}
catch (Exception e)
{
PrintError(e.ToString());
}
if (data == null) data = new PluginData();
}
private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject("RaidAlerts", data);
private class PluginData
{
public Dictionary<ulong, PlayerData> PlayerData = new Dictionary<ulong, PlayerData>();
}
private static PluginData data;
private class PlayerData
{
public bool useNotifyGame;
public static PlayerData GetOrAdd(BasePlayer player)
{
return GetOrAdd(player.userID);
}
public static PlayerData GetOrAdd(ulong userId)
{
if (!data.PlayerData.ContainsKey(userId))
data.PlayerData.Add(userId, new PlayerData
{
useNotifyGame = true,
});
return data.PlayerData[userId];
}
}
#endregion
#region [Oxide]
private void OnServerInitialized()
{
cmd.AddChatCommand("raid", this, "SettingsMenu");
LoadData();
}
private void Unload()
{
foreach (var player in BasePlayer.activePlayerList)
CuiHelper.DestroyUi(player, Layer);
SaveData();
data = null;
}
#endregion
#region [Rust-Api]
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info)
{
if (info == null || entity == null) return;
BasePlayer player = info.InitiatorPlayer;
if (player == null) return;
if (entity is BuildingBlock)
{
int tier = (int)(entity as BuildingBlock).grade;
if (tier <= 0) return;
NotifyManager(entity, player, tier);
}
else if (entity is DecayEntity || entity is SamSite || entity is AutoTurret)
{
NotifyManager(entity, player);
}
}
#endregion
#region [Notify]
private void NotifyManager(BaseCombatEntity entity, BasePlayer player, int grade = 0)
{
var data = PlayerData.GetOrAdd(player);
if (!data.useNotifyGame) return;
Vector3 entityPosition = entity.transform.position;
string entityName = entity.ShortPrefabName;
if (grade == 1) entityName += " Wood";
else if (grade == 2) entityName += " Stone";
else if (grade == 3) entityName += " Metal";
else if (grade == 4) entityName += " TopTier";
BuildingPrivlidge buildingPrivlidge = entity is BuildingPrivlidge ? entity as BuildingPrivlidge : entity.GetBuildingPrivilege(entity.WorldSpaceBounds());
if (buildingPrivlidge == null) return;
if (!buildingPrivlidge.AnyAuthed()) return;
var playerList = buildingPrivlidge.authorizedPlayers.ToList();
string displayName = player.displayName;
string quad = getGrid(entityPosition);
foreach (var playerAuth in playerList)
{
SendNotify(playerAuth.userid, displayName, quad, entityName);
}
}
private void SendNotify(ulong playerID, string displayName, string quad, string entityName)
{
string IDstring = playerID.ToString();
if (!cooldownNotify.ContainsKey(playerID))
cooldownNotify.Add(playerID, DateTime);
if (cooldownNotify[playerID] < DateTime.Now)
{
BasePlayer player = BasePlayer.FindByID(playerID);
if (player != null && player.IsConnected)
{
timer.Once(config._Settings.destroy, () => CuiHelper.DestroyUi(player, Layer));
NotifyUi(player, displayName, quad, entityName);
cooldownNotify[playerID] = DateTime.Now.AddSeconds(config._Settings.cooldown);
}
}
}
#endregion
#region [Notify-Ui]
private void NotifyUi(BasePlayer player, string name, string quad, string entityName)
{
CuiHelper.DestroyUi(player, Layer);
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel
{
Image = { Color = "0.5 0.5 0.5 0.25", Material = "assets/icons/greyout.mat" },
RectTransform =
{AnchorMin = "1 0.5", AnchorMax = "1 0.5", OffsetMin = "-245.182 -155.661", OffsetMax = "-2.618 -102.735"},
CursorEnabled = false,
}, "Overlay", Layer);
container.Add(new CuiElement
{
Parent = Layer,
Name = Layer + ".itemImage",
Components =
{
new CuiImageComponent {Color = "0.49 0.44 0.38 0.75", Material = "assets/icons/greyout.mat"},
new CuiRectTransformComponent { AnchorMin = "0.01586128 0.08839238", AnchorMax = "0.1925 0.9208925" }
}
});
container.Add(new CuiElement
{
Parent = Layer + ".itemImage",
Components =
{
new CuiImageComponent { ItemId = FindItemID(config._Settings.Image), SkinId = 0 },
new CuiRectTransformComponent { AnchorMin = "0 0", AnchorMax = "1 1" }
}
});
container.Add(new CuiElement
{
Parent = Layer,
Components =
{
new CuiTextComponent() { Color = "1 1 1 0.65", Text = $"Оповещение о рейде!", FontSize = 14, Align = TextAnchor.MiddleLeft, Font = "robotocondensed-bold.ttf" },
new CuiRectTransformComponent {AnchorMin = "0.215 0.585", AnchorMax = "1 1"},
new CuiOutlineComponent{Color = "0 0 0 1", Distance = "0.15 0.15"},
}
});
if (TranslateRu.ContainsKey(entityName))
{
container.Add(new CuiElement
{
Parent = Layer,
Components =
{
new CuiTextComponent() { Color = "1 1 1 0.65", Text = $"{name} {TranslateRu[entityName]}, квадрат {quad}.", FontSize = 12, Align = TextAnchor.MiddleLeft, Font = "robotocondensed-regular.ttf" },
new CuiRectTransformComponent { AnchorMin = "0.215 0", AnchorMax = "1 0.7" },
new CuiOutlineComponent{ Color = "0 0 0 1", Distance = "0.15 0.15" },
}
});
}
else if (!TranslateRu.ContainsKey(entityName))
{
container.Add(new CuiElement
{
Parent = Layer,
Components =
{
new CuiTextComponent() { Color = "1 1 1 0.65", Text = $"{name} начал рейд, квадрат {quad}.", FontSize = 12, Align = TextAnchor.MiddleLeft, Font = "robotocondensed-regular.ttf" },
new CuiRectTransformComponent { AnchorMin = "0.215 0", AnchorMax = "1 0.7" },
new CuiOutlineComponent{ Color = "0 0 0 1", Distance = "0.15 0.15" },
}
});
}
container.Add(new CuiButton
{
Button = { Color = "0.9 0 0 0.65", Material = "assets/icons/greyout.mat", Close = Layer },
RectTransform = { AnchorMin = "0.94 0.725", AnchorMax = "0.995 0.98" }
}, Layer, "CloseX");
container.Add(new CuiElement
{
Parent = "CloseX",
Components =
{
new CuiTextComponent() { Color = "1 1 1 0.65", Text = $"✘", FontSize = 12, Font = "robotocondensed-regular.ttf", Align = TextAnchor.MiddleCenter },
new CuiRectTransformComponent {AnchorMin = "0 0", AnchorMax = "1 1"},
new CuiOutlineComponent{ Color = "0 0 0 1", Distance = "0.35 0.35" },
}
});
CuiHelper.AddUi(player, container);
}
#endregion
#region [Ui-Settings]
private void SettingsMenu(BasePlayer player)
{
CuiHelper.DestroyUi(player, LayerMenu);
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel
{
CursorEnabled = true,
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1", OffsetMax = "0 0" },
Image = { Material = "assets/content/ui/uibackgroundblur.mat", Color = "0 0 0 0.77" },
}, "Overlay", LayerMenu);
container.Add(new CuiPanel
{
RectTransform = { AnchorMin = "0 0", AnchorMax = "1 1" },
Image = { Color = "0.36 0.33 0.28 0.3", Material = "assets/icons/greyout.mat" }
}, LayerMenu);
CuiHelper.AddUi(player, container);
SettingsUi(player);
}
private void SettingsUi(BasePlayer player)
{
CuiHelper.DestroyUi(player, LayerMenu + ".Main");
CuiElementContainer container = new CuiElementContainer();
var data = PlayerData.GetOrAdd(player);
container.Add(new CuiPanel
{
RectTransform = { AnchorMin = "0.5 0.5", AnchorMax = "0.5 0.5", OffsetMin = "-300 -240", OffsetMax = "300 240" },
Image = { Color = "0 0 0 0" }
}, LayerMenu, LayerMenu + ".Main");
container.Add(new CuiButton
{
Button = { Color = "0 0 0 0", Close = LayerMenu },
Text = { Text = "✘", Color = "1 1 1 0.65", FontSize = 48, Font = "robotocondensed-regular.ttf", Align = TextAnchor.MiddleCenter },
RectTransform = { AnchorMin = $"0.825 0.825", AnchorMax = $"1 1" },
}, LayerMenu + ".Main");
foreach (var check in FRaid.Select((i, t) => new { A = i, B = t }))
{
container.Add(new CuiPanel
{
RectTransform = { AnchorMin = $"{0.15 + check.B * 0.15 - Math.Floor((float) check.B / 1) * 1 * 0.15} {0.65 - Math.Floor((float) check.B/ 1) * 0.165}",
AnchorMax = $"{0.725 + check.B * 0.15 - Math.Floor((float) check.B / 1) * 1 * 0.15} {0.8 - Math.Floor((float) check.B / 1) * 0.165}", },
Image = { Color = "0 0 0 0.25", Material = "assets/icons/greyout.mat" }
}, LayerMenu + ".Main", LayerMenu + ".Main" + $".{check.B}");
container.Add(new CuiPanel
{
RectTransform = { AnchorMin = "0.01586128 0.08839238", AnchorMax = "0.1925 0.9208925" },
Image = { Color = "0.49 0.44 0.38 0.25", Material = "assets/icons/greyout.mat" }
}, LayerMenu + ".Main" + $".{check.B}", LayerMenu + ".Main" + $".{check.B}" + ".Image");
container.Add(new CuiElement
{
Parent = LayerMenu + ".Main" + $".{check.B}" + ".Image",
Components =
{
new CuiImageComponent { ItemId = FindItemID(check.A.Value), SkinId = 0, Color = "1 1 1 0.95" },
new CuiRectTransformComponent {AnchorMin = "0.025 0.025", AnchorMax = "0.975 0.975"}
}
});
container.Add(new CuiElement
{
Parent = LayerMenu + ".Main" + $".{check.B}",
Components =
{
new CuiTextComponent { Text = $"{check.A.Key}", Color = "1 1 1 0.65", FontSize = 24, Font = "robotocondensed-regular.ttf", Align = TextAnchor.MiddleLeft},
new CuiRectTransformComponent { AnchorMin = "0.215 0", AnchorMax = "1 1" },
}
});
container.Add(new CuiButton
{
RectTransform = { AnchorMin = "1.015 0", AnchorMax = "1.25 0.997" },
Button = { Color = "0 0 0 0.25", Material = "assets/icons/greyout.mat", Command = $"UI_RaidAlerts setUse" },
Text = { Text = data.useNotifyGame == true ? "Отключить" : "Включить", Color = "1 1 1 0.65", FontSize = 14, Font = "robotocondensed-regular.ttf", Align = TextAnchor.MiddleCenter }
}, LayerMenu + ".Main" + $".{check.B}");
}
CuiHelper.AddUi(player, container);
}
#endregion
#region [ConsoleCommand]
[ConsoleCommand("UI_RaidAlerts")]
private void CmdConsoleMarkers(ConsoleSystem.Arg arg)
{
var player = arg?.Player();
if (player == null || !arg.HasArgs()) return;
switch (arg.Args[0])
{
case "setUse":
{
var data = PlayerData.GetOrAdd(player);
if (data == null) return;
if (data.useNotifyGame == true)
{
data.useNotifyGame = false;
}
else if (data.useNotifyGame == false)
{
data.useNotifyGame = true;
}
SettingsUi(player);
break;
}
}
}
#endregion
#region [Support]
Dictionary<string, string> TranslateRu = new Dictionary<string, string>()
{
["wall TopTier"] = "сломал вашу мвк стенку",
["wall Metal"] = "сломал вашу металическую стенку",
["wall Stone"] = "сломал вашу каменную стенку",
["wall Wood"] = "сломал вашу деревянную стенку",
["wall.doorway TopTier"] = "сломал ваш мвк проем",
["wall.doorway Metal"] = "сломал ваш металический проем",
["wall.doorway Stone"] = "сломал ваш каменный проем",
["wall.doorway Wood"] = "сломал ваш деревянный проем",
["wall.window TopTier"] = "сломал ваше мвк окно",
["wall.window Metal"] = "сломал ваше металическое окно",
["wall.window Stone"] = "сломал ваше каменное окно",
["wall.window Wood"] = "сломал ваше деревянное окно",
["wall.frame TopTier"] = "сломал ваш мвк двойной проем",
["wall.frame Metal"] = "сломал ваш металический двойной проем",
["wall.frame Stone"] = "сломал ваш каменный двойной проем",
["wall.frame Wood"] = "сломал ваш деревянный двойной проем",
["foundation TopTier"] = "сломал ваш мвк фундамент",
["foundation Metal"] = "сломал ваш металический фундамент",
["foundation Stone"] = "сломал ваш каменный фундамент",
["foundation Wood"] = "сломал ваш деревянный фундамент",
["door.double.hinged.wood"] = "сломал вашу деревянную дверь",
["door.double.hinged.metal"] = "сломал вашу металическую дверь",
["door.double.hinged.toptier"] = "сломал вашу мвк дверь",
["autoturret_deployed"] = "сломал вашу автоматическую турель",
["sam_site_turret_deployed"] = "сломал вашу ПВО",
["wall.external.high.stone"] = "сломал вашу большую каменную стенку",
["wall.external.high.wood"] = "сломал вашу большую деревянную стенку",
};
Dictionary<string, string> FRaid = new Dictionary<string, string>()
{
["Оповещение о рейде!"] = "grenade.f1",
};
#endregion
#region [Func]
private Dictionary<string, int> _itemIds = new Dictionary<string, int>();
private int FindItemID(string shortName)
{
int val;
if (_itemIds.TryGetValue(shortName, out val))
return val;
var definition = ItemManager.FindItemDefinition(shortName);
if (definition == null) return 0;
val = definition.itemid;
_itemIds[shortName] = val;
return val;
}
private static string getGrid(Vector3 pos)
{
var letter = 'A';
var x = Mathf.Floor((pos.x + ConVar.Server.worldsize / 2f) / 146.3f) % 26;
var z = Mathf.Floor(ConVar.Server.worldsize / 146.3f) -
Mathf.Floor((pos.z + ConVar.Server.worldsize / 2f) / 146.3f);
letter = (char)(letter + x);
return $"{letter}{z}";
}
#endregion
}
}