C#:
using System.Collections.Generic;
using Oxide.Game.Rust.Cui;
using System.Linq;
using UnityEngine;
using System;
using Oxide.Core;
using System.Globalization;
//V1.0.7
// Fix for July update
namespace Oxide.Plugins {
[Info("InfoScreens", "Steenamaroo", "1.0.7", ResourceId = 75)]
[Description("Server info screens, with navigation.")]
class InfoScreens : RustPlugin {
Dictionary<ulong, int> users = new Dictionary<ulong, int>();
public Dictionary<string, Page> Pages = new Dictionary<string, Page>();
const string permAllowed = "infoscreens.show";
bool HasPermission(string id, string perm) => permission.UserHasPermission(id, perm);
void OnServerInitialized() {
permission.RegisterPermission(permAllowed, this);
if (!LoadConfigVariables()) {
Interface.Oxide.UnloadPlugin(Name);
return;
}
cmd.AddChatCommand($"{config.Global.CommandAlias}", this, "InfoScreen");
if (config.Global.NumberOfPages == 0) config.Global.NumberOfPages = 1;
for (int i = 1; i <= Mathf.Max(config.Global.NumberOfPages, config.Pages.Count);
i++) {
if (config.Pages.Count >= i) Pages.Add(config.Pages.ElementAt(i - 1).Key, config.Pages.ElementAt(i - 1).Value);
else if (!Pages.ContainsKey($"Page{i}")) Pages.Add($"Page{i}", DefaultPage());
}
foreach (var page in config.Pages.ToDictionary(x => x.Key, x => x.Value)) if (page.Value.ImageElements.Count == 0 && page.Value.TextElements.Count == 0) Pages[page.Key] = DefaultPage();
config.Pages = Pages;
SaveConfig(config);
foreach (var player in BasePlayer.activePlayerList) if (config.Global.PermaUIButton) ISPermaUI(player);
}
void Unload() {
foreach (BasePlayer player in BasePlayer.activePlayerList) DestroyMenu(player, true);
SaveData();
}
void OnPlayerConnected(BasePlayer player) {
if (player.IsReceivingSnapshot) {
timer.Once(1f, () => {
if (player?.net?.connection != null) OnPlayerConnected(player);
}
);
return;
}
if (config.Global.PermaUIButton) ISPermaUI(player);
if (config.Global.NeverAutoShow) return;
if (config.Global.OnlyShowOnce) {
if (!storedData.DisplayedTo.Contains(player.userID)) {
OpenUI(player);
storedData.DisplayedTo.Add(player.userID.Get());
}
}
else OpenUI(player);
}
void OnPlayerDisconnected(BasePlayer player) {
if (users.ContainsKey(player.userID)) DestroyMenu(player, true);
}
void OnPlayerDeath(BasePlayer player, HitInfo info) {
if (users.ContainsKey(player.userID)) DestroyMenu(player, false);
}
void DestroyMenu(BasePlayer player, bool all) {
if (all) CuiHelper.DestroyUi(player, "ISPermaUI");
CuiHelper.DestroyUi(player, "ISUI");
users.Remove(player.userID);
}
static BasePlayer FindPlayerByName(string name) {
BasePlayer result = null;
foreach (BasePlayer current in BasePlayer.activePlayerList) {
if (current.displayName.Equals(name, StringComparison.OrdinalIgnoreCase) || current.UserIDString.Contains(name, CompareOptions.OrdinalIgnoreCase) || current.displayName.Contains(name, CompareOptions.OrdinalIgnoreCase)) result = current;
}
return result;
}
[ChatCommand("infoscreen")]
void InfoScreen(BasePlayer player, string command, string[] args) {
if (args == null) return;
if (args.Length == 2 && args[0] == "ui") {
DestroyMenu(player, true);
if (args[1] == "on") ISPermaUI(player);
return;
}
if ((player.IsAdmin || HasPermission(player.UserIDString, permAllowed)) && args?.Length > 0) {
BasePlayer target = FindPlayerByName(args[0]);
if (target == null) {
SendReply(player, $"Target player {args[0]} not found.");
return;
}
else {
SendReply(player, $"Opened infoscreens for player {target.displayName}.");
if (args.Length == 2) {
if (config.Pages.ContainsKey(args[1])) ISUI(player, config.Pages.Keys.ToList().IndexOf(args[1]), 0);
else SendReply(player, $"No page found for '{args[1]}'.");
return;
}
else {
OpenUI(target);
return;
}
}
}
OpenUI(player);
}
void OpenUI(BasePlayer player) => ISUI(player, 0, 0);
[ConsoleCommand("ISWipe")]
private void ISWipe(ConsoleSystem.Arg arg) {
if (arg.Player() == null || arg.Player()?.IsAdmin == true) {
storedData.DisplayedTo.Clear();
SaveData();
Puts("InfoScreens displayed-to records have been cleared.");
}
}
[ConsoleCommand("ISRefreshUI")]
private void ISRefreshUI(ConsoleSystem.Arg arg) {
if (arg.Player() == null) return;
ISUI(arg.Player(), arg.GetInt(0), arg.GetInt(1));
}
void ISPermaUI(BasePlayer player) {
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel {
Image = {
Color = $"0.1 0.1 0.1 0"
}
, RectTransform = {
AnchorMin = "0.97 0.97", AnchorMax = "0.995 0.995"
}
, CursorEnabled = false
}
, "Overlay", "ISPermaUI");
elements.Add(new CuiButton {
Button = {
Command = "ISRefreshUI 0 0", Color = GetColour(config.Global.ButtonColour)
}
, RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, Text = {
Text = "i", FontSize = 11, Align = TextAnchor.MiddleCenter
}
}
, mainName);
CuiHelper.AddUi(player, elements);
}
void ISUI(BasePlayer player, int page, int subpage) {
DestroyMenu(player, false);
Dictionary<string, Page> VisiblePages = new Dictionary<string, Page>();
foreach (var storedpage in config.Pages) {
foreach (var group in permission.GetUserGroups(player.UserIDString)) if (storedpage.Value.VisibleTo.Split(',').Contains(group)) if (!VisiblePages.ContainsKey(storedpage.Key)) VisiblePages.Add(storedpage.Key, storedpage.Value);
}
if (VisiblePages.Count == 0) {
SendReply(player, "InfoScreens has no pages");
return;
}
users[player.userID] = page;
var elements = new CuiElementContainer();
var mainName = elements.Add(new CuiPanel {
Image = {
Color = $"0.1 0.1 0.1 {config.Global.GuiTransparency}"
}
, RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1"
}
, CursorEnabled = true
}
, "Overlay", "ISUI");
var pageInfo = VisiblePages.ElementAt(page);
int subPages = GetSubPages(pageInfo.Value);
foreach (var image in pageInfo.Value.ImageElements.Where(x => x.Value.ShowOnSubPages.Split(',').Contains(subpage.ToString()))) {
string[] pos = GetPosition(image.Key, image.Value);
elements.Add(new CuiElement {
Parent = "ISUI", Components = {
new CuiRawImageComponent {
Url = $"{image.Value.URL}" , FadeIn = 0.8f
}
, new CuiRectTransformComponent {
AnchorMin = $"{pos[0]} {pos[1]}", AnchorMax = $"{pos[2]} {pos[3]}"
}
}
}
);
}
foreach (var text in pageInfo.Value.TextElements.Where(x => x.Value.ShowOnSubPages.Split(',').Contains(subpage.ToString()))) {
string[] pos = GetPosition(text.Key, text.Value);
elements.Add(new CuiLabel {
Text = {
Text = $"{text.Value.Content}", FontSize = text.Value.FontSize, Color = GetColour(text.Value.FontColour), Align = GetAnchor(text.Key, text.Value)
}
, RectTransform = {
AnchorMin = $"{pos[0]} {pos[1]}", AnchorMax = $"{pos[2]} {pos[3]}"
}
}
, mainName);
}
if (config.Global.SideNav) elements.Add(new CuiButton {
Button = {
Color = $"0 0 0 {config.Global.GuiTransparency}"
}
, RectTransform = {
AnchorMin = $"0 0", AnchorMax = $"0.1 1"
}
, Text = {
Text = string.Empty
}
}
, mainName);
else elements.Add(new CuiButton {
Button = {
Color = $"0 0 0 {config.Global.GuiTransparency}"
}
, RectTransform = {
AnchorMin = $"0 0.965", AnchorMax = $"1 1"
}
, Text = {
Text = string.Empty
}
}
, mainName);
int num = (VisiblePages.Count * 2) + 1;
double unit = 1.0 / num;
for (int i = 1; i <= VisiblePages.Count; i++) {
int fontsize = VisiblePages.Count > 8 ? 12 : 18;
string bc = i - 1 == page ? GetColour(config.Global.ButtonColourSelected) : GetColour(config.Global.ButtonColour);
if (config.Global.SideNav) elements.Add(new CuiButton {
Button = {
Command = $"ISRefreshUI {i - 1} 0", Color = bc
}
, RectTransform = {
AnchorMin = $"0 {1-(unit * ((i * 2) - 0.5))}", AnchorMax = $"0.1 {1-(unit * ((i * 2) - 1))}"
}
, Text = {
Text = $"{VisiblePages.ElementAt(i - 1).Key}", FontSize = fontsize, Align = TextAnchor.MiddleCenter
}
}
, mainName);
else elements.Add(new CuiButton {
Button = {
Command = $"ISRefreshUI {i - 1} 0", Color = bc
}
, RectTransform = {
AnchorMin = $"{unit * ((i * 2) - 1)} 0.965", AnchorMax = $"{unit * (i * 2)} 1"
}
, Text = {
Text = $"{VisiblePages.ElementAt(i - 1).Key}", FontSize = fontsize, Align = TextAnchor.MiddleCenter
}
}
, mainName);
}
if (subpage < subPages) elements.Add(new CuiButton {
Button = {
Command = $"ISRefreshUI {page} {subpage + 1}", Color = GetColour(config.Global.ButtonColour)
}
, RectTransform = {
AnchorMin = "0.8 0.01", AnchorMax = "0.895 0.05"
}
, Text = {
Text = "->", FontSize = 24, Align = TextAnchor.MiddleCenter
}
}
, mainName);
if (subpage > 0) elements.Add(new CuiButton {
Button = {
Command = $"ISRefreshUI {page} {subpage - 1}", Color = GetColour(config.Global.ButtonColour)
}
, RectTransform = {
AnchorMin = "0.105 0.01", AnchorMax = "0.2 0.05"
}
, Text = {
Text = "<-", FontSize = 24, Align = TextAnchor.MiddleCenter
}
}
, mainName);
elements.Add(new CuiButton {
Button = {
Command = "CloseIS", Color = GetColour(config.Global.ButtonColour)
}
, RectTransform = {
AnchorMin = "0.97 0.97", AnchorMax = "0.995 0.995"
}
, Text = {
Text = "X", FontSize = 11, Align = TextAnchor.MiddleCenter
}
}
, mainName);
CuiHelper.AddUi(player, elements);
}
public int GetSubPages(Page page) {
string source = string.Empty;
foreach (var image in page.ImageElements) source += $",{image.Value.ShowOnSubPages}";
foreach (var text in page.TextElements) source += $",{text.Value.ShowOnSubPages}";
string[] subs = source.Split(',');
int maxsub = 0;
foreach (var sub in subs) if (sub.IsNumeric() && Convert.ToInt16(sub) > maxsub) maxsub = Convert.ToInt16(sub);
return maxsub;
}
public bool IsFloat(string input) {
float num;
return float.TryParse(input, out num);
}
public string[] GetPosition(string name, Element element) {
var LR = element.PosLeftToRight.Split(',');
var BT = element.PosBottomToTop.Split(',');
if (BT == null || LR == null || BT.Length != 2 || LR.Length != 2 || !IsFloat(BT[0]) || !IsFloat(BT[1]) || !IsFloat(LR[0]) || !IsFloat(LR[1])) {
Puts($"Error in config for {name}.");
return new string[] {
"0", "1", "0", "1"
}
;
}
if (!element.GoBehindNav) if (config.Global.SideNav) LR[0] = (float.Parse(LR[0]) + 0.1f).ToString();
else BT[1] = ((float.Parse(BT[1]) / 100f) * 96.5).ToString();
return new string[] {
LR[0], BT[0], LR[1], BT[1]
}
;
}
public TextAnchor GetAnchor(string name, Text text) {
int tAnchor = text.AlignTopMiddleBottom.ToLower() == "top" ? 0 : text.AlignTopMiddleBottom.ToLower() == "middle" ? 3 : 6;
tAnchor += text.AlignLeftMiddleRight.ToLower() == "middle" ? 1 : text.AlignLeftMiddleRight.ToLower() == "right" ? 2 : 0;
return (TextAnchor)tAnchor;
}
string GetColour(string colour) {
var cols = colour.Replace(" ", "").Split(',');
if (cols == null || cols.Length != 4 || !IsFloat(cols[0]) || !IsFloat(cols[1]) || !IsFloat(cols[2]) || !IsFloat(cols[3])) return "0, 0, 0, 1";
for (int i = 0; i < 3; i++) cols[i] = (float.Parse(cols[i]) / 255).ToString();
return $"{cols[0]} {cols[1]} {cols[2]} {cols[3]}";
}
[ConsoleCommand("CloseIS")]
private void CloseIS(ConsoleSystem.Arg arg) {
if (arg.Player() == null) return;
DestroyMenu(arg.Player(), false);
}
#region Config
private ConfigData config;
public class ConfigData {
public Global Global = new Global();
public Dictionary<string, Page> Pages = new Dictionary<string, Page>();
}
public class Global {
public bool PermaUIButton = false;
public bool SideNav = false;
public bool OnlyShowOnce = false;
public bool NeverAutoShow = false;
public int NumberOfPages = 4;
public double GuiTransparency = 0.95;
public string ButtonColour = "0,100,0,1";
public string ButtonColourSelected = "0,200,0,1";
public string CommandAlias = "is";
}
public class Page {
public Dictionary<string, Image> ImageElements = new Dictionary<string, Image>();
public Dictionary<string, Text> TextElements = new Dictionary<string, Text>();
public string VisibleTo = "default,somegroup";
}
public Page DefaultPage() => new Page() {
ImageElements = new Dictionary<string, Image>() {
{
"BackGround", new Image ()
}
}
, TextElements = new Dictionary<string, Text>() {
{
"Title", new Text()
}
, {
"Content", new Text() {
PosBottomToTop = "0.0,0.5"
}
}
,
}
}
;
public class Element {
public bool GoBehindNav = false;
public string ShowOnSubPages = "0";
public string PosBottomToTop = "0.0,1.0";
public string PosLeftToRight = "0.0,1.0";
}
public class Text : Element {
public string Content = "Default Text";
public int FontSize = 16;
public string AlignTopMiddleBottom = "top";
public string AlignLeftMiddleRight = "middle";
public string FontColour = "255,255,255,1";
}
public class Image : Element {
public string URL = string.Empty ;
}
private bool LoadConfigVariables() {
try {
config = Config.ReadObject<ConfigData>();
}
catch {
return false;
}
SaveConfig(config);
return true;
}
protected override void LoadDefaultConfig() {
Puts("Creating new config file.");
var config = new ConfigData();
SaveConfig(config);
}
void SaveConfig(ConfigData config) => Config.WriteObject(config, true);
#endregion
#region Data
StoredData storedData;
class StoredData {
public List<ulong> DisplayedTo = new List<ulong>();
}
void Loaded() {
storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("InfoScreens");
Interface.Oxide.DataFileSystem.WriteObject("InfoScreens", storedData);
}
void SaveData()=>Interface.Oxide.DataFileSystem.WriteObject("InfoScreens", storedData);
#endregion
}
}