C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;
using Rust;
namespace Oxide.Plugins {
[Info("Clans", "S1m0n", "2.7.7")]
public class Clans : RustPlugin {
bool Changed;
bool Initialized;
internal static Clans cc = null;
bool newSaveDetected = false;
List<ulong> manuallyEnabledBy = new List<ulong>();
HashSet<ulong> bypass = new HashSet<ulong>();
Dictionary<string, DateTime> notificationTimes = new Dictionary<string, DateTime>();
static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
static readonly double MaxUnixSeconds = (DateTime.MaxValue - UnixEpoch).TotalSeconds;
FieldInfo displayName = typeof(BasePlayer).GetField("_displayName", (BindingFlags.Instance | BindingFlags.NonPublic));
FieldInfo name = typeof(BasePlayer).GetField("_name", (BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public));
Library lib;
MethodInfo isInstalled;
MethodInfo addFriend;
public Dictionary<string, Clan> clans = new Dictionary<string, Clan>();
List<string> purgedClans = new List<string>();
Dictionary<string, string> originalNames = new Dictionary<string, string>();
Dictionary<string, List<string>> pendingPlayerInvites = new Dictionary<string, List<string>>();
Regex tagReExt;
Dictionary<string, Clan> clanCache = new Dictionary<string, Clan>();
List<object> filterDefaults() {
var dp = new List<object>();
dp.Add("admin");
dp.Add("mod");
dp.Add("owner");
return dp;
}
public int limitMembers;
int limitModerators;
public int limitAlliances;
int tagLengthMin;
int tagLengthMax;
int inviteValidDays;
int friendlyFireNotifyTimeout;
string allowedSpecialChars;
public bool enableFFOPtion;
bool enableAllyFFOPtion;
bool enableWordFilter;
bool enableClanTagging;
public bool enableClanAllies;
bool forceAllyFFNoDeactivate;
int authLevelRename;
int authLevelDelete;
int authLevelInvite;
int authLevelKick;
int authLevelPromoteDemote;
int authLevelClanInfo;
bool purgeOldClans;
int notUpdatedSinceDays;
bool listPurgedClans;
bool wipeClansOnNewSave;
string consoleName;
string broadcastPrefix;
string broadcastPrefixAlly;
string broadcastPrefixColor;
string broadcastPrefixFormat;
string broadcastMessageColor;
string colorCmdUsage;
string colorTextMsg;
string colorClanNamesOverview;
string colorClanFFOff;
string colorClanFFOn;
string pluginPrefix;
string pluginPrefixColor;
string pluginPrefixREBORNColor;
string pluginPrefixFormat;
string clanServerColor;
string clanOwnerColor;
string clanCouncilColor;
string clanModeratorColor;
string clanMemberColor;
bool setHomeOwner;
bool setHomeModerator;
bool setHomeMember;
string chatCommandClan;
string chatCommandFF;
string chatCommandAllyChat;
string chatCommandClanChat;
string chatCommandClanInfo;
bool usePermGroups;
string permGroupPrefix;
bool usePermToCreateClan;
string permissionToCreateClan;
bool addClanMembersAsIOFriends;
bool enableRustIOSupport;
string clanTagColorBetterChat;
int clanTagSizeBetterChat;
string clanTagOpening;
string clanTagClosing;
List<object> wordFilter = new List<object>();
object GetConfig(string menu, string datavalue, object defaultValue) {
var data = Config[menu] as Dictionary<string, object>;
if (data == null) {
data = new Dictionary<string, object>();
Config[menu] = data;
Changed = true;
}
object value;
if (!data.TryGetValue(datavalue, out value)) {
value = defaultValue;
data[datavalue] = value;
Changed = true;
}
return value;
}
void LoadVariables() {
wordFilter = (List<object>)GetConfig("WordFilter", "Words", filterDefaults());
limitMembers = Convert.ToInt32(GetConfig("Limits", "limitMembers", 8));
limitModerators = Convert.ToInt32(GetConfig("Limits", "limitModerators", 2));
limitAlliances = Convert.ToInt32(GetConfig("Limits", "limitAlliances", 2));
tagLengthMin = Convert.ToInt32(GetConfig("Limits", "tagLengthMin", 2));
tagLengthMax = Convert.ToInt32(GetConfig("Limits", "tagLengthMax", 6));
inviteValidDays = Convert.ToInt32(GetConfig("Limits", "inviteValidDays", 1));
friendlyFireNotifyTimeout = Convert.ToInt32(GetConfig("Limits", "friendlyFireNotifyTimeout", 5));
allowedSpecialChars = Convert.ToString(GetConfig("Limits", "allowedSpecialChars", "!²³"));
enableFFOPtion = Convert.ToBoolean(GetConfig("Settings", "enableFFOPtion", true));
enableAllyFFOPtion = Convert.ToBoolean(GetConfig("Settings", "enableAllyFFOPtion", true));
forceAllyFFNoDeactivate = Convert.ToBoolean(GetConfig("Settings", "forceAllyFFNoDeactivate", true));
enableWordFilter = Convert.ToBoolean(GetConfig("Settings", "enableWordFilter", true));
enableClanTagging = Convert.ToBoolean(GetConfig("Settings", "enableClanTagging", true));
enableClanAllies = Convert.ToBoolean(GetConfig("Settings", "enableClanAllies", false));
setHomeOwner = Convert.ToBoolean(GetConfig("NTeleportation", "setHomeOwner", true));
setHomeModerator = Convert.ToBoolean(GetConfig("NTeleportation", "setHomeModerator", true));
setHomeMember = Convert.ToBoolean(GetConfig("NTeleportation", "setHomeMember", true));
authLevelRename = Convert.ToInt32(GetConfig("Permission", "authLevelRename", 1));
authLevelDelete = Convert.ToInt32(GetConfig("Permission", "authLevelDelete", 2));
authLevelInvite = Convert.ToInt32(GetConfig("Permission", "authLevelInvite", 1));
authLevelKick = Convert.ToInt32(GetConfig("Permission", "authLevelKick", 2));
authLevelPromoteDemote = Convert.ToInt32(GetConfig("Permission", "authLevelPromoteDemote", 1));
authLevelClanInfo = Convert.ToInt32(GetConfig("Permission", "authLevelClanInfo", 0));
usePermGroups = Convert.ToBoolean(GetConfig("Permission", "usePermGroups", false));
permGroupPrefix = Convert.ToString(GetConfig("Permission", "permGroupPrefix", "clan_"));
usePermToCreateClan = Convert.ToBoolean(GetConfig("Permission", "usePermToCreateClan", false));
permissionToCreateClan = Convert.ToString(GetConfig("Permission", "permissionToCreateClan", "clans.cancreate"));
purgeOldClans = Convert.ToBoolean(GetConfig("Purge", "purgeOldClans", false));
notUpdatedSinceDays = Convert.ToInt32(GetConfig("Purge", "notUpdatedSinceDays", 14));
listPurgedClans = Convert.ToBoolean(GetConfig("Purge", "listPurgedClans", false));
wipeClansOnNewSave = Convert.ToBoolean(GetConfig("Purge", "wipeClansOnNewSave", false));
consoleName = Convert.ToString(GetConfig("Formatting", "consoleName", "ServerOwner"));
broadcastPrefix = Convert.ToString(GetConfig("Formatting", "broadcastPrefix", "[КЛАН]"));
broadcastPrefixAlly = Convert.ToString(GetConfig("Formatting", "broadcastPrefixAlly", "[СОЮЗ]"));
broadcastPrefixColor = Convert.ToString(GetConfig("Formatting", "broadcastPrefixColor", "#ff9900"));
broadcastPrefixFormat = Convert.ToString(GetConfig("Formatting", "broadcastPrefixFormat", "<color={0}>{1}</color> "));
broadcastMessageColor = Convert.ToString(GetConfig("Formatting", "broadcastMessageColor", "#ffffff"));
colorCmdUsage = Convert.ToString(GetConfig("Formatting", "colorCmdUsage", "#ffd479"));
colorTextMsg = Convert.ToString(GetConfig("Formatting", "colorTextMsg", "#ffffff"));
colorClanNamesOverview = Convert.ToString(GetConfig("Formatting", "colorClanNamesOverview", "orange"));
colorClanFFOff = Convert.ToString(GetConfig("Formatting", "colorClanFFOff", "lime"));
colorClanFFOn = Convert.ToString(GetConfig("Formatting", "colorClanFFOn", "#47d147"));
pluginPrefix = Convert.ToString(GetConfig("Formatting", "pluginPrefix", "КЛАНЫ"));
pluginPrefixColor = Convert.ToString(GetConfig("Formatting", "pluginPrefixColor", "orange"));
pluginPrefixREBORNColor = Convert.ToString(GetConfig("Formatting", "pluginPrefixREBORNColor", "#ce422b"));
pluginPrefixFormat = Convert.ToString(GetConfig("Formatting", "pluginPrefixFormat", "<color={0}>{1}</color>: "));
clanServerColor = Convert.ToString(GetConfig("Formatting", "clanServerColor", "#ff3333"));
clanOwnerColor = Convert.ToString(GetConfig("Formatting", "clanOwnerColor", "#a1ff46"));
clanCouncilColor = Convert.ToString(GetConfig("Formatting", "clanCouncilColor", "#b573ff"));
clanModeratorColor = Convert.ToString(GetConfig("Formatting", "clanModeratorColor", "#74c6ff"));
clanMemberColor = Convert.ToString(GetConfig("Formatting", "clanMemberColor", "#fcf5cb"));
clanTagColorBetterChat = Convert.ToString(GetConfig("BetterChat", "clanTagColorBetterChat", "#66cc00"));
clanTagSizeBetterChat = Convert.ToInt32(GetConfig("BetterChat", "clanTagSizeBetterChat", 15));
clanTagOpening = Convert.ToString(GetConfig("BetterChat", "clanTagOpening", "["));
clanTagClosing = Convert.ToString(GetConfig("BetterChat", "clanTagClosing", "]"));
chatCommandClan = Convert.ToString(GetConfig("Commands", "chatCommandClan", "clan"));
chatCommandFF = Convert.ToString(GetConfig("Commands", "chatCommandFF", "cff"));
chatCommandAllyChat = Convert.ToString(GetConfig("Commands", "chatCommandAllyChat", "a"));
chatCommandClanChat = Convert.ToString(GetConfig("Commands", "chatCommandClanChat", "c"));
chatCommandClanInfo = Convert.ToString(GetConfig("Commands", "chatCommandClanInfo", "cinfo"));
addClanMembersAsIOFriends = Convert.ToBoolean(GetConfig("RustIO", "addClanMembersAsIOFriends", true));
enableRustIOSupport = Convert.ToBoolean(GetConfig("RustIO", "enableRustIOSupport", false));
if (!Changed) return;
SaveConfig();
Changed = false;
}
protected override void LoadDefaultConfig() {
Config.Clear();
LoadVariables();
}
void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
{
"nopermtocreate", "У вас нет прав на создание клана."
}
, {
"claninvite", "<color=white>Вас пригласили присоединиться к клану:</color> [<color=#ffd479>{0}</color>] '<color=#ffd479>{1}</color>'\n<color=white>Чтобы присоединиться, введите:</color> <color=#ffd479>/clan join {0}</color>"
}
, {
"comeonline", "<color=#ffd479>{0}</color> <color=white>зашёл на сервер!</color>"
}
, {
"goneoffline", "<color=#ffd479>{0}</color> <color=white>покинул сервер!</color>"
}
, {
"friendlyfire", "<color=#ffd479>{0}</color> <color=white>является участником клана.\nЧтобы переключить дружественный огонь для клана, введите</color> <color=#ffd479>/clan ff</color>"
}
, {
"allyfriendlyfire", "<color=#ffd479>{0}</color> <color=white>является союзником клана.</color>"
}
, {
"notmember", "<color=white>На данный момент вы не состоите в клане.</color>"
}
, {
"youareownerof", "<color=white>Вы являетесь владельцем: </color>"
}
, {
"youaremodof", "<color=white>Вы являетесь модератором: </color>"
}
, {
"youarecouncilof", "<color=white>Вы являетесь советом: </color>"
}
, {
"youarememberof", "<color=white>Вы являетесь участником: </color>"
}
, {
"claninfo", " [{0}] {1}"
}
, {
"memberon", "<color=white>В сети: </color>"
}
, {
"overviewnamecolor", "<color={0}>{1}</color>"
}
, {
"memberoff", "<color=white>Оффлайн: </color>"
}
, {
"notmoderator", "<color=white>Это команда доступна модератору и владельцу клана.</color>"
}
, {
"pendinvites", "<color=white>Приглашения в ожидании: </color>"
}
, {
"bannedwords", "<color=white>Тег клана содержит запрещенные слова.</color>"
}
, {
"viewthehelp", "<color=white>Чтобы узнать больше о кланах, введите: </color><color=#ffd479>/{1} help</color>"
}
, {
"usagecreate", "<color=white>Используйте - </color><color=#ffd479>/clan create <ТЕГ> <описание></color>"
}
, {
"hintlength", "Тег клана должен содержать от <color=#ffd479>{0}</color> до <color=#ffd479>{1}</color> символов"
}
, {
"hintchars", "<color=white>Тег клана должен содержать только такие символы как: '</color><color=#ffd479>a-z</color><color=white>' '</color><color=#ffd479>A-Z</color><color=white>' '</color><color=#ffd479>0-9</color><color=white>' '</color><color=#ffd479>а-я</color><color=white>' '</color><color=#ffd479>А-Я</color><color=white>' '</color><color=#ffd479>{0}</color><color=white>'</color>"
}
, {
"providedesc", "<color=white>Напишите краткое описание вашего клана.</color>"
}
, {
"tagblocked", "<color=white>Какой-то клан уже использует этот тег.</color>"
}
, {
"nownewowner", "<color=white>Теперь вы владелец клана</color> <color=#ffd479>{0}</color>\n<color=white>Описание клана:</color> <color=#ffd479>{1}</color>"
}
, {
"inviteplayers", "<color=white>Чтобы пригласить игрока, введите:</color> <color=#ffd479>/clan invite <игрок></color>"
}
, {
"usageinvite", "<color=white>Используйте - </color><color=#ffd479>/clan invite <игрок></color>"
}
, {
"nosuchplayer", "<color=white>Игрока с никнеймом</color> <color=#ffd479>{0}</color> <color=white>нет, либо вы ввели неправильно никнейм.</color>"
}
, {
"alreadymember", "<color=white>Игрок</color> <color=#ffd479>{0}</color> <color=white>уже состоит в вашем клане.</color>"
}
, {
"alreadyinvited", "<color=white>Игрок</color> <color=#ffd479>{0}</color> <color=white>уже приглашен в ваш клан.</color>"
}
, {
"alreadyinclan", "<color=white>Игрок</color> <color=#ffd479>{0}</color> <color=white>уже состоит в клане.</color>"
}
, {
"invitebroadcast", "Игрок <color=#ffd479>{0}</color> пригласил <color=#ffd479>{1}</color> в клан."
}
, {
"usagewithdraw", "<color=white>Используйте - </color><color=#ffd479>/clan withdraw <игрок></color>"
}
, {
"notinvited", "<color=white>Игрок</color> <color=#ffd479>{0}</color> <color=white>не приглашен в ваш клан.</color>"
}
, {
"canceledinvite", "<color=#ffd479>{0}</color> отменил приглашение <color=#ffd479>{1}</color>"
}
, {
"usagejoin", "<color=white>Используйте - </color><color=#ffd479>/clan join <ТЕГ></color>"
}
, {
"youalreadymember", "<color=white>Вы уже состоите в клане.</color>"
}
, {
"younotinvited", "<color=white>Вас не приглашали в этот клан.</color>"
}
, {
"reachedmaximum", "<color=white>В этом клане достигнуто максимальное количество участников.</color>"
}
, {
"broadcastformat", "<color={0}>{1}</color>: {2}"
}
, {
"allybroadcastformat", "[{0}] <color={1}>{2}</color>: {3}"
}
, {
"clanrenamed", "<color=#ffd479>{0}</color> переименовал клан на: [<color=#ffd479>{1}</color>]"
}
, {
"yourenamed", "Вы переименовали клан [<color=#ffd479>{0}</color>] на [<color=#ffd479>{1}</color>]"
}
, {
"clandeleted", "<color=#ffd479>{0}</color> удалил ваш клан."
}
, {
"youdeleted", "Вы удалили клан [<color=#ffd479>{0}</color>]"
}
, {
"noclanfound", "Клана с тегом [<color=#ffd479>{0}</color>] не существует"
}
, {
"renamerightsowner", "Вам нужно быть владельцем сервера, чтобы переименовать клан."
}
, {
"usagerename", "<color=white>Используйте - </color><color=#ffd479>/clan rename <СТАРЫЙ ТЕГ> <НОВЫЙ ТЕГ></color>"
}
, {
"deleterightsowner", "Вы должны быть владельцем сервера, чтобы удалить клан."
}
, {
"usagedelete", "<color=white>Используйте - </color><color=#ffd479>/clan delete <ТЕГ></color>"
}
, {
"clandisbanded", "<color=white>Вы распустили свой клан.</color>"
}
, {
"needclanowner", "Вы должны быть владельцем сервера, чтобы использовать эту команду."
}
, {
"needclanownercouncil", "Вы должны быть владельцем или советом, чтобы использовать эту команду."
}
, {
"usagedisband", "<color=white>Используйте - </color><color=#ffd479>/clan disband forever</color>"
}
, {
"usagepromote", "<color=white>Используйте - </color><color=#ffd479>/clan promote <игрок></color>"
}
, {
"playerjoined", "<color=#ffd479>{0}</color> зашёл в клан!"
}
, {
"waskicked", "<color=#ffd479>{0}</color> выгнал <color=#ffd479>{1}</color> из клана."
}
, {
"modownercannotkicked", "Игрок <color=#ffd479>{0}</color> является модератором или владельцем клана и его нельзя выгнать."
}
, {
"notmembercannotkicked", "Игрок <color=#ffd479>{0}</color> не участник вашего клана."
}
, {
"usageff", "<color=white>Используйте - </color><color=#ffd479>/clan ff</color> Изменить статус дружественного огня."
}
, {
"usagekick", "<color=white>Используйте - </color><color=#ffd479>/clan kick <игрок></color>"
}
, {
"playerleft", "<color=orange>{0}</color> <color=white>покинул клан.</color>"
}
, {
"youleft", "<color=white>Вы покинули свой клан.</color>"
}
, {
"usageleave", "<color=white>Используйте - </color><color=#ffd479>/clan leave</color>"
}
, {
"notaclanmember", "Игрок <color=#ffd479>{0}</color> не участник вашего клана."
}
, {
"alreadyamod", "Игрок <color=#ffd479>{0}</color> уже является модератором вашего клана."
}
, {
"alreadyacouncil", "Игрок <color=#ffd479>{0}</color> уже является советом вашего клана."
}
, {
"alreadyacouncilset", "Должность совета уже присуждена."
}
, {
"maximummods", "В этом клане уже достигнуто максимальное количество модераторов."
}
, {
"playerpromoted", "Игрок <color=#ffd479>{0}</color> повысил <color=#ffd479>{1}</color> до модератора."
}
, {
"playerpromotedcouncil", "Игрок <color=#ffd479>{0}</color> повысил <color=#ffd479>{1}</color> до совета."
}
, {
"usagedemote", "<color=white>Используйте - </color><color=#ffd479>/clan demote <игрок></color>"
}
, {
"notamoderator", "Игрок <color=#ffd479>{0}</color> не модератор вашего клана."
}
, {
"notpromoted", "Игрок <color=#ffd479>{0}</color> не модератор/совет вашего клана."
}
, {
"playerdemoted", "Игрок <color=#ffd479>{0}</color> понизил <color=#ffd479>{1}</color> до участника."
}
, {
"councildemoted", "Игрок <color=#ffd479>{0}</color> понизил <color=#ffd479>{1}</color> до модератора."
}
, {
"noactiveally", "У вашего клана нет союзов."
}
, {
"yourffstatus", "Дружественный огонь:"
}
, {
"yourclanallies", "Ваши союзные кланы:"
}
, {
"allyinvites", "Приглашения в союз:"
}
, {
"allypending", "Запросы союзника:"
}
, {
"allyReqHelp", "Предложить союз другому клану"
}
, {
"allyAccHelp", "Принять союз с другим кланом"
}
, {
"allyDecHelp", "Отклонить союз от другого клана"
}
, {
"allyCanHelp", "Отменить союз с другим кланом"
}
, {
"reqAlliance", "[<color=#ffd479>{0}</color>] отправил вам запрос на союз"
}
, {
"invitePending", "У вас уже есть приглашение союза с [<color=#ffd479>{0}</color>]"
}
, {
"clanNoExist", "Клана [<color=#ffd479>{0}</color>] не существует"
}
, {
"alreadyAllies", "Вы уже союзники с"
}
, {
"allyProvideName", "Необходимо указать название клана"
}
, {
"allyLimit", "Вы достигли максимального количества союзников клана"
}
, {
"allyAccLimit", "Вы не можете принять союз с <color=#ffd479>{0}</color>.Вы достигли предела"
}
, {
"allyCancel", "Вы отменили свой союз с [<color=#ffd479>{0}</color>]"
}
, {
"allyCancelSucc", "[<color=#ffd479>{0}</color>] отменил ваш клановый союз"
}
, {
"noAlly", "У вас в клане нету союзников"
}
, {
"noAllyInv", "У вас нет союз приглашения от [<color=#ffd479>{0}</color>]"
}
, {
"allyInvWithdraw", "Вы отменили свой запрос на союз с [<color=#ffd479>{0}</color>]"
}
, {
"allyDeclined", "Вы отказались от кланового союза с [<color=#ffd479>{0}</color>]"
}
, {
"allyDeclinedSucc", "[<color=#ffd479>{0}</color>] отклонил ваш запрос на союз"
}
, {
"allyReq", "Вы отправили запрос на клановый союз с [<color=#ffd479>{0}</color>]"
}
, {
"allyAcc", "Вы приняли клановый союз с [<color=#ffd479>{0}</color>]"
}
, {
"allyAccSucc", "[<color=#ffd479>{0}</color>] принял ваш запрос на союз"
}
, {
"allyPendingInfo", "У вашго клана есть запрос на союз."
}
, {
"clanffdisabled", "Вы <color={0}>выключили</color> дружественный огонь для вашего клана."
}
, {
"clanffenabled", "Вы <color={0}>включили</color> дружественный огонь для вашего клана."
}
, {
"yourname", "ВЫ"
}
, {
"helpavailablecmds", "Доступные команды:"
}
, {
"helpinformation", "Показать информацию о вашем клане"
}
, {
"helpmessagemembers", "Отправить сообщение всем участникам клана"
}
, {
"helpmessageally", "Отправить сообщение всем участникам клана"
}
, {
"helpcreate", "Создать новый клан"
}
, {
"helpjoin", "Вступить в клан по приглашению"
}
, {
"helpleave", "Покинуть клан"
}
, {
"helptoggleff", "Изменить статус дружественного огня"
}
, {
"helpinvite", "Пригласить игрока в клан"
}
, {
"helpwithdraw", "Отменить приглашение в клан"
}
, {
"helpkick", "Выгнать игрока из клана"
}
, {
"helpallyoptions", "Список опций союза"
}
, {
"helppromote", "Повысить участника клана до модератора"
}
, {
"helpdemote", "Снять привилегию модератора с участника клана"
}
, {
"helpdisband", "Распустить ваш клан"
}
, {
"helpconsole", "<color=white>Откройте консоль с помощью</color> <color=#ffd479>F1</color> <color=white>и введите:</color>"
}
,
}
, this);
}
void Init() {
cc = this;
LoadVariables();
LoadDefaultMessages();
Initialized = false;
if (!permission.PermissionExists(permissionToCreateClan)) permission.RegisterPermission(permissionToCreateClan, this);
cmd.AddChatCommand(chatCommandFF, this, "cmdChatClanFF");
cmd.AddChatCommand(chatCommandClan, this, "cmdChatClan");
cmd.AddChatCommand(chatCommandClanChat, this, "cmdChatClanchat");
cmd.AddChatCommand(chatCommandAllyChat, this, "cmdChatAllychat");
cmd.AddChatCommand(chatCommandClanInfo, this, "cmdChatClanInfo");
cmd.AddChatCommand(chatCommandClan+"help", this, "cmdChatClanHelp");
cmd.AddChatCommand(chatCommandClan+"ally", this, "cmdChatClanAlly");
if (enableClanTagging) Interface.CallHook("API_RegisterThirdPartyTitle", this, new Func<IPlayer, string>(getFormattedClanTag));
}
void OnPluginLoaded(Plugin plugin) {
if (plugin.Title != "Better Chat") return;
if (enableClanTagging) Interface.CallHook("API_RegisterThirdPartyTitle", this, new Func<IPlayer, string>(getFormattedClanTag));
}
string getFormattedClanTag(IPlayer player) {
var clan = findClanByUser(player.Id);
if (clan != null && !string.IsNullOrEmpty(clan.tag)) return $"[#{clanTagColorBetterChat.Replace("#","")}][+{clanTagSizeBetterChat}]{clanTagOpening}{clan.tag}{clanTagClosing}[/+][/#]";
return string.Empty;
}
void OnServerInitialized() {
if (enableRustIOSupport) ioInitialize();
LoadData();
if (purgeOldClans) Puts($"Valid clans loaded: '{clans.Count}'");
if (purgeOldClans && purgedClans.Count() > 0) {
Puts($"Old Clans purged: '{purgedClans.Count}'");
if (listPurgedClans) {
foreach (var purged in purgedClans) Puts($"Purged > {purged}");
}
}
AllyRemovalCheck();
tagReExt = new Regex("[^a-zA-Z0-9" + allowedSpecialChars + "]");
foreach (var player in BasePlayer.activePlayerList) setupPlayer(player);
foreach (var player in BasePlayer.sleepingPlayerList) setupPlayer(player);
Initialized = true;
}
void OnServerSave() {
SaveData();
}
void OnNewSave() {
if (wipeClansOnNewSave) newSaveDetected = true;
}
void Unload() {
if (!Initialized) return;
SaveData();
foreach (var pair in originalNames) {
var player = rust.FindPlayerByIdString(pair.Key);
if (player != null && player.displayName != pair.Value) {
displayName.SetValue(player, pair.Value);
if (player.net != null) name.SetValue(player, string.Format("{1}[{0}/{2}]", player.net.ID, pair.Value, player.userID));
player.SendNetworkUpdate();
}
}
}
void ioInitialize() {
lib = Interface.GetMod().GetLibrary<Library>("RustIO");
if (lib == null || (isInstalled = lib.GetFunction("IsInstalled")) == null || (addFriend = lib.GetFunction("AddFriend")) == null) {
lib = null;
Puts("{0}: {1}", Title, "Rust:IO is not present.You need to install Rust:IO first in order to use this plugin!");
}
}
bool ioIsInstalled() {
if (lib == null) return false;
return (bool)isInstalled.Invoke(lib, new object[] {
}
);
}
bool ioAddFriend(string playerId, string friendId) {
if (lib == null) return false;
return (bool)addFriend.Invoke(lib, new object[] {
playerId, friendId
}
);
}
void LoadData() {
if (wipeClansOnNewSave && newSaveDetected) {
var newdata = Interface.GetMod().DataFileSystem.GetDatafile("rustio_clans");
newdata.Save(Interface.GetMod().DataFileSystem.Directory+ "/rustio_clans.old");
clans.Clear();
newdata["clans"] = clans;
Interface.GetMod().DataFileSystem.SaveDatafile("rustio_clans");
Puts("New save detected > Created backup of clans and wiped datafile.");
return;
}
Puts("Loading clans data.");
clans.Clear();
var data = Interface.GetMod().DataFileSystem.GetDatafile("rustio_clans");
if (data["clans"] != null) {
Dictionary<string, object> clansData = new Dictionary<string, object>();
try {
clansData = (Dictionary<string, object>)Convert.ChangeType(data["clans"], typeof(Dictionary<string, object>));
}
catch {
}
foreach (var iclan in clansData) {
string tag = iclan.Key;
string permGroup = permGroupPrefix + tag;
if (usePermGroups && !permission.GroupExists(permGroup)) permission.CreateGroup(permGroup, "Clan " + tag, 0);
var clanData = iclan.Value as Dictionary<string, object>;
string description = (string)clanData["description"];
string owner = (string)clanData["owner"];
string council = null;
if (clanData.ContainsKey("council")) council = (string)clanData["council"];
if (!enableClanAllies) council = null;
List<string> moderators = new List<string>();
foreach (var imoderator in clanData["moderators"] as List<object>) {
moderators.Add((string)imoderator);
}
List<string> members = new List<string>();
foreach (var imember in clanData["members"] as List<object>) {
members.Add((string)imember);
if (usePermGroups && !permission.UserHasGroup((string)imember, permGroup)) permission.AddUserGroup((string)imember, permGroup);
}
List<string> clanAlliances = new List<string>();
if (enableClanAllies && clanData.ContainsKey("clanAlliances")) foreach (var iAlly in clanData["clanAlliances"] as List<object>) {
clanAlliances.Add((string)iAlly);
}
List<string> invitedAllies = new List<string>();
if (enableClanAllies && clanData.ContainsKey("invitedAllies")) foreach (var iInvited in clanData["invitedAllies"] as List<object>) {
invitedAllies.Add((string)iInvited);
}
List<string> pendingInvites = new List<string>();
if (enableClanAllies && clanData.ContainsKey("pendingInvites")) foreach (var iPending in clanData["pendingInvites"] as List<object>) {
pendingInvites.Add((string)iPending);
}
Dictionary<string, int> invites = new Dictionary<string, int>();
try {
foreach (var iinvited in clanData["invites"] as Dictionary<string, object>) {
if ((UnixTimeStampUTC() - (int)iinvited.Value) < (inviteValidDays * 86400)) invites.Add((string)iinvited.Key, (int)iinvited.Value);
}
}
catch {
}
object time;
int created = 0;
int updated = 0;
if (clanData.TryGetValue("created", out time)) created = (int)time;
if (created == 0) created = UnixTimeStampUTC();
time = null;
if (clanData.TryGetValue("updated", out time)) updated = (int)time;
if (updated == 0) updated = UnixTimeStampUTC();
Clan clan;
if (purgeOldClans && (UnixTimeStampUTC() - updated) > (notUpdatedSinceDays * 86400)) {
purgedClans.Add($"[{tag}] | {description} | Owner: {owner} | LastUpd: {UnixTimeStampToDateTime(updated)}");
if (permission.GroupExists(permGroup)) {
foreach (var member in members) if (permission.UserHasGroup(member, permGroup)) permission.RemoveUserGroup(member, permGroup);
permission.RemoveGroup(permGroup);
}
continue;
}
clans.Add(tag, clan = new Clan() {
tag = tag, description = description, owner = owner, council = council, moderators = moderators, members = members, invites = invites, clanAlliances = clanAlliances, invitedAllies = invitedAllies, pendingInvites = pendingInvites, created = created, updated = updated, total = members.Count(), mods = moderators.Count()
}
);
clanCache[owner] = clan;
foreach (var member in members) clanCache[member] = clan;
foreach (var invite in invites) {
if (!pendingPlayerInvites.ContainsKey(invite.Key)) pendingPlayerInvites.Add(invite.Key, new List<string>());
pendingPlayerInvites[invite.Key].Add(tag);
}
}
}
Puts($"Loaded data with '{clans.Count}' valid Clans and overall '{clanCache.Count}' Members.");
}
void SaveData() {
if (!Initialized) return;
var data = Interface.GetMod().DataFileSystem.GetDatafile("rustio_clans");
data.Clear();
data["clans"] = clans;
Interface.GetMod().DataFileSystem.SaveDatafile("rustio_clans");
}
public Clan findClan(string tag) {
Clan clan;
if (clans.TryGetValue(tag, out clan)) return clan;
return null;
}
public Clan findClanByUser(string userId) {
Clan clan;
if (clanCache.TryGetValue(userId, out clan)) return clan;
return null;
}
void setupPlayer(BasePlayer player, string cName = "", string cId = "") {
if (player == null || player.UserIDString == "" || player.displayName == "") return;
if (cName == "" || cId == "") {
var current = this.covalence.Players.FindPlayer(player.UserIDString);
if (current == null) return;
cName = current.Name;
cId = current.Id;
}
if (!originalNames.ContainsKey(cId)) originalNames.Add(cId, cName);
else originalNames[cId] = cName;
var prevName = player.displayName;
var clan = findClanByUser(cId);
if (clan == null) {
if (enableClanTagging) {
displayName.SetValue(player, cName);
if (player.IsConnected) name.SetValue(player, string.Format("{1}[{0}/{2}]", player.net.ID, cName, player.userID));
}
}
else {
if (enableClanTagging) displayName.SetValue(player, $"[{clan.tag}] {cName}");
if (player.IsConnected) {
if (enableClanTagging) name.SetValue(player, string.Format("{1}[{0}/{2}]", player.net.ID, $"[{clan.tag}] {cName}", player.userID));
clan.online++;
}
}
if (enableClanTagging && player.displayName != prevName) player.SendNetworkUpdate();
}
void setupPlayers(List<string> playerIds) {
if (enableClanTagging) foreach (var playerId in playerIds) {
var player = rust.FindPlayerByIdString(playerId);
if (player != null) setupPlayer(player);
}
}
void OnPlayerInit(BasePlayer player) {
if (player == null || player.net == null || player.net.connection == null) return;
displayName.SetValue(player, player.net.connection.username);
setupPlayer(player, player.net.connection.username, player.UserIDString);
var clan = findClanByUser(player.UserIDString);
if (clan != null) {
clan.BroadcastLoc("comeonline", clan.ColNam(player.UserIDString, player.net.connection.username), "", "", "", player.UserIDString);
var sb = new StringBuilder();
sb.Append($"<color={colorTextMsg}>");
sb.Append(string.Format(msg("<color=white>В сети: </color>", player.UserIDString)));
int n = 0;
foreach (var memberId in clan.members) {
var op = this.covalence.Players.FindPlayer(memberId);
if (op != null && op.IsConnected) {
var memberName = op.Name;
if (op.Name == player.net.connection.username) memberName = msg("ВЫ", player.UserIDString);
if (n > 0) sb.Append(", ");
if (clan.IsOwner(memberId)) {
sb.Append(string.Format(msg("overviewnamecolor", player.UserIDString), clanOwnerColor, memberName));
}
else if (clan.IsCouncil(memberId)) {
sb.Append(string.Format(msg("overviewnamecolor", player.UserIDString), clanCouncilColor, memberName));
}
else if (clan.IsModerator(memberId)) {
sb.Append(string.Format(msg("overviewnamecolor", player.UserIDString), clanModeratorColor, memberName));
}
else {
sb.Append(string.Format(msg("overviewnamecolor", player.UserIDString), clanMemberColor, memberName));
}
++n;
}
}
sb.Append($"</color>");
PrintChat(player, sb.ToString().TrimEnd());
clan.updated = UnixTimeStampUTC();
manuallyEnabledBy.Remove(player.userID);
if (enableClanAllies && (clan.IsOwner(player.UserIDString) || clan.IsCouncil(player.UserIDString)) && clan.pendingInvites.Count > 0) {
if (player != null) PrintChat(player, string.Format(msg("У вашго клана есть запрос на союз.", player.UserIDString)));
}
return;
}
if (pendingPlayerInvites.ContainsKey(player.UserIDString)) {
foreach (var invitation in pendingPlayerInvites[player.UserIDString] as List<string>) {
Clan newclan = findClan(invitation);
if (newclan != null) timer.Once(3f, () => {
if (player != null) PrintChat(player, string.Format(msg("<color=white>Вас пригласили присоединиться к клану:</color> [<color=#ffd479>{0}</color>] '<color=#ffd479>{1}</color>'\n<color=white>Чтобы присоединиться, введите:</color> <color=#ffd479>/clan join {0}</color>", player.UserIDString), newclan.tag, newclan.description, colorCmdUsage));
}
);
}
}
}
void OnPlayerDisconnected(BasePlayer player) {
var clan = findClanByUser(player.UserIDString);
if (clan != null) {
clan.BroadcastLoc("goneoffline", clan.ColNam(player.UserIDString, player.net.connection.username), "", "", "", player.UserIDString);
clan.online--;
manuallyEnabledBy.Remove(player.userID);
}
}
void OnPlayerAttack(BasePlayer attacker, HitInfo hit) {
if (!enableFFOPtion || attacker == null || hit == null || !(hit.HitEntity is BasePlayer)) return;
OnAttackShared(attacker, hit.HitEntity as BasePlayer, hit);
}
void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hit) {
if (!enableFFOPtion || entity == null || hit == null || !(entity is BasePlayer) || !(hit.Initiator is BasePlayer)) return;
OnAttackShared(hit.Initiator as BasePlayer, entity as BasePlayer, hit);
}
object OnAttackShared(BasePlayer attacker, BasePlayer victim, HitInfo hit) {
if (bypass.Contains(victim.userID) || attacker == victim) return null;
var victimClan = findClanByUser(victim.UserIDString);
var attackerClan = findClanByUser(attacker.UserIDString);
if (victimClan == null || attackerClan == null) return null;
if (victimClan.tag == attackerClan.tag) {
if (manuallyEnabledBy.Contains(attacker.userID)) return null;
DateTime now = DateTime.UtcNow;
DateTime time;
var key = attacker.UserIDString + "-" + victim.UserIDString;
if (!notificationTimes.TryGetValue(key, out time) || time < now.AddSeconds(-friendlyFireNotifyTimeout)) {
PrintChat(attacker, string.Format(msg("<color=#ffd479>{0}</color> <color=white>является участником клана.\nЧтобы переключить дружественный огонь для клана, введите</color> <color=#ffd479>/clan ff</color>", attacker.UserIDString), victim.displayName, colorCmdUsage));
notificationTimes[key] = now;
}
hit.damageTypes = new DamageTypeList();
hit.DidHit = false;
hit.HitEntity = null;
hit.Initiator = null;
hit.DoHitEffects = false;
return false;
}
if (victimClan.tag != attackerClan.tag && enableClanAllies && enableAllyFFOPtion) {
if (!victimClan.clanAlliances.Contains(attackerClan.tag)) return null;
if (manuallyEnabledBy.Contains(attacker.userID) && !forceAllyFFNoDeactivate) return null;
DateTime now = DateTime.UtcNow;
DateTime time;
var key = attacker.UserIDString + "-" + victim.UserIDString;
if (!notificationTimes.TryGetValue(key, out time) || time < now.AddSeconds(-friendlyFireNotifyTimeout)) {
PrintChat(attacker, string.Format(msg("<color=#ffd479>{0}</color> <color=white>является союзником клана.</color>", attacker.UserIDString), victim.displayName));
notificationTimes[key] = now;
}
hit.damageTypes = new DamageTypeList();
hit.DidHit = false;
hit.HitEntity = null;
// ... [Code preview truncated due to length. Full source in attached file] ...