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", "Fujikura", "2.8.2", ResourceId = 14)]
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;
bool enableWhoIsOnlineMsg;
bool enableComesOnlineMsg;
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));
enableWhoIsOnlineMsg = Convert.ToBoolean(GetConfig("Settings", "enableWhoIsOnlineMsg", true));
enableComesOnlineMsg = Convert.ToBoolean(GetConfig("Settings", "enableComesOnlineMsg", true));
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", "(CLAN)"));
broadcastPrefixAlly = Convert.ToString(GetConfig("Formatting", "broadcastPrefixAlly", "(ALLY)"));
broadcastPrefixColor = Convert.ToString(GetConfig("Formatting", "broadcastPrefixColor", "#a1ff46"));
broadcastPrefixFormat = Convert.ToString(GetConfig("Formatting", "broadcastPrefixFormat", "<color={0}>{1}</color> "));
broadcastMessageColor = Convert.ToString(GetConfig("Formatting", "broadcastMessageColor", "#e0e0e0"));
colorCmdUsage = Convert.ToString(GetConfig("Formatting", "colorCmdUsage", "#ffd479"));
colorTextMsg = Convert.ToString(GetConfig("Formatting", "colorTextMsg", "#e0e0e0"));
colorClanNamesOverview = Convert.ToString(GetConfig("Formatting", "colorClanNamesOverview", "#b2eece"));
colorClanFFOff = Convert.ToString(GetConfig("Formatting", "colorClanFFOff", "lime"));
colorClanFFOn = Convert.ToString(GetConfig("Formatting", "colorClanFFOn", "red"));
pluginPrefix = Convert.ToString(GetConfig("Formatting", "pluginPrefix", "CLANS"));
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", "#aaff55"));
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", "You got no rights to create a clan."
}
, {
"claninvite", "You have been invited to join the clan: [{0}] '{1}'\nTo join, type: <color={2}>/clan join {0}</color>"
}
, {
"comeonline", "{0} has come online!"
}
, {
"goneoffline", "{0} has gone offline!"
}
, {
"friendlyfire", "{0} is a clan member and cannot be hurt.\nTo toggle clan friendlyfire type: <color={1}>/clan ff</color>"
}
, {
"allyfriendlyfire", "{0} is an ally member and cannot be hurt."
}
, {
"notmember", "You are currently not a member of a clan."
}
, {
"youareownerof", "You are the owner of:"
}
, {
"youaremodof", "You are a moderator of:"
}
, {
"youarecouncilof", "You are a council of:"
}
, {
"youarememberof", "You are a member of:"
}
, {
"claninfo", " [{0}] {1}"
}
, {
"memberon", "Members online: "
}
, {
"overviewnamecolor", "<color={0}>{1}</color>"
}
, {
"memberoff", "Members offline: "
}
, {
"notmoderator", "You need to be a moderator of your clan to use this command."
}
, {
"pendinvites", "Pending invites: "
}
, {
"bannedwords", "The clan tag contains banned words."
}
, {
"viewthehelp", "To view more commands, type: <color={0}>/{1} help</color>"
}
, {
"usagecreate", "Usage - <color={0}>/clan create \"TAG\" \"Description\"</color>"
}
, {
"hintlength", "Clan tags must be {0} to {1} characters long"
}
, {
"hintchars", "Clan tags must contain only 'a-z' 'A-Z' '0-9' '{0}'"
}
, {
"providedesc", "Please provide a short description of your clan."
}
, {
"tagblocked", "There is already a clan with this tag."
}
, {
"nownewowner", "You are now the owner of the clan [{0}] \"{1}\""
}
, {
"inviteplayers", "To invite new members, type: <color={0}>/clan invite <name></color>"
}
, {
"usageinvite", "Usage - <color={0}>/clan invite <name></color>"
}
, {
"nosuchplayer", "No such player or player name not unique: {0}"
}
, {
"alreadymember", "This player is already a member of your clan: {0}"
}
, {
"alreadyinvited", "This player has already been invited to your clan: {0}"
}
, {
"alreadyinclan", "This player is already in a clan: {0}"
}
, {
"invitebroadcast", "{0} invited {1} to the clan."
}
, {
"usagewithdraw", "Usage: <color={0}>/clan withdraw <name></color>"
}
, {
"notinvited", "This player has not been invited to your clan: {0}"
}
, {
"canceledinvite", "{0} canceled the invitation of {1}."
}
, {
"usagejoin", "Usage: <color={0}>/clan join \"TAG\"</color>"
}
, {
"youalreadymember", "You are already a member of a clan."
}
, {
"younotinvited", "You have not been invited to join this clan."
}
, {
"reachedmaximum", "This clan has already reached the maximum number of members."
}
, {
"broadcastformat", "<color={0}>{1}</color>: {2}"
}
, {
"allybroadcastformat", "[{0}] <color={1}>{2}</color>: {3}"
}
, {
"clanrenamed", "{0} renamed your clan to: [{1}]."
}
, {
"yourenamed", "You have renamed the clan [{0}] to [{1}]"
}
, {
"clandeleted", "{0} deleted your clan."
}
, {
"youdeleted", "You have deleted the clan [{0}]"
}
, {
"noclanfound", "There is no clan with that tag [{0}]"
}
, {
"renamerightsowner", "You need to be a server owner to rename clans."
}
, {
"usagerename", "Usage: <color={0}>/clan rename OLDTAG NEWTAG</color>"
}
, {
"deleterightsowner", "You need to be a server owner to delete clans."
}
, {
"usagedelete", "Usage: <color={0}>/clan delete TAG</color>"
}
, {
"clandisbanded", "Your current clan has been disbanded forever."
}
, {
"needclanowner", "You need to be the owner of your clan to use this command."
}
, {
"needclanownercouncil", "You need to be the owner or a council to use this command."
}
, {
"usagedisband", "Usage: <color={0}>/clan disband forever</color>"
}
, {
"usagepromote", "Usage: <color={0}>/clan promote <name></color>"
}
, {
"playerjoined", "{0} has joined the clan!"
}
, {
"waskicked", "{0} kicked {1} from the clan."
}
, {
"modownercannotkicked", "The player {0} is an owner or moderator and cannot be kicked."
}
, {
"notmembercannotkicked", "The player {0} is not a member of your clan."
}
, {
"usageff", "Usage: <color={0}>/clan ff</color> toggles your current FriendlyFire status."
}
, {
"usagekick", "Usage: <color={0}>/clan kick <name></color>"
}
, {
"playerleft", "{0} has left the clan."
}
, {
"youleft", "You have left your current clan."
}
, {
"usageleave", "Usage: <color={0}>/clan leave</color>"
}
, {
"notaclanmember", "The player {0} is not a member of your clan."
}
, {
"alreadyamod", "The player {0} is already a moderator of your clan."
}
, {
"alreadyacouncil", "The player {0} is already a council of your clan."
}
, {
"alreadyacouncilset", "The position of the council is already awarded."
}
, {
"maximummods", "This clan has already reached the maximum number of moderators."
}
, {
"playerpromoted", "{0} promoted {1} to moderator."
}
, {
"playerpromotedcouncil", "{0} promoted {1} to council."
}
, {
"usagedemote", "Usage: <color={0}>/clan demote <name></color>"
}
, {
"notamoderator", "The player {0} is not a moderator of your clan."
}
, {
"notpromoted", "The player {0} is not a moderator or council of your clan."
}
, {
"playerdemoted", "{0} demoted {1} to a member."
}
, {
"councildemoted", "{0} demoted {1} to a moderator."
}
, {
"noactiveally", "Your clan has no current alliances."
}
, {
"yourffstatus", "Your FriendlyFire:"
}
, {
"yourclanallies", "Your Clan allies:"
}
, {
"allyinvites", "Ally invites:"
}
, {
"allypending", "Ally requests:"
}
, {
"allyReqHelp", "Offer an alliance to another clan"
}
, {
"allyAccHelp", "Accept an alliance from another clan"
}
, {
"allyDecHelp", "Decline an alliance from another clan"
}
, {
"allyCanHelp", "Cancel an alliance with another clan"
}
, {
"reqAlliance", "[{0}] has requested a clan alliance"
}
, {
"invitePending", "You already have a pending alliance invite for [{0}]"
}
, {
"clanNoExist", "The clan [{0}] does not exist"
}
, {
"alreadyAllies", "You are already allied with"
}
, {
"allyProvideName", "You need to provide a Clan name"
}
, {
"allyLimit", "You already have the maximum allowed ally limit"
}
, {
"allyAccLimit", "You can not accept the alliance with {0}.You reached the limit"
}
, {
"allyCancel", "You have cancelled your alliance with [{0}]"
}
, {
"allyCancelSucc", "{0} has cancelled your clan alliance"
}
, {
"noAlly", "Your clans have no alliance with each other"
}
, {
"noAllyInv", "You do not have a alliance invite from [{0}]"
}
, {
"allyInvWithdraw", "You have cancelled your request to [{0}]"
}
, {
"allyDeclined", "You have declined the clan alliance from [{0}]"
}
, {
"allyDeclinedSucc", "[{0}] has declined your alliance request"
}
, {
"allyReq", "You have requested a clan alliance from [{0}]"
}
, {
"allyAcc", "You have accepted the clan alliance from [{0}]"
}
, {
"allyAccSucc", "[{0}] has accepted your alliance request"
}
, {
"allyPendingInfo", "Your clan has pending ally request(s).Check those in the clan overview."
}
, {
"clanffdisabled", "You have <color={0}>disabled</color> friendly fire for your clan.\nThey are safe!"
}
, {
"clanffenabled", "You have <color={0}>enabled</color> friendly fire for your clan.\nTake care!"
}
, {
"yourname", "YOU"
}
, {
"helpavailablecmds", "Available commands:"
}
, {
"helpinformation", "Display your clan information"
}
, {
"helpmessagemembers", "Send a message to all members"
}
, {
"helpmessageally", "Send a message to all allied members"
}
, {
"helpcreate", "Create a new clan"
}
, {
"helpjoin", "Join a clan by invitation"
}
, {
"helpleave", "Leave your clan"
}
, {
"helptoggleff", "Toggle friendlyfire status"
}
, {
"helpinvite", "Invite a player"
}
, {
"helpwithdraw", "Cancel an invite"
}
, {
"helpkick", "Kick a member"
}
, {
"helpallyoptions", "Lists the ally options"
}
, {
"helppromote", "Promote a member"
}
, {
"helpdemote", "Demote a member"
}
, {
"helpdisband", "Disband your clan (no undo)"
}
, {
"helpconsole", "Open F1 console and type:"
}
,
}
, 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) {
if (enableComesOnlineMsg) clan.BroadcastLoc("comeonline", clan.ColNam(player.UserIDString, player.net.connection.username), "", "", "", player.UserIDString);
if (enableWhoIsOnlineMsg) {
var sb = new StringBuilder();
sb.Append($"<color={colorTextMsg}>");
sb.Append(string.Format(msg("memberon", 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("yourname", 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("allyPendingInfo", 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("claninvite", 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("friendlyfire", 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("allyfriendlyfire", attacker.UserIDString), victim.displayName));
notificationTimes[key] = now;
}
hit.damageTypes = new DamageTypeList();
hit.DidHit = false;
hit.HitEntity = null;
hit.Initiator = null;
hit.DoHitEffects = false;
return false;
}
return null;
}
void AllyRemovalCheck() {
foreach (var ally in clans) {
try {
Clan allyClan = clans[ally.Key];
foreach (var clanAlliance in allyClan.clanAlliances.ToList()) {
if (!clans.ContainsKey(clanAlliance)) allyClan.clanAlliances.Remove(clanAlliance);
}
foreach (var invitedAlly in allyClan.invitedAllies.ToList()) {
if (!clans.ContainsKey(invitedAlly)) allyClan.clanAlliances.Remove(invitedAlly);
}
foreach (var pendingInvite in allyClan.pendingInvites.ToList()) {
if (!clans.ContainsKey(pendingInvite)) allyClan.clanAlliances.Remove(pendingInvite);
}
}
catch {
PrintWarning("Ally removal check failed.Please contact the developer.");
}
}
}
void cmdChatClan(BasePlayer player, string command, string[] args) {
if (player == null) return;
if (args.Length == 0) {
cmdClanOverview(player);
return;
}
switch (args[0]) {
case "create" : cmdClanCreate(player, args);
return;
case "invite" : cmdClanInvite(player, args);
return;
case "withdraw" : cmdClanWithdraw(player, args);
return;
case "join" : cmdClanJoin(player, args);
return;
case "promote" : cmdClanPromote(player, args);
return;
case "demote" : cmdClanDemote(player, args);
return;
case "leave" : cmdClanLeave(player, args);
return;
case "ff" : if (!enableFFOPtion) goto default;
cmdChatClanFF(player, command, args);
return;
case "ally" : if (!enableClanAllies) goto default;
for (var i = 0; i < args.Length-1; ++i) {
if (i < args.Length) args[i] = args[i+1];
}
Array.Resize(ref args, args.Length - 1);
cmdChatClanAlly(player, command, args);
return;
case "kick" : cmdClanKick(player, args);
return;
case "disband" : cmdClanDisband(player, args);
// ... [Code preview truncated due to length. Full source in attached file] ...