C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using UnityEngine;
using Random = UnityEngine.Random;
namespace Oxide.Plugins
{
[Info("Magic Message Panel", "MJSU", "1.2.1")]
[Description("Displays messages in magic panel")]
public class MagicMessagePanel : RustPlugin
{
#region Class Fields
[PluginReference] private readonly Plugin MagicPanel, PlaceholderAPI;
private DynamicConfigFile _newConfig;
private PluginConfig _pluginConfig; //Plugin Config
private enum UpdateEnum { All = 1, Panel = 2, Image = 3, Text = 4 }
private enum State {In, NotIn}
private readonly Hash<ulong, int> _playerIndex = new Hash<ulong, int>();
private readonly Hash<ulong, string> _playerLastMessage = new Hash<ulong, string>();
private Action<IPlayer, StringBuilder, bool> _replacer;
#endregion
#region Setup & Loading
protected override void LoadDefaultConfig()
{
PrintWarning("Loading Default Config");
}
protected override void LoadConfig()
{
string path = $"{Manager.ConfigPath}/MagicPanel/{Name}.json";
_newConfig = new DynamicConfigFile(path);
if (!_newConfig.Exists())
{
LoadDefaultConfig();
_newConfig.Save();
}
try
{
_newConfig.Load();
}
catch (Exception ex)
{
RaiseError("Failed to load config file (is the config file corrupt?) (" + ex.Message + ")");
return;
}
_newConfig.Settings.DefaultValueHandling = DefaultValueHandling.Populate;
_pluginConfig = AdditionalConfig(_newConfig.ReadObject<PluginConfig>());
_newConfig.WriteObject(_pluginConfig);
}
private PluginConfig AdditionalConfig(PluginConfig config)
{
config.Panels = config.Panels ?? new Hash<string, PanelData>
{
[$"{Name}_1"] = new PanelData
{
Panel = new Panel
{
Text = new PanelText
{
Enabled = true,
Color = "#FFFFFFFF",
Order = 1,
Width = 1f,
FontSize = 14,
Padding = new TypePadding(0.05f, 0.05f, 0.1f, 0.00f),
TextAnchor = TextAnchor.MiddleCenter,
Text = ""
}
},
PermMessages = new List<MessageGroupData>
{
new MessageGroupData
{
Enabled = true,
GroupOrPerm = "default",
State = State.In,
Messages = new List<string>
{
"You must be in the default group to see this message"
}
},
new MessageGroupData
{
Enabled = true,
GroupOrPerm = "VIP",
State = State.NotIn,
Messages = new List<string>
{
"Messages here for players not in VIP group or perm"
}
}
},
PanelSettings = new PanelRegistration
{
BackgroundColor = "#FFF2DF08",
Dock = "bottom",
Order = 0,
Width = 0.2954f
},
UpdateRate = 15f,
Enabled = true
}
};
return config;
}
private void OnServerInitialized()
{
//*****BEGIN TEMPORARY REMOVE AFTER 02/03/2021
bool changed = false;
foreach (PanelData panel in _pluginConfig.Panels.Values)
{
if (panel.ShouldSerializeMessages())
{
panel.PermMessages = new List<MessageGroupData>
{
new MessageGroupData
{
Messages = panel.Messages,
Enabled = true,
GroupOrPerm = "default",
State = State.In
}
};
changed = true;
}
}
if (changed)
{
_newConfig.WriteObject(_pluginConfig);
}
//*****END TEMPORARY REMOVE AFTER 02/03/2021
MagicPanelRegisterPanels();
foreach (IGrouping<float, KeyValuePair<string, PanelData>> panelUpdates in _pluginConfig.Panels.Where(p => p.Value.Enabled).GroupBy(p => p.Value.UpdateRate))
{
timer.Every(panelUpdates.Key, () =>
{
foreach (KeyValuePair<string, PanelData> data in panelUpdates)
{
MagicPanel?.Call("UpdatePanel", data.Key, (int)UpdateEnum.Text);
}
});
}
}
private void MagicPanelRegisterPanels()
{
if (MagicPanel == null)
{
PrintError("Missing plugin dependency MagicPanel: https://umod.org/plugins/magic-panel");
return;
}
foreach (KeyValuePair<string, PanelData> panel in _pluginConfig.Panels)
{
if (!panel.Value.Enabled)
{
continue;
}
MagicPanel?.Call("RegisterPlayerPanel", this, panel.Key, JsonConvert.SerializeObject(panel.Value.PanelSettings), nameof(GetPanel));
}
}
#endregion
#region MagicPanel Hook
private List<string> GetPlayerMessages(BasePlayer player, string panelName)
{
PanelData panel = _pluginConfig.Panels[panelName];
List<string> messages = new List<string>();
foreach (MessageGroupData data in panel.PermMessages)
{
if (data.State == State.In ? InPermOrGroup(player, data.GroupOrPerm) : !InPermOrGroup(player, data.GroupOrPerm))
{
messages.AddRange(data.Messages);
}
}
return messages;
}
private bool InPermOrGroup(BasePlayer player, string permGroup)
{
return permission.UserHasPermission(player.UserIDString, permGroup) || permission.UserHasGroup(player.UserIDString, permGroup);
}
private Hash<string, object> GetPanel(BasePlayer player, string panelName)
{
PanelData panelData = _pluginConfig.Panels[panelName];
Panel panel = panelData.Panel;
PanelText text = panel.Text;
if (text != null)
{
List<string> playerMessages = GetPlayerMessages(player, panelName);
if (playerMessages.Count == 0)
{
text.Text = string.Empty;
}
else if (playerMessages.Count == 1)
{
text.Text = playerMessages[0];
}
else if (panelData.RandomOrder)
{
string previous = _playerLastMessage[player.userID];
text.Text = playerMessages.Where(m => previous != m).Skip(Random.Range(0, playerMessages.Count - 1)).FirstOrDefault();
_playerLastMessage[player.userID] = text.Text;
}
else
{
int index = _playerIndex[player.userID];
index = (index + 1) % playerMessages.Count;
text.Text = playerMessages[index];
_playerIndex[player.userID] = index;
}
text.Text = ParseText(text.Text);
}
return panel.ToHash();
}
#endregion
#region PlaceholderAPI
private string ParseText(string text)
{
Action<IPlayer, StringBuilder, bool> replacer = GetReplacer();
if (replacer == null)
{
return text;
}
StringBuilder sb = new StringBuilder(text);
replacer.Invoke(null, sb, false);
return sb.ToString();
}
private void OnPluginUnloaded(Plugin plugin)
{
if (plugin?.Name == "PlaceholderAPI")
{
_replacer = null;
}
}
private Action<IPlayer, StringBuilder, bool> GetReplacer()
{
if (!IsPlaceholderApiLoaded())
{
return _replacer;
}
return _replacer ?? (_replacer = PlaceholderAPI.Call<Action<IPlayer, StringBuilder, bool>>("GetProcessPlaceholders", 1));
}
private bool IsPlaceholderApiLoaded() => PlaceholderAPI != null && PlaceholderAPI.IsLoaded;
#endregion
#region Classes
private class PluginConfig
{
[JsonProperty(PropertyName = "Message Panels")]
public Hash<string, PanelData> Panels { get; set; }
}
private class PanelData
{
[JsonProperty(PropertyName = "Panel Settings")]
public PanelRegistration PanelSettings { get; set; }
[JsonProperty(PropertyName = "Panel Layout")]
public Panel Panel { get; set; }
[JsonProperty(PropertyName = "Messages to all players")]
public List<string> Messages { get; set; }
[JsonProperty(PropertyName = "Perm or Group messages")]
public List<MessageGroupData> PermMessages = new List<MessageGroupData>();
[JsonProperty(PropertyName = "Random Message Display Order")]
public bool RandomOrder { get; set; }
[JsonProperty(PropertyName = "Update Rate (Seconds)")]
public float UpdateRate { get; set; }
[DefaultValue(true)]
[JsonProperty(PropertyName = "Enabled")]
public bool Enabled { get; set; }
public bool ShouldSerializeMessages()
{
return Messages != null && Messages.Count > 0;
}
}
private class MessageGroupData
{
[JsonProperty(PropertyName = "Messages")]
public List<string> Messages { get; set; }
[JsonProperty(PropertyName = "Group or Permission")]
public string GroupOrPerm { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
[JsonProperty(PropertyName = "Player Group or Permission State (In, NotIn)")]
public State State { get; set; }
[JsonProperty(PropertyName = "Enabled")]
public bool Enabled { get; set; }
}
private class PanelRegistration
{
public string Dock { get; set; }
public float Width { get; set; }
public int Order { get; set; }
public string BackgroundColor { get; set; }
}
private class Panel
{
public PanelText Text { get; set; }
public Hash<string, object> ToHash()
{
return new Hash<string, object>
{
[nameof(Text)] = Text.ToHash()
};
}
}
private abstract class PanelType
{
public bool Enabled { get; set; }
public string Color { get; set; }
public int Order { get; set; }
public float Width { get; set; }
public TypePadding Padding { get; set; }
public virtual Hash<string, object> ToHash()
{
return new Hash<string, object>
{
[nameof(Enabled)] = Enabled,
[nameof(Color)] = Color,
[nameof(Order)] = Order,
[nameof(Width)] = Width,
[nameof(Padding)] = Padding.ToHash(),
};
}
}
private class PanelText : PanelType
{
public string Text { get; set; }
public int FontSize { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public TextAnchor TextAnchor { get; set; }
public override Hash<string, object> ToHash()
{
Hash<string, object> hash = base.ToHash();
hash[nameof(Text)] = Text;
hash[nameof(FontSize)] = FontSize;
hash[nameof(TextAnchor)] = TextAnchor;
return hash;
}
}
private class TypePadding
{
public float Left { get; set; }
public float Right { get; set; }
public float Top { get; set; }
public float Bottom { get; set; }
public TypePadding(float left, float right, float top, float bottom)
{
Left = left;
Right = right;
Top = top;
Bottom = bottom;
}
public Hash<string, object> ToHash()
{
return new Hash<string, object>
{
[nameof(Left)] = Left,
[nameof(Right)] = Right,
[nameof(Top)] = Top,
[nameof(Bottom)] = Bottom
};
}
}
#endregion
}
}