Иконка ресурса

FREE StaticLootables : 2.9.0 2.9.0

Нет прав для скачивания
C#:
using Facepunch;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using ProtoBuf;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("StaticLootables", "Raul-Sorin Sorban", "2.9.0")]
    [Description("Loot containers that aren't normally supposed to be looted.")]
    public class StaticLootables : RustPlugin {
        public static StaticLootables Instance {
            get;
            private set;
        }
        public System.Random Randomizer {
            get;
            set;
        }
        = new System.Random();
        public System.Random GetSeededRandomizer(int seed) {
            return new System.Random(seed);
        }
        public Dictionary<string, string> PanelTypes {
            get;
            set;
        }
        = new Dictionary<string, string> {
            ["generic"]
            = "Generic", ["genericsmall"] = "Generic - Small", ["generic_large"] = "Generic - Large", ["generic_resizable"] = "Generic - Resizable", ["locker"] = "Locker", ["lantern"] = "Lantern", ["mailboxcontents"] = "Mailbox Contents", ["photoframe"] = "Photo Frame", ["reclaim"] = "Reclaim", ["skulltrophy"] = "Skull Trophy", ["toolcupboard"] = "Tool Cupboard"
        }
        ;
        public List<string> PanelTypesList {
            get;
            set;
        }
        = new List<string>();
#region Permissions
        public const string AdminPerm = "staticlootables.admin";
        public const string EditorPerm = "staticlootables.editor";
        public void RegisterPermissions() {
            permission.RegisterPermission(AdminPerm, this);
            permission.RegisterPermission(EditorPerm, this);
        }
#endregion
#region Plugins
        [PluginReference]
        Plugin ImageLibrary;
        [PluginReference]
        Plugin QuickSort;
        [PluginReference]
        Plugin ZoneManager;
        [PluginReference]
        Plugin LootablesExt;
        public void RefreshPlugins() {
            if (ImageLibrary == null || !ImageLibrary.IsLoaded) {
                ImageLibrary = plugins.Find("ImageLibrary");
                ImageLibrary?.Load();
            }
            if (QuickSort == null || !QuickSort.IsLoaded) {
                QuickSort = plugins.Find("QuickSort");
                QuickSort?.Load();
            }
            if (ZoneManager == null || !ZoneManager.IsLoaded) {
                ZoneManager = plugins.Find("ZoneManager");
                ZoneManager?.Load();
            }
            if (LootablesExt == null || !LootablesExt.IsLoaded) {
                LootablesExt = plugins.Find("LootablesExt");
                LootablesExt?.Load();
            }
        }
#endregion
#region Raycast
        private bool TryGetClosestRayPoint(BasePlayer player, out object closestEnt, out Vector3 closestHitpoint) {
            var hits = Physics.RaycastAll(player.eyes.HeadRay(), Config.Distance);
            var closestdist = 999999f;
            closestHitpoint = player.eyes.position;
            closestEnt = false;
            foreach (var hit in hits) {
                var colliderName = hit.collider.name.ToLower().Trim();
                if (hit.distance < closestdist && !colliderName.Contains("preventbuilding") && !colliderName.Contains("prevent_building") && !colliderName.Contains("prevent_movement") && !colliderName.Contains("terrain") && !colliderName.Contains("player.prefab")) {
                    closestdist = hit.distance;
                    closestEnt = hit.collider;
                    closestHitpoint = hit.point;
                }
            }
            hits = null;
            if (closestEnt is bool) return false;
            return true;
        }
#endregion
#region CUI
        public const string CUIInteractionName = "stlootable";
        public const string CUIEditorInteractionName = "stlootableeditorinteraction";
        public const string CUIEditorName = "stlootableeditor";
        public const string CUICodeLockInputName = "stlootableclin";
        public const string CUIPinAppendCommand = "staticlootables.pinappend";
        public const string CUIPinApplyCommand = "staticlootables.pinapply";
        public const string CUIPinUndoCommand = "staticlootables.pinundo";
        public const string DamageColor = "1 0.3 0.3 0.8";
        public const string HackingColor = "0.5 0.8 0.3 0.8";
        public Dictionary<BasePlayer, PlayerInteraction?> CUIPlayers {
            get;
            set;
        }
        = new Dictionary<BasePlayer, PlayerInteraction?>(800);
        public Dictionary<BasePlayer, TimeSince> TimedPlayers {
            get;
            set;
        }
        = new Dictionary<BasePlayer, TimeSince>(800);
        public Dictionary<BasePlayer, Vector3> PositionCache {
            get;
            set;
        }
        = new Dictionary<BasePlayer, Vector3>(800);
        public Dictionary<BasePlayer, string> PinCache {
            get;
            set;
        }
        = new Dictionary<BasePlayer, string>(800);
        public Dictionary<BasePlayer, RootData.Lootable> LootingPlayers {
            get;
            set;
        }
        = new Dictionary<BasePlayer, RootData.Lootable>(800);
        public List<BasePlayer> DrawnUI {
            get;
            set;
        }
        = new List<BasePlayer>();
        public const int ProcessorCount = 1;
        public struct PlayerInteraction {
            public RootConfig.Interaction Interaction {
                get;
                set;
            }
            public RootLock Lock {
                get;
                set;
            }
            public RootHack Hack {
                get;
                set;
            }
            public RootData.Lootable Lootable {
                get;
                set;
            }
            public bool IsProcessingCommand {
                get;
                set;
            }
            public bool IsLoadingTimer {
                get;
                set;
            }
            public DateTime Timer {
                get;
                set;
            }
            public float TimerTime => (float)(DateTime.Now - Timer).TotalSeconds;
        }
        public void DrawInteraction(BasePlayer player, RootConfig.Interaction interaction, RootConfig.LootableDefinition definition, RootData.Lootable lootable, bool transition = true, bool enableDot = true, bool reset = true) {
            // UndrawInteraction(player, reset);
            var container = new CuiElementContainer();
            var background = container.Add(new CuiPanel {
                Image = {
                    Color = $"0 0 0 0"
                }
                , RectTransform = {
                    AnchorMin = "0.36 0.36", AnchorMax = "0.64 0.738"
                }
                , CursorEnabled = false
            }
            , "Hud", CUIInteractionName, CUIInteractionName);
            var offset = "0 -10";
            var fade = transition ? 0.3f : 0f;
            var @lock = lootable != null && lootable.Lock != null ? lootable.Lock : null;
            var hack = lootable != null && lootable.Hack != null ? lootable.Hack : null;
            var i = default(PlayerInteraction?);
            if (!CUIPlayers.ContainsKey(player)) CUIPlayers.Add(player, i = new PlayerInteraction {
                Interaction = interaction, Lock = @lock, Lootable = lootable
            }
            );
            else i = CUIPlayers[player];
            if (i == null) return;
            if (enableDot) container.Add(new CuiElement {
                Parent = background, FadeOut = fade, Components = {
                    Death.GetRawImage(Config.Urls.DotUrl, fade : fade), new CuiRectTransformComponent {
                        AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = offset, OffsetMax = offset
                    }
                }
            }
            );
            if (Config.ShadowOpacity != 0f) container.Add(new CuiElement {
                Parent = background, FadeOut = fade, Components = {
                    Death.GetRawImage(Config.Urls.ShadowUrl, color : $"1 1 1 {Config.ShadowOpacity}", fade : fade), new CuiRectTransformComponent {
                        AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = offset, OffsetMax = offset
                    }
                }
            }
            );
            container.Add(new CuiElement {
                Parent = background, FadeOut = fade, Components = {
                    Death.GetRawImage(i.Value.IsProcessingCommand ? Config.Urls.LoadingUrl : lootable != null && lootable.IsBusy(player) ? Config.Urls.BusyUrl : (@lock == null ? (hack == null ? interaction.Icon : hack.IsHacking ? Config.Urls.HackingUrl : Config.Urls.HackUrl) : Config.Urls.LockUrl), fade : fade), new CuiRectTransformComponent {
                        AnchorMin = "0.46 0.53", AnchorMax = "0.54 0.63", OffsetMin = offset, OffsetMax = offset
                    }
                }
            }
            );
            container.Add(new CuiLabel {
                Text = {
                    Text = $"<b>{(i.Value.IsProcessingCommand ? Config.CommandName : lootable != null && lootable.IsBusy(player) ? $" {
                        Config.BusyName
                    }
                    " : (@lock == null ? hack == null ? interaction.Text : hack.IsHacking ? Config.HackingName : Config.HackName : Config.LockName))}</b>".ToUpper(), FadeIn = fade, FontSize = 13, Font = "robotocondensed-regular.ttf", Align = TextAnchor.LowerCenter
                }
                , RectTransform = {
                    AnchorMin = $"0 0.435", AnchorMax = $"1 1"
                }
            }
            , background);
            if (lootable != null) {
                if (lootable.IsLocked() && definition != null && definition.Lock != null) {
                    var value = lootable.Lock.Health;
                    var total = definition.Lock.Health * Config.LootableHealthMultiplier;
                    var count = lootable.Contents.Count;
                    DrawInteractionBar(background, container, value, total, fade, count, definition, lootable);
                }
                else if (lootable.Hack != null && definition != null && definition.Hack != null) {
                    var time = lootable.GetHackTime();
                    var totalTime = lootable.GetTotalHackingTime();
                    if (lootable.IsHacking()) {
                        DrawInteractionBar(background, container, totalTime - time, totalTime, fade, -1, definition, textOne : $"{totalTime - time:0}s", textTwo : $"Please wait...", hackMode : true);
                    }
                }
            }
            if (i != null && i.Value.IsLoadingTimer) {
                var span = DateTime.Now - i.Value.Timer;
                var value = definition.Timer - (float)span.TotalSeconds;
                var total = definition.Timer;
                DrawInteractionBar(background, container, value, total, fade, 0, definition, textOne : $"{value:0}s", textTwo : "", hackMode : true);
            }
            CuiHelper.AddUi(player, container);
            DrawnUI.Add(player);
        }
        public void UndrawInteraction(BasePlayer player, bool reset = true) {
            if (reset && !CUIPlayers.ContainsKey(player)) return;
            if (DrawnUI.Contains(player)) {
                for (int i = 0; i < ProcessorCount; i++) {
                    CuiHelper.DestroyUi(player, CUICodeLockInputName);
                }
                for (int i = 0; i < ProcessorCount; i++) {
                    CuiHelper.DestroyUi(player, CUIInteractionName);
                }
                for (int i = 0; i < ProcessorCount; i++) {
                    CuiHelper.DestroyUi(player, CUIEditorInteractionName);
                }
                for (int i = 0; i < ProcessorCount; i++) {
                    CuiHelper.DestroyUi(player, CUIEditorName);
                }
                DrawnUI.Remove(player);
            }
            if (reset) CUIPlayers.Remove(player);
        }
        public void DrawInteractionBar(string background, CuiElementContainer container, float value, float total, float fade, int count = -1, RootConfig.LootableDefinition definition = null, RootData.Lootable lootable = null, string textOne = null, string textTwo = null, bool hackMode = false) {
            container.Add(new CuiLabel {
                Text = {
                    Text = textOne == null ? $"<b>{value:n0} / {total:n0}</b>".ToUpper() : textOne, FadeIn = fade, FontSize = 10, Font = "robotocondensed-regular.ttf", Align = TextAnchor.UpperRight
                }
                , RectTransform = {
                    AnchorMin = "0.3 0.9", AnchorMax = "0.7 1"
                }
            }
            , background);
            var bar = container.Add(new CuiPanel {
                Image = {
                    Color = hackMode ? HackingColor : DamageColor, FadeIn = fade
                }
                , RectTransform = {
                    AnchorMin = "0.3 0.925", AnchorMax = "0.7 0.95"
                }
                , CursorEnabled = false
            }
            , background);
            container.Add(new CuiPanel {
                Image = {
                    Color = $"1 1 1 1", FadeIn = fade
                }
                , RectTransform = {
                    AnchorMin = "0 0", AnchorMax = $"{Scale(value, 0f, total, 0f, 1f)} 1"
                }
                , CursorEnabled = false
            }
            , bar);
            if ((definition != null && Instance.Config.ShowLockedLootableApproximateCount) || textTwo != null) {
                var randomizer = GetSeededRandomizer(lootable == null ? definition.InteractionIndex : (int)(lootable.Position.x + lootable.Position.y + lootable.Position.z + definition.InteractionIndex));
                container.Add(new CuiLabel {
                    Text = {
                        Text = textTwo == null ? $"~{randomizer.Next(count - 2, count + 2):n0} items appx.".ToUpper() : textTwo, FadeIn = fade, FontSize = 10, Font = "robotocondensed-regular.ttf", Align = TextAnchor.UpperLeft
                    }
                    , RectTransform = {
                        AnchorMin = "0.3 0.9", AnchorMax = "0.7 1"
                    }
                }
                , background);
                randomizer = null;
            }
        }
        private void DrawCodeLockInput(BasePlayer player) {
            if (!PinCache.ContainsKey(player)) PinCache.Add(player, string.Empty);
            for (int i = 0; i < 5; i++) {
                CuiHelper.DestroyUi(player, CUICodeLockInputName);
            }
            var container = new CuiElementContainer();
            var background = container.Add(new CuiPanel {
                Image = {
                    Color = $"0.3 0.3 0.3 0.9", Material = "assets/content/ui/uibackgroundblur.mat"
                }
                , RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1"
                }
                , CursorEnabled = true
            }
            , "Hud", CUICodeLockInputName, CUICodeLockInputName);
            container.Add(new CuiButton {
                Button = {
                    Command = $"{CUIPinApplyCommand}", Color = "0 0 0 0"
                }
                , Text = {
                    Text = string.Empty
                }
                , RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1"
                }
            }
            , background);
            var panel = container.Add(new CuiPanel {
                Image = {
                    Color = $"0 0 0 0"
                }
                , RectTransform = {
                    AnchorMin = "0.425 0.35", AnchorMax = "0.575 0.7"
                }
                , CursorEnabled = false
            }
            , background);
            container.Add(new CuiLabel {
                Text = {
                    Text = $"<b>{Config.CodeInputTitle}</b>".ToUpper(), FontSize = 18, Font = "robotocondensed-regular.ttf", Align = TextAnchor.UpperCenter
                }
                , RectTransform = {
                    AnchorMin = $"0 0.75", AnchorMax = $"1 0.985"
                }
            }
            , panel);
            var pinText = "";
            foreach (var number in PinCache[player]) pinText += $"{number}  ";
            var pin = container.Add(new CuiPanel {
                Image = {
                    Color = $"0 0 0 0.5"
                }
                , RectTransform = {
                    AnchorMin = "0.25 0.78", AnchorMax = "0.75 0.875"
                }
                , CursorEnabled = false
            }
            , panel);
            container.Add(new CuiLabel {
                Text = {
                    Text = $"<b>{pinText.Trim()}</b>".ToUpper(), Color = "1 1 1 0.7", FontSize = 18, Font = "robotocondensed-regular.ttf", Align = TextAnchor.MiddleCenter
                }
                , RectTransform = {
                    AnchorMin = $"0 0", AnchorMax = $"1 1"
                }
            }
            , pin);
#region Buttons
            var offset = 0f;
            var horizontalOffset = 12f;
            var spacing = 37.5f;
            var count = 9;
            for (int i = 0; i < 3; i++) {
                container.Add(new CuiButton {
                    Button = {
                        Command = $"{CUIPinAppendCommand} {count - 2}", Color = "0.8 0.8 0.8 0.35"
                    }
                    , Text = {
                        Text = $"<b>{count - 2}</b>", Align = TextAnchor.MiddleCenter, Color = "0.15 0.15 0.15 0.7", Font = "robotocondensed-regular.ttf", FontSize = 19
                    }
                    , RectTransform = {
                        AnchorMin = "0.2 0.62", AnchorMax = "0.35 0.75", OffsetMin = $"{horizontalOffset} {offset}", OffsetMax = $"{horizontalOffset} {offset}"
                    }
                }
                , panel);
                container.Add(new CuiButton {
                    Button = {
                        Command = $"{CUIPinAppendCommand} {count - 1}", Color = "0.8 0.8 0.8 0.35"
                    }
                    , Text = {
                        Text = $"<b>{count - 1}</b>", Align = TextAnchor.MiddleCenter, Color = "0.15 0.15 0.15 0.7", Font = "robotocondensed-regular.ttf", FontSize = 19
                    }
                    , RectTransform = {
                        AnchorMin = "0.2 0.62", AnchorMax = "0.35 0.75", OffsetMin = $"{horizontalOffset + 32} {offset}", OffsetMax = $"{horizontalOffset + 32} {offset}"
                    }
                }
                , panel);
                container.Add(new CuiButton {
                    Button = {
                        Command = $"{CUIPinAppendCommand} {count}", Color = "0.8 0.8 0.8 0.35"
                    }
                    , Text = {
                        Text = $"<b>{count}</b>", Align = TextAnchor.MiddleCenter, Color = "0.15 0.15 0.15 0.7", Font = "robotocondensed-regular.ttf", FontSize = 19
                    }
                    , RectTransform = {
                        AnchorMin = "0.2 0.62", AnchorMax = "0.35 0.75", OffsetMin = $"{horizontalOffset + 64} {offset}", OffsetMax = $"{horizontalOffset + 64} {offset}"
                    }
                }
                , panel);
                offset -= spacing;
                count -= 3;
            }
            container.Add(new CuiButton {
                Button = {
                    Command = $"{CUIPinAppendCommand} 0", Color = "0.8 0.8 0.8 0.35"
                }
                , Text = {
                    Text = $"<b>0</b>", Align = TextAnchor.MiddleCenter, Color = "0.15 0.15 0.15 0.7", Font = "robotocondensed-regular.ttf", FontSize = 19
                }
                , RectTransform = {
                    AnchorMin = "0.2 0.62", AnchorMax = "0.515 0.75", OffsetMin = $"{horizontalOffset} {offset}", OffsetMax = $"{horizontalOffset} {offset}"
                }
            }
            , panel);
            var acceptButton = container.Add(new CuiButton {
                Button = {
                    Command = $"{CUIPinApplyCommand}", Color = "0.2 0.85 0.2 0.35"
                }
                , Text = {
                    Text = string.Empty, Align = TextAnchor.MiddleCenter, Color = "0.15 0.15 0.15 0.7", Font = "robotocondensed-regular.ttf", FontSize = 19
                }
                , RectTransform = {
                    AnchorMin = "0.535 0.62", AnchorMax = "0.68 0.75", OffsetMin = $"{horizontalOffset} {offset}", OffsetMax = $"{horizontalOffset} {offset}"
                }
            }
            , panel);
            container.Add(new CuiElement {
                Parent = acceptButton, Components = {
                    Death.GetRawImage(Config.Urls.CheckUrl, color : "0.15 0.15 0.15 0.7"), new CuiRectTransformComponent {
                        AnchorMin = "0.2 0.22", AnchorMax = "0.8 0.78"
                    }
                }
            }
            );
            offset -= spacing;
            container.Add(new CuiButton {
                Button = {
                    Command = $"{CUIPinUndoCommand}", Color = "0.5 0.5 0.5 0.35"
                }
                , Text = {
                    Text = $"<b>C</b>", Align = TextAnchor.MiddleCenter, Color = "1 1 1 0.4", Font = "robotocondensed-regular.ttf", FontSize = 19
                }
                , RectTransform = {
                    AnchorMin = "0.2 0.62", AnchorMax = "0.68 0.75", OffsetMin = $"{horizontalOffset} {offset}", OffsetMax = $"{horizontalOffset} {offset}"
                }
            }
            , panel);
#endregion
            CuiHelper.AddUi(player, container);
            if (!CUIPlayers.ContainsKey(player)) CUIPlayers.Add(player, new PlayerInteraction());
        }
        public bool IsLootingLootable(BasePlayer player, RootData.Lootable lootable) {
            if (!CUIPlayers.ContainsKey(player)) return false;
            return CUIPlayers[player]?.Lootable == lootable;
        }
        [ConsoleCommand(CUIPinAppendCommand)]
        private void PinAppendCommand(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            if (PinCache[player].Length >= 4) PinCache[player] = string.Empty;
            PinCache[player] += arg.Args[0];
            DrawCodeLockInput(player);
        }
        [ConsoleCommand(CUIPinApplyCommand)]
        private void PinApplyCommand(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            var interaction = CUIPlayers[player];
            if (string.IsNullOrEmpty(PinCache[player]) || PinCache[player].Length < 4) {
                UndrawInteraction(player);
                PinCache[player] = string.Empty;
                return;
            }
            if (PinCache[player] == interaction?.Lootable.Hack.Code) {
                var definition = interaction?.Lootable.GetDefinition();
                var interactionDefinition = Config.Interactions[definition.InteractionIndex];
                PlayerLootContainer(player, definition, interaction?.Lootable, interactionDefinition, definition.Panel);
            }
            else {
                player.ChatMessage($"Wrong code for that static lootable container.");
            }
            PinCache[player] = string.Empty;
            UndrawInteraction(player);
        }
        [ConsoleCommand(CUIPinUndoCommand)]
        private void PinUndoCommand(ConsoleSystem.Arg arg) {
            var player = arg.Player();
            if (player == null) return;
            if (!string.IsNullOrEmpty(PinCache[player])) PinCache[player] = PinCache[player].Substring(0, PinCache[player].Length - 1);
            DrawCodeLockInput(player);
        }
#endregion
#region Override
        public class Death {
            public static string GetImage(string url, bool isPng = true, ulong imageId = 0) {
                try {
                    var name = GetStringChecksum(url);
                    if (string.IsNullOrEmpty(url)) return string.Empty;
                    if ((bool)Instance.ImageLibrary.Call("HasImage", name, imageId)) {
                        var success = Instance.ImageLibrary.Call("GetImage", name, imageId);
                        return !isPng ? null : (string)success;
                    }
                    else {
                        Instance.ImageLibrary.Call("AddImage", url, name, imageId);
                        return !isPng ? url : null;
                    }
                }
                catch {
                    Instance.RefreshPlugins();
                }
                return string.Empty;
            }
            public static CuiRawImageComponent GetRawImage(string url, ulong skin = 0, string color = "", float fade = 0.3f) {
                var _url = GetImage(url, isPng : false, imageId : skin);
                var _png = GetImage(url, imageId : skin);
                return new CuiRawImageComponent {
                    Url = _url, Png = _png, Color = color, FadeIn = fade
                }
                ;
            }
        }
        public static string GetStringChecksum(string value) {
            if (value.Length <= 3) return null;
            using (var md5 = MD5.Create()) {
                var hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(value));
                return BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
            }
        }
        private void OnServerInitialized() {
            Instance = this;
            RegisterPermissions();
            timer.Every(20, () => {
                ServerMgr.Instance.StartCoroutine(DoRefillingCalculations());
            }
            );
            LoadContainer();
            Log($"Initialized {Config.Definitions.Count:n0} lootables and {Data.Container.ItemContainer.itemList.Count:n0} persistent container(s). Poggers.");
            CreateBehaviour();
            foreach (var panel in PanelTypes) {
                PanelTypesList.Add(panel.Key);
            }
        }
        private void Loaded() {
            RefreshPlugins();
            if (ConfigFile == null) ConfigFile = new Core.Configuration.DynamicConfigFile($"{Manager.ConfigPath}/{Name}.json");
            if (DataFile == null) DataFile = Interface.Oxide.DataFileSystem.GetFile($"{Name}_data");
            if (!ConfigFile.Exists()) {
                ConfigFile.WriteObject(Config ?? (Config = new RootConfig()));
            }
            else {
                Config = ConfigFile.ReadObject<RootConfig>();
            }
            if (DataFile.Exists()) Data = DataFile.ReadObject<RootData>();
            else Data = new RootData();
            if (Instance == null) Instance = this;
        }
        private void Unload() {
            foreach (var player in CUIPlayers.ToArray()) {
                UndrawInteraction(player.Key);
                player.Key.inventory.loot.Clear();
                player.Key.inventory.loot.SendImmediate();
            }
            foreach (var player in Editors) {
                UndrawEditor(player.Key, false);
                UndrawEditorInteraction(player.Key);
            }
            foreach (var lootable in Data.Lootables) {
                lootable.ClearContainer();
            }
            Data.Lootables.Clear();
            Data.Container.ItemContainer?.Kill();
            ClearBehaviour();
            Instance = null;
        }
        private void OnServerSave() {
            SaveContainer();
            ConfigFile.WriteObject(Config ?? (Config = new RootConfig()));
            DataFile.WriteObject(Data ?? (Data = new RootData()));
        }
        public void DoPlayerInput(BasePlayer player, InputState input) {
            if (Config == null || Instance == null) return;
            try {
                if (Config.AsyncMode) {
                    if (!CoroutineBuffer.ContainsKey(player.userID)) CoroutineBuffer.Add(player.userID, true);
                    else if (CoroutineBuffer[player.userID] && !input.WasJustPressed(BUTTON.USE) && !input.WasJustPressed(BUTTON.RELOAD)) return;
                    CoroutineBuffer[player.userID] = true;
                    player.StartCoroutine(DoPlayerInputCoroutine(player, input));
                }
                else {
                    var loot = (RootData.Lootable)null;
                    if (LootingPlayers.TryGetValue(player, out loot) && loot.TimeSinceDistanceCheck >= 0.5f) {
                        if (Vector3.Distance(player.eyes.position, PositionCache[player]) > Config.Distance) {
                            player.inventory.loot.Clear();
                            player.inventory.loot.SendImmediate();
                        }
                        loot.TimeSinceDistanceCheck = 0;
                    }
                    object closestEnt;
                    Vector3 closestHitpoint;
                    if (!TryGetClosestRayPoint(player, out closestEnt, out closestHitpoint)) {
                        if (CUIPlayers.ContainsKey(player)) {
                            var i = CUIPlayers[player].GetValueOrDefault();
                            i.Timer = DateTime.Now;
                            i.IsLoadingTimer = false;
                            i.Lootable?.CancelHack();
                            CUIPlayers[player] = i;
                        }
                        UndrawEditorInteraction(player);
                        UndrawInteraction(player);
                        return;
                    }
                    var obj = (closestEnt as Collider)?.gameObject;
                    if (closestEnt == null || obj == null) return;
                    var name = obj.transform.GetRecursiveName().ToLower();
                    if (IsInEditMode(player)) {
                        if (input.WasJustPressed(BUTTON.RELOAD)) {
                            input.SwallowButton(BUTTON.RELOAD);
                            var editor = GetOrCreateEditor(player);
                            if (!editor.IsEditing) DrawEditor(player, EditModes.Settings);
                        }
                        if (!EditorInteractionPlayers.ContainsKey(player) || (EditorInteractionPlayers.ContainsKey(player) && EditorInteractionPlayers[player] != obj.transform)) {
                            if (!EditorInteractionPlayers.ContainsKey(player)) EditorInteractionPlayers.Add(player, obj.transform);
                            else EditorInteractionPlayers[player] = obj.transform;
                            DrawEditorInteraction(player, obj.transform);
                        }
                        if (input.WasJustPressed(BUTTON.USE)) {
                            input.SwallowButton(BUTTON.USE);
                            var editor = GetOrCreateEditor(player);
                            var definition = GetDefinition(obj.transform);
                            Editor.StartEdit(definition ?? new RootConfig.LootableDefinition(obj.transform.name.Split(' ')[0].ToLower(), 2, new List<RootLootableItemDefinition>()), editor.EditingDefinition);
                            editor.Transform = obj.transform;
                            DrawEditor(player);
                        }
                    }
                    else {
                        if (Config.MiddleMouseInfo && input.WasJustPressed(BUTTON.FIRE_THIRD) && permission.UserHasPermission(player.UserIDString, AdminPerm) && !player.IsHoldingEntity<BaseEntity>()) {
                            input.SwallowButton(BUTTON.FIRE_THIRD);
                            var ids = ZoneManager?.Call<string[]>("GetPlayerZoneIDs", player) ?? new string[0];
                            player.ChatMessage($"<size=10>Looking at:</size>\n<color=orange>{name}</color>\n" + $"<size=10>Zone(s) [{ids.Length:n0}]:</size>\n<color=orange>{(ids.Length == 0 ? "-" : string.Join(", ", ids))}</color>");
                            return;
                        }
                        var farAway = Vector3.Distance(closestHitpoint, player.transform.position) > Config.Distance;
                        var definition = GetDefinition(obj);
                        var interaction = definition == null ? null : Config.Interactions[definition.InteractionIndex];
                        var lootable = GetLootable(player, obj, definition, false);
                        var playerInteraction = !CUIPlayers.ContainsKey(player) ? null : CUIPlayers[player];
                        if (definition != null && definition.HasTimer() && lootable == null) lootable = GetLootable(player, obj, definition, true);
                        if (lootable != null && !lootable.IsLocked() && definition.HasTimer()) {
                            if (playerInteraction == null && !player.inventory.loot.IsLooting()) {
                                DrawInteraction(player, interaction, definition, lootable, true, reset : false);
                            }
                            var val = playerInteraction.GetValueOrDefault();
                            if (input.IsDown(BUTTON.USE)) {
                                if (!PositionCache.ContainsKey(player)) PositionCache.Add(player, closestHitpoint);
                                else PositionCache[player] = closestHitpoint;
                                if (input.WasJustPressed(BUTTON.USE)) {
                                    val.Timer = DateTime.Now;
                                    val.IsLoadingTimer = true;
                                    CUIPlayers[player] = val;
                                    DrawInteraction(player, interaction, definition, lootable, true, reset : false);
                                }
                                else if (val.IsLoadingTimer && val.TimerTime >= definition.Timer) {
                                    input.SwallowButton(BUTTON.USE);
                                    val.Timer = DateTime.Now;
                                    val.IsLoadingTimer = false;
                                    PlayerLootContainer(player, definition, lootable, interaction, definition.Panel);
                                    CUIPlayers[player] = val;
                                    UndrawInteraction(player, true);
                                    return;
                                }
                            }
                            else {
                                val.IsLoadingTimer = false;
                                CUIPlayers[player] = val;
                                if (input.WasDown(BUTTON.USE) && !player.inventory.loot.IsLooting()) {
                                    DrawInteraction(player, interaction, definition, lootable, false, reset : false);
                                }
                            }
                            CUIPlayers[player] = val;
                            if (!TimedPlayers.ContainsKey(player) || (TimedPlayers.ContainsKey(player) && TimedPlayers[player] >= Config.DamageCUIRefreshRate / 2)) {
                                if (input.IsDown(BUTTON.USE) && !player.inventory.loot.IsLooting()) DrawInteraction(player, interaction, definition, lootable, false, reset : false);
                                if (TimedPlayers.ContainsKey(player)) TimedPlayers[player] = 0f;
                                else TimedPlayers.Add(player, 0f);
                            }
                            return;
                        }
                        else {
                            var val = playerInteraction.GetValueOrDefault();
                            val.Timer = DateTime.Now;
                            val.IsLoadingTimer = false;
                            CUIPlayers[player] = val;
                        }
                        if (definition != null && !definition.Rule.IsValid(name, player)) return;
                        if (interaction == null && playerInteraction?.Interaction == interaction || playerInteraction?.Lock != lootable?.Lock || playerInteraction?.Interaction != interaction) {
                            if (lootable != null && lootable.HackingPlayer == player) {
                                lootable.CancelHack();
                            }
                            UndrawInteraction(player);
                        }
                        if (!farAway && definition != null && !player.inventory.loot.IsLooting() && !Config.IsFilteredOut(name) && Config.ZoneCheck(player)) {
                            if (definition.Lock != null || definition.Hack != null) lootable = GetLootable(player, obj, definition, true);
                            if (!CUIPlayers.ContainsKey(player) && !player.inventory.loot.IsLooting()) {
                                DrawInteraction(player, interaction, definition, lootable, true);
                            }
                        }
                        else {
                            if (lootable != null && lootable.HackingPlayer == player) {
                                lootable.CancelHack();
                            }
                            if (CUIPlayers.ContainsKey(player)) UndrawInteraction(player);
                        }
                        if (definition != null && !farAway) {
                            if (input.WasJustPressed(BUTTON.USE)) {
                                if (lootable == null) lootable = GetLootable(player, obj, definition, true);
                                if (lootable == null) return;
                                if (!PositionCache.ContainsKey(player)) PositionCache.Add(player, closestHitpoint);
                                else PositionCache[player] = closestHitpoint;
                                if (lootable.IsHackable() && !lootable.IsLocked() && !lootable.IsBusy(player)) {
                                    lootable.StartHack(player);
                                    DrawInteraction(player, interaction, definition, lootable, true, false);
                                    lootable.Hack.HackingTimer = timer.Every(Config.DamageCUIRefreshRate, () => {
                                        if (!CUIPlayers.ContainsKey(player) || Vector3.Distance(PositionCache[player], player.transform.position) > Config.Distance) {
                                            if (lootable != null && lootable.HackingPlayer == player) {
                                                lootable.CancelHack();
                                            }
                                            UndrawInteraction(player);
                                            return;
                                        }
                                        if (lootable.HackHacked()) {
                                            var hackNote = ItemManager.CreateByName("note");
                                            hackNote.text = $"Successfully hacked! The code is: {lootable.Hack.Code}\n\nPress [RELOAD] to open the code input panel.";
                                            player.GiveItem(hackNote);
                                            lootable.Hack.HackedTimes++;
                                            if (lootable != null && lootable.HackingPlayer == player) {
                                                lootable.CancelHack();
                                            }
                                        }
                                        var players = CUIPlayers?.ToArray();
                                        for (int i = 0; i < players.Length; i++) {
                                            if (players[i].Value?.Lootable == lootable) {
                                                DrawInteraction(players[i].Key, interaction, definition, lootable, false, false);
                                            }
                                        }
                                        players = null;
                                    }
                                    );
                                    return;
                                }
                                else if (lootable.IsHacking()) return;
                                if (!lootable.IsLocked() && CUIPlayers[player].Value.TimerTime >= definition.Timer) {
                                    PlayerLootContainer(player, definition, lootable, interaction, definition.Panel);
                                }
                            }
                            else if (input.WasJustPressed(BUTTON.RELOAD) && !lootable.IsLocked() && lootable.IsHackable()) {
                                DrawCodeLockInput(player);
                            }
                        }
                    }
                }
            }
            catch {
            }
            // catch ( Exception ex ) { Puts ( $"{ex}" ); }
        }
        private void OnPlayerAttack(BasePlayer player, HitInfo info) {
            if (Config == null || Instance == null) return;
            object closestEnt;
            Vector3 closestHitpoint;
            if(!TryGetClosestRayPoint(player, out closestEnt, out closestHitpoint)) return;
            var obj = (closestEnt as Collider)?.gameObject;
            if (closestEnt == null || obj == null) return;
            var lootable = GetLootable(player, obj);
            if (lootable == null) return;
            var definition = lootable.GetDefinition();
            if (!lootable.IsLocked()) return;
            var multiplier = info.damageProperties.fallback.GetMultiplier(HitArea.Head);
            var damageAmount = GetRandomNumber(Config.DamageMultiplierMinimum, Config.DamageMultiplierMaximum) * multiplier;
            lootable.Lock.Health -= damageAmount;
            if (lootable.Lock.Health <= 0) {
                lootable.Lock = null;
            }
            if (!TimedPlayers.ContainsKey(player) || (TimedPlayers.ContainsKey(player) && TimedPlayers[player] >= Config.DamageCUIRefreshRate) || !lootable.IsLocked()) {
                ServerMgr.Instance.Invoke(() => {
                    var players = CUIPlayers.ToArray();
                    foreach (var cuiPlayer in players) {
                        if (cuiPlayer.Value?.Lootable == lootable) {
                            DrawInteraction(cuiPlayer.Key, Config.Interactions[definition.InteractionIndex], definition, lootable, false);
                        }
                    }
                    players = null;
                }
                , 0.2f);
                TimedPlayers[player] = 0;
            }
            player?.SendConsoleCommand("gametip.hidegametip");
        }
        private void OnPlayerLootEnd(PlayerLoot inventory) {
            var player = inventory.baseEntity;
            if (player == null) return;
            UndrawInteraction(player, reset : true);
            if (LootingPlayers.ContainsKey(player)) LootingPlayers.Remove(player);
            if (CUIPlayers.ContainsKey(player)) CUIPlayers[player] = null;
        }
        private void OnPluginLoaded(Plugin name) {
            RefreshPlugins();
        }
        private void OnPluginUnloaded(Plugin name) {
            RefreshPlugins();
        }
        private void OnNewSave(string filename) {
            DataFile.WriteObject(Data = new RootData());
        }
        private void OnEntityKill(TimedExplosive entity) {
            var colliders = Facepunch.Pool.GetList<Collider>();
            Vis.Colliders(entity.transform.position, entity.explosionRadius, colliders);
            foreach (var collider in colliders) {
                var lootable = GetLootable(null, collider.gameObject);
                if (lootable != null && lootable.IsLocked()) {
                    lootable.Lock.Health -= entity.damageTypes.Sum(x => x.amount);
                    if (lootable.Lock.Health <= 0) lootable.Lock = null;
                }
            }
            Facepunch.Pool.FreeList(ref colliders);
        }
        private readonly static string[] CommandSplit = new string[] {
            " "
        }
        ;
        private readonly static string[] EmptyArgs = new string[0];
        public static void PlayerLootContainer(BasePlayer player, RootConfig.LootableDefinition definition, RootData.Lootable lootable, RootConfig.Interaction interaction, string lootPanel) {
            player.serverInput.SwallowButton(BUTTON.USE);
            var cui = Instance.CUIPlayers[player].GetValueOrDefault();
            if (cui.IsProcessingCommand) return;
            if (!string.IsNullOrEmpty(interaction.OpenEffect)) SendEffectTo(interaction.OpenEffect, player);
            if (!string.IsNullOrEmpty(definition.Command)) {
                cui.IsProcessingCommand = true;
                Instance.CUIPlayers[player] = cui;
                Instance.DrawInteraction(player, interaction, definition, lootable, false, false, reset : false);
                Instance.timer.In(0.5f, () => {
                    var credential = ConsoleSystem.Option.Unrestricted.FromConnection(player.net.connection);
                    var split = definition.Command.Split(CommandSplit, StringSplitOptions.RemoveEmptyEntries);
                    var command = split.Length > 1 ? split[0] : definition.Command;
                    ConsoleSystem.Run(credential, command, split.Length <= 1 ? EmptyArgs : split.Skip(1).ToArray());
                    cui.IsProcessingCommand = false;
                    Instance.CUIPlayers[player] = cui;
                    Instance.DrawInteraction(player, interaction, definition, lootable, false, reset : false);
                }
                );
                return;
            }
            player.inventory.loot.Clear();
            player.inventory.loot.PositionChecks = false;
            player.inventory.loot.entitySource = RelationshipManager.ServerInstance;
            player.inventory.loot.itemSource = null;
            player.inventory.loot.AddContainer(lootable.GetContainer(definition.ContainerSize, definition.Liquid, definition.AllowStack));
            player.inventory.loot.MarkDirty();
            player.inventory.loot.SendImmediate();
            player.ClientRPCPlayer(null, player, "RPC_OpenLootPanel", lootPanel);
            Instance.QuickSort?.CallHook("OnLootPlayer", player);
            Instance.UndrawInteraction(player, true);
            if (!Instance.LootingPlayers.ContainsKey(player)) Instance.LootingPlayers.Add(player, lootable);
        }
        public static ItemContainer CreateContainer(int capacity = 1, bool liquid = false) {
            var container = new ItemContainer {
                isServer = true, allowedContents = liquid ? ItemContainer.ContentsType.Liquid : ItemContainer.ContentsType.Generic, capacity = capacity
            }
            ;
            container.GiveUID();
            return container;
        }
        public Dictionary<ulong, bool> CoroutineBuffer {
            get;
            privat
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху