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

FREE GlassBridge : 1.7.1 1.7.1

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6

/*
*  <----- End-User License Agreement ----->
*  Copyright © 2024 Iftebinjan
*  Devoloper: Iftebinjan (Contact: https://discord.gg/HFaGs8YwsH)
*  
*  You may not copy, modify, merge, publish, distribute, sublicense, or sell copies of This Software without the Developer’s consent
*  
*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
*  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
*  BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
*  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
*  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.* 
*/
using System;
using System.Linq;
using System.Collections.Generic;
using Oxide.Core;
using UnityEngine;
using VLB;
using System.Collections;
using Newtonsoft.Json;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using Oxide.Core.Libraries.Covalence;
using UnityEngine.UI;
using Network;
using System.Text.RegularExpressions;
namespace Oxide.Plugins {
    [Info("Glass Bridge", "https://discord.gg/TrJ7jnS233", "1.7.1")]
    [Description("The Glass Bridge game")]
    class GlassBridge : RustPlugin {
#region Variables
        [PluginReference]
        Plugin ImageLibrary;
        static GlassBridge plugin;
        private const string glassPrefab = "assets/prefabs/building/wall.window.reinforcedglass/wall.window.glass.reinforced.prefab";
        private const string foundationPrefab = "assets/prefabs/building core/foundation/foundation.prefab";
        private const string entitiesName = "[GlassBridge] Entity";
        private GameObject currentEvent = null;
        private enum EventStatus {
            Spawning, Waiting, Started, Finishing,
        }
        ;
#endregion Variables
#region Hooks
        private void Init() {
            plugin = this;
            permission.RegisterPermission(config.permissionName, this);
            foreach (var command in config.commands) {
                cmd.AddChatCommand(command, this, nameof(GlassBridgeCommand));
                cmd.AddConsoleCommand(command, this, nameof(GlassBridgeConsoleCommand));
            }
        }
        private void Unload() {
            if (currentEvent != null) {
                UnityEngine.Object.Destroy(currentEvent);
            }
        }
        private void OnServerInitialized() {
            if (config.eventSettings.autoStartCooldown > 0) {
                timer.Every(config.eventSettings.autoStartCooldown, () => {
                    if (GetCurrentEvent() != null) {
                        var timespan = TimeSpan.FromSeconds(config.eventSettings.autoStartCooldown);
                        Interface.Oxide.LogDebug($"Unable to start an event automatically because there is already an event currently active.Trying again in {(int)timespan.TotalMinutes}:{timespan.Seconds:00}");
                        return;
                    }
                    StartGlassBridgeEvent();
                }
                );
            }
        }
        private void OnPlayerDisconnected(BasePlayer player, string reason) {
            var @event = GetCurrentEvent();
            if (@event != null && @event.HasPlayer(player)) {
                @event.RemovePlayer(player);
            }
        }
        private object OnEntityMarkHostile(BaseCombatEntity entity, float duration) {
            if (!(entity is BasePlayer)) return null;
            if (IsPlaying((entity as BasePlayer).userID)) return false;
            return null;
        }
        /* TruePVE hook */
        private object CanEntityTakeDamage(BasePlayer victim, HitInfo info) {
            if (victim != null && victim.userID.IsSteamId() && IsPlaying(victim.userID)) {
                return true;
            }
            return null;
        }
        private object OnEntityTakeDamage(BaseEntity entity, HitInfo info) {
            var @event = GetCurrentEvent();
            if (@event != null) {
                if (entity is BasePlayer) {
                    var player = entity as BasePlayer;
                    if (!@event.HasPlayer(player)) {
                        return null;
                    }
                    if (!config.eventSettings.pvpEnabled) {
                        var initiator = info.InitiatorPlayer;
                        if (initiator != null && initiator.userID.IsSteamId()) {
                            info.damageTypes.ScaleAll(0f);
                            return true;
                        }
                    }
                    var damageType = info.damageTypes.GetMajorityDamageType();
                    if (damageType == Rust.DamageType.Fall) {
                        info.damageTypes.ScaleAll(0f);
                        return false;
                    }
                    if (@event.Status() != EventStatus.Started) {
                        info.damageTypes.ScaleAll(0f);
                        return false;
                    }
                }
                if (@event.HasGlass(entity)) {
                    info.damageTypes.ScaleAll(0f);
                    return true;
                }
            }
            return null;
        }
        private void OnRunPlayerMetabolism(PlayerMetabolism metabolism, BasePlayer player) {
            GlassBridgeEvent @event = GetCurrentEvent();
            if (@event == null || !@event.HasPlayer(player)) return;
            if (metabolism.bleeding.value < 1) return;
            metabolism.bleeding.value = 0;
        }
        private object OnPlayerDeath(BasePlayer player, HitInfo info) {
            var @event = GetCurrentEvent();
            if (@event == null || !@event.HasPlayer(player)) {
                return null;
            }
            if (config.eventSettings.rollbackWhenDie) {
                @event.RollbackPlayer(player);
            }
            else {
                info.damageTypes.ScaleAll(0f);
                info.DidHit = false;
                info.PointStart = Vector3.zero;
                @event.RemovePlayer(player);
            }
            return true;
        }
        private object OnPlayerWound(BasePlayer player, HitInfo info) => OnPlayerDeath(player, info);
        private object OnUserCommand(IPlayer _player, string command, string[] args) {
            if (config.commands.Contains(command)) {
                return null;
            }
            var player = BasePlayer.Find(_player.Id);
            if (player == null || !IsPlaying(player.userID)) {
                return null;
            }
            if (config.blockedChatCommands.Contains("*") || config.blockedChatCommands.Contains(command)) {
                SendMessage(player, "CommandBlocked");
                return true;
            }
            return null;
        }
        private object OnServerCommand(ConsoleSystem.Arg arg) {
            var player = arg?.Player();
            if (player == null || !IsPlaying(player.userID)) {
                return null;
            }
            if (config.allowedConsoleCommands.Contains("*")) {
                return null;
            }
            var command = arg.cmd.Name;
            var allowedCommands = config.allowedConsoleCommands.Append("glassbridge_ui");
            if (!allowedCommands.Contains(command)) {
                arg.ReplyWith(Lang("CommandBlocked", player.UserIDString));
                return true;
            }
            return null;
        }
#endregion Hooks
#region Commands
        private void GlassBridgeCommand(BasePlayer player, string command, string[] args) {
            if (args.Length < 1) {
                SendMessage(player, "SyntaxError", command);
                return;
            }
            switch (args[0]) {
                case "start" : {
                    if (!HasPermission(player)) {
                        SendMessage(player, "NotAllowed");
                        return;
                    }
                    if (currentEvent != null) {
                        SendMessage(player, "AlreadyActive");
                        return;
                    }
                    StartGlassBridgeEvent();
                    SendMessage(player, "YouStartedAnEvent");
                    return;
                }
                case "stop" : {
                    if (!HasPermission(player)) {
                        SendMessage(player, "NotAllowed");
                        return;
                    }
                    var @event = GetCurrentEvent();
                    if (@event == null) {
                        SendMessage(player, "NoActiveEvent");
                        return;
                    }
                    if (@event.Status() == GlassBridge.EventStatus.Finishing) {
                        SendMessage(player, "AlreadyBeingFinalized");
                        return;
                    }
                    @event.Finalize(GlassBridgeEvent.FinalizationType.Stop);
                    SendMessage(player, "YouStoppedTheEvent");
                    return;
                }
                case "join" : {
                    var @event = GetCurrentEvent();
                    if (@event == null) {
                        SendMessage(player, "NoActiveEvent");
                        return;
                    }
                    if (@event.HasPlayer(player)) {
                        SendMessage(player, "IsAlreadyAtTheEvent");
                        return;
                    }
                    if (@event.Status() == EventStatus.Started) {
                        SendMessage(player, "AlreadyStarted");
                        return;
                    }
                    if (@event.Status() != EventStatus.Waiting) {
                        SendMessage(player, "NoActiveEvent");
                        return;
                    }
                    if (player.IsDead() || player.IsWounded()) {
                        SendMessage(player, "DeadOrWounded");
                        return;
                    }
                    if (!player.IsOnGround()) {
                        SendMessage(player, "NotOnGround");
                        return;
                    }
                    player.inventory.crafting.CancelAll();
                    @event.AddPlayer(player);
                    SendMessage(player, "Joined");
                    return;
                }
                case "leave" : {
                    var @event = GetCurrentEvent();
                    if (@event == null || (@event.Status() != EventStatus.Started && @event.Status() != EventStatus.Waiting)) {
                        SendMessage(player, "NoActiveEvent");
                        return;
                    }
                    if (!@event.HasPlayer(player)) {
                        SendMessage(player, "NotParticipating");
                        return;
                    }
                    @event.RemovePlayer(player);
                    SendMessage(player, "Leave");
                    return;
                }
                default : SendMessage(player, "SyntaxError", command);
                break;
            }
        }
        private void GlassBridgeConsoleCommand(ConsoleSystem.Arg arg) {
            if (arg == null) return;
            BasePlayer player = arg.Player();
            if (!arg.HasArgs()) {
                arg.ReplyWith(HumanizedLang("ConsoleSyntaxError", player, arg.cmd.Name));
                return;
            }
            switch (arg.Args[0]) {
                case "start" : {
                    if (player != null && !HasPermission(player)) {
                        arg.ReplyWith(HumanizedLang("NotAllowed", player));
                        return;
                    }
                    if (currentEvent != null) {
                        arg.ReplyWith(HumanizedLang("AlreadyActive", player));
                        return;
                    }
                    StartGlassBridgeEvent();
                    arg.ReplyWith(HumanizedLang("YouStartedAnEvent", player));
                    return;
                }
                case "stop" : {
                    if (player != null && !HasPermission(player)) {
                        arg.ReplyWith(HumanizedLang("NotAllowed", player));
                        return;
                    }
                    var @event = GetCurrentEvent();
                    if (@event == null) {
                        arg.ReplyWith(HumanizedLang("NoActiveEvent", player));
                        return;
                    }
                    if (@event.Status() == GlassBridge.EventStatus.Finishing) {
                        arg.ReplyWith(HumanizedLang("AlreadyBeingFinalized", player));
                        return;
                    }
                    @event.Finalize(GlassBridgeEvent.FinalizationType.Stop);
                    arg.ReplyWith(HumanizedLang("YouStoppedTheEvent", player));
                    return;
                }
                default : arg.ReplyWith(HumanizedLang("ConsoleSyntaxError", player, arg.cmd.Name));
                break;
            }
        }
        [ConsoleCommand("glassbridge_ui")]
        private void consoleCommandGlassBridgeJoin(ConsoleSystem.Arg arg) {
            var player = arg?.Player();
            if (player == null || !arg.HasArgs(1)) {
                return;
            }
            var subcommand = arg.Args[0];
            player.SendConsoleCommand($"chat.say", $"/{config.commands.FirstOrDefault()} {subcommand}");
        }
#endregion Commands
#region Methods
        public void StartGlassBridgeEvent() {
            if (GetCurrentEvent() != null) {
                return;
            }
            var sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere);
            sphere.transform.position = config.eventSettings.position;
            var collider = sphere.GetComponent<SphereCollider>();
            collider.radius = config.glassesSettings.rows * config.glassesSettings.columns + 50;
            var trigger = sphere.GetOrAddComponent<TriggerBase>();
            trigger.interestLayers = LayerMask.GetMask("Player (Server)");
            trigger.enabled = true;
            var @event = sphere.AddComponent<GlassBridgeEvent>();
            currentEvent = sphere;
        }
        private GlassBridgeEvent GetCurrentEvent() {
            return currentEvent?.GetComponent<GlassBridgeEvent>();
        }
        public Item GiveItem(ItemContainer container, string name, int amount, int loadedAmmo = 0, ulong skinId = 0L, string customName = "") {
            var item = ItemManager.CreateByName(name, amount, skinId);
            if (item != null) {
                if (loadedAmmo > 0) {
                    var projectile = item.GetHeldEntity()?.GetComponent<BaseProjectile>();
                    if (projectile != null) {
                        projectile.primaryMagazine.contents = Math.Min((int)loadedAmmo, projectile.primaryMagazine.capacity);
                    }
                }
                if (!string.IsNullOrEmpty(customName)) {
                    item.name = customName;
                }
                item.MoveToContainer(container, allowStack : false, ignoreStackLimit : true);
            }
            return item;
        }
        private void BroadcastMessage(string message, params object[] args) {
            foreach (var player in BasePlayer.activePlayerList) {
                SendMessage(player, message, args);
            }
        }
        private void SendMessage(BasePlayer player, string message, params object[] args) => rust.SendChatMessage(player, Lang("ChatName", player.UserIDString), string.Format(Lang(message, player.UserIDString), args) );
#endregion Methods
#region API
        private bool IsActive() => GetCurrentEvent() != null;
        private bool IsPlaying(string playerId) {
            var @event = GetCurrentEvent();
            if (@event != null) {
                return @event.HasPlayer(playerId);
            }
            return false;
        }
        private bool IsPlaying(ulong playerId) => IsPlaying(playerId.ToString());
        private void RemovePlayer(string playerId) {
            var @event = GetCurrentEvent();
            if (@event != null) {
                @event.RemovePlayer(playerId);
            }
        }
        private void RemovePlayer(ulong playerId) => RemovePlayer(playerId.ToString());
        private List<BasePlayer> PlayingList() {
            var playing = new List<BasePlayer>();
            foreach (var player in BasePlayer.activePlayerList) {
                if (IsPlaying(player.userID)) {
                    playing.Add(player);
                }
            }
            return playing;
        }
#endregion API
#region ImageLibrary
        private bool AddImage(string url, string name) => (bool)ImageLibrary?.Call("AddImage", url, name);
        private string GetImage(string name) => ImageLibrary?.Call<string>("GetImage", name);
        private bool HasImage(string name) => (bool)ImageLibrary?.Call("HasImage", name);
#endregion ImageLibrary
#region Helpers
        private bool HasPermission(BasePlayer player) => player.IsAdmin || permission.UserHasPermission(player.UserIDString, config.permissionName);
        private int[] GetRandomNumbersBetweenRange(int start, int end, int amount) {
            if (end - start < amount) {
                return new int[] {
                }
                ;
            }
            var result = new int[amount];
            for (int i = 0; i < amount; i++) {
                int num = UnityEngine.Random.Range(start, end + 1);
                if (!result.Contains(num)) {
                    result[i] = num;
                    continue;
                }
                i--;
            }
            return result;
        }
        private long DateNow() {
            return (long)(DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds;
        }
#endregion Helpers
#region UI
        private void CreateJoinLeaveUI(BasePlayer player) {
            var container = new CuiElementContainer();
            var @event = GetCurrentEvent();
            if (@event == null || @event.Status() != EventStatus.Waiting) {
                CuiHelper.DestroyUi(player, "JoinLeavePanel");
                return;
            }
            var settings = config.UI.joinLeave;
            var isPlaying = IsPlaying(player.UserIDString);
            UIBuilder.CreatePanel(ref container, "Overlay", settings.color, settings.anchor, settings.offset, name : "JoinLeavePanel", destroyUi : "JoinLeavePanel");
            UIBuilder.CreatePanel(ref container, "JoinLeavePanel", "0 1 1 1", "0 1 1 1", "0 -2 0 0");
            // Title
            UIBuilder.CreateLabel(ref container, "JoinLeavePanel", Lang("GlassBridgeTitle", player.UserIDString), "0 1 1 1", "0 -56 0 0", align : TextAnchor.MiddleCenter);
            // Button
            UIBuilder.CreatePanel(ref container, "JoinLeavePanel", isPlaying ? settings.button.leaveColor : settings.button.joinColor, "0 0 1 0", "4 4 -4 36", name : "JoinLeaveButton");
            UIBuilder.CreateLabel(ref container, "JoinLeaveButton", Lang(isPlaying ? "LeaveButton" : "JoinButton", player.UserIDString), "0 0 1 1", "", align : TextAnchor.MiddleCenter);
            container.Add(new CuiButton {
                RectTransform = {
                    AnchorMin = "0 0", AnchorMax = "1 1"
                }
                , Button = {
                    Color = "0 0 0 0", Command = $"glassbridge_ui {(isPlaying ? "leave" : "join")}"
                }
            }
            , "JoinLeaveButton" );
            UIBuilder.CreatePanel(ref container, "JoinLeavePanel", "1 1 1.1", "0 0 1 0", "4 68 -4 92", name : "JoinLeaveInfoPlayers");
            UIBuilder.CreatePanel(ref container, "JoinLeaveInfoPlayers", null, "0.5 0.5", "4 -7 18 7", image : "https://i.ibb.co/0msdX54/image.png");
            UIBuilder.CreateLabel(ref container, "JoinLeaveInfoPlayers", $"<size=12><b>{@event?.GetRemainingPlayersAmount() ?? 0}</b></size>", "0 0 1 1", "0 0 0 0", align : TextAnchor.MiddleCenter);
            TimeSpan timespan = TimeSpan.FromSeconds(@event.waitStartedAt != null ? Math.Max(config.eventSettings.waitDuration - (DateNow() - (int)@event.waitStartedAt), 0) : 0);
            UIBuilder.CreatePanel(ref container, "JoinLeavePanel", "1 1 1.1", "0 0 1 0", "4 40 -4 64", name : "JoinLeaveInfoTime");
            UIBuilder.CreatePanel(ref container, "JoinLeaveInfoTime", null, "0.5 0.5", "4 -7 18 7", image : "https://i.ibb.co/Fb5WsqH/image.png");
            UIBuilder.CreateLabel(ref container, "JoinLeaveInfoTime", $"<size=12><b>{(int)timespan.TotalMinutes}:{timespan.Seconds:00}</b></size>", "0 0 1 1", "0 0 0 0", align : TextAnchor.MiddleCenter);
            CuiHelper.AddUi(player, container);
        }
        private void UpdateEventStatusUI(BasePlayer player, int remainingPlayers, long remainingTime = 0) {
            var container = new CuiElementContainer();
            var timespan = TimeSpan.FromSeconds(remainingTime);
            var minutes = $"{(config.eventSettings.autoStopAfter > 0 ? ((int)timespan.TotalMinutes).ToString() : "--")}";
            var seconds = $"{(config.eventSettings.autoStopAfter > 0 ? timespan.Seconds.ToString() : "--")}";
            UIBuilder.CreateLabel(ref container, "EventStatusRemainingPlayersBox", string.Format(Lang("EventStatusRemainingPlayersText", player.UserIDString), remainingPlayers), "0 0 1 1", "4 0 -4 0", align : TextAnchor.MiddleCenter, name : "EventStatusRemainingPlayersText", destroyUi : "EventStatusRemainingPlayersText");
            UIBuilder.CreateLabel(ref container, "EventStatusRemainingTimeBox", string.Format(Lang("EventStatusRemainingTimeText", player.UserIDString), minutes, seconds.PadLeft(2, '0')), "0 0 1 1", "4 0 -4 0", align : TextAnchor.MiddleCenter, name : "EventStatusRemainingTimeText", destroyUi : "EventStatusRemainingTimeText");
            CuiHelper.AddUi(player, container);
        }
        private void CreateEventStatusUI(BasePlayer player, int remainingPlayers, long remainingTime = 0) {
            var container = new CuiElementContainer();
            var UISettings = config.UI.eventStatus;
            UIBuilder.CreatePanel(ref container, "Hud", "0 0 0 0", UISettings.anchor, UISettings.offset, name : "EventStatus", destroyUi : "EventStatus");
            UIBuilder.CreatePanel(ref container, "EventStatus", UISettings.remainingPlayers.color, UISettings.remainingPlayers.anchor, UISettings.remainingPlayers.offset, name : "EventStatusRemainingPlayersBox");
            UIBuilder.CreatePanel(ref container, "EventStatus", UISettings.remainingTime.color, UISettings.remainingTime.anchor, UISettings.remainingTime.offset, name : "EventStatusRemainingTimeBox");
            UIBuilder.CreatePanel(ref container, "EventStatusRemainingPlayersBox", "1 1 1 1", UISettings.remainingPlayers.iconAnchor, UISettings.remainingPlayers.iconOffset, image : UISettings.remainingPlayers.iconUrl);
            CuiHelper.AddUi(player, container);
            UpdateEventStatusUI(player, remainingPlayers, remainingTime);
        }
        private void CreateStartCountdownUI(BasePlayer player, string text, bool isLast = false) {
            var container = new CuiElementContainer();
            UIBuilder.CreateLabel(ref container, "Hud", text, "0 0 1 1", "", .1f, .3f, TextAnchor.MiddleCenter, "StartCountdown", "StartCountdown");
            Effect.server.Run(isLast ? "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab" : "assets/prefabs/locks/keypad/effects/lock.code.lock.prefab", player, 0, new Vector3(), player.transform.position, null, false);
            CuiHelper.AddUi(player, container);
        }
        private void CreateGiveTimeWarnUI(BasePlayer player, string text, string color) {
            var container = new CuiElementContainer();
            UIBuilder.CreatePanel(ref container, "Hud", "0 0 0.65", "0.5 0 0.5 0", "-128 100 128 136", .3f, .3f, name : "GiveTimeWarn", destroyUi : "GiveTimeWarn", material : "assets/content/ui/uibackgroundblur-ingamemenu.mat");
            UIBuilder.CreatePanel(ref container, "GiveTimeWarn", color, "0 0 0 1", "0 0 3 0");
            UIBuilder.CreatePanel(ref container, "GiveTimeWarn", color, "1 0 1 1", "-3 0 0 0");
            UIBuilder.CreateLabel(ref container, "GiveTimeWarn", text, "0 0 1 1", $"12 0 -12 0", align : TextAnchor.MiddleCenter, fontSize : 12);
            CuiHelper.AddUi(player, container);
        }
        private class UIBuilder {
            public static void CreatePanel(ref CuiElementContainer container, string parent, string color, string anchor, string offset, float fadeIn = 0f, float fadeOut = 0f, string image = null, int itemId = 0, string name = null, string destroyUi = null, string material = null) {
                var _anchor = ParseMinMax(anchor);
                var _offset = ParseMinMax(offset);
                if (string.IsNullOrEmpty(image)) {
                    container.Add(new CuiPanel {
                        FadeOut = fadeOut, RectTransform = {
                            AnchorMin = _anchor[0], AnchorMax = _anchor[1], OffsetMin = _offset[0], OffsetMax = _offset[1],
                        }
                        , Image = {
                            Color = color, ItemId = itemId, FadeIn = fadeIn, Material = material,
                        }
                    }
                    , parent, name, destroyUi );
                }
                else {
                    if (!plugin.HasImage(image)) {
                        plugin.AddImage(image, image);
                    }
                    container.Add(new CuiElement {
                        Name = name, Parent = parent, DestroyUi = destroyUi, FadeOut = fadeOut, Components = {
                            new CuiRectTransformComponent {
                                AnchorMin = _anchor[0], AnchorMax = _anchor[1], OffsetMin = _offset[0], OffsetMax = _offset[1],
                            }
                            , new CuiRawImageComponent {
                                Url = plugin.HasImage(image) ? null : image, Png = plugin.HasImage(image) ? plugin.GetImage(image) : null, FadeIn = fadeIn,
                            }
                        }
                    }
                    );
                }
            }
            public static void CreateLabel(ref CuiElementContainer container, string parent, string text, string anchor, string offset, float fadeIn = 0f, float fadeOut = 0f, TextAnchor align = TextAnchor.MiddleLeft, string name = null, string destroyUi = null, int fontSize = 14) {
                var _anchor = ParseMinMax(anchor);
                var _offset = ParseMinMax(offset);
                container.Add(new CuiLabel {
                    FadeOut = fadeOut, RectTransform = {
                        AnchorMin = _anchor[0], AnchorMax = _anchor[1], OffsetMin = _offset[0], OffsetMax = _offset[1],
                    }
                    , Text = {
                        Color = "1 1 1 1", Text = text, FadeIn = fadeIn, Align = align, FontSize = fontSize, Font = "robotocondensed-regular.ttf"
                    }
                }
                , parent, name, destroyUi );
            }
            private static string[] ParseMinMax(string value) {
                var array = value.Split(' ');
                return new string[] {
                    string.Join(" ", array.Take(2)), string.Join(" ", array.Skip(2)),
                }
                ;
            }
        }
#endregion UI
#region Structures
        private class Glass : MonoBehaviour {
            public bool isBroken = false;
            private BaseEntity entity;
            private BoxCollider collider;
            private void Awake() {
                entity = GetComponent<BaseEntity>();
                if (entity == null) {
                    Destroy(this);
                    return;
                }
                entity.name = "[GlassBridge] Glass Entity";
                var stability = GetComponent<StabilityEntity>();
                stability.grounded = true;
                collider = this.GetOrAddComponent<BoxCollider>();
                collider.isTrigger = true;
                collider.center = entity.bounds.center;
                collider.size = entity.bounds.size + new Vector3(3f, 0f, 0f);
                gameObject.layer = (int)Rust.Layer.Reserved1;
                gameObject.name = "[GlassBridge] Glass";
                ;
            }
            private void OnTriggerEnter(Collider col) {
                var player = col.GetComponent<BasePlayer>();
                if (player == null || !player.userID.IsSteamId()) {
                    return;
                }
                if (isBroken) {
                    var @event = plugin.GetCurrentEvent();
                    if (!@event) {
                        Destroy(this);
                        return;
                    }
                    if (@event.Status() == EventStatus.Started && @event.HasPlayer(player)) {
                        @event.DestroyGlass(this);
                    }
                }
            }
            private void OnDestroy() {
                if (entity != null && !entity.IsDestroyed) {
                    entity.AdminKill();
                }
            }
        }
        private class EventPlayer : MonoBehaviour {
            public BasePlayer player {
                get;
                private set;
            }
            private PlayerBackup backup;
            private int startCountdown = 3;
            private bool isFreeze = false;
            private Vector3? freezePosition = null;
            private bool isWinner = false;
            private void Awake() {
                player = GetComponent<BasePlayer>();
            }
            private void Update() {
                var @event = plugin.GetCurrentEvent();
                if (!@event) {
                    Destroy(this);
                    return;
                }
                if (@event.Status() == EventStatus.Started) {
                    if (isFreeze && freezePosition != null) {
                        player.Teleport(freezePosition.Value);
                    }
                    if (@event.GetPlayerEventPosition(player) == GlassBridgeEvent.PlayerEventPosition.Arrival) {
                        @event.Finalize(GlassBridgeEvent.FinalizationType.Winner, player);
                        return;
                    }
                }
                if (transform.position.y < plugin.config.eventSettings.position.y - 20f) {
                    if (plugin.config.eventSettings.loseWhenFall && @event.Status() == EventStatus.Started && @event.startedAt != null) {
                        @event.RemovePlayer(player);
                        return;
                    }
                    player.Teleport(@event.GetRandomSpawnPoint());
                }
            }
            private void OnDestroy() {
                CancelInvoke(nameof(ShowStartCountdown));
                CancelInvoke(nameof(DestroyCountdown));
                CancelInvoke(nameof(UpdateEventStatusUI));
                DestroyAllUI();
                Restore();
            }
            private void Restore() {
                player.metabolism.Reset();
                player.SetHealth(backup.metabolism.health);
                player.metabolism.bleeding.value = backup.metabolism.bleeding;
                player.metabolism.calories.value = backup.metabolism.calories;
                player.metabolism.hydration.value = backup.metabolism.hydration;
                player.metabolism.oxygen.value = backup.metabolism.oxygen;
                player.metabolism.poison.value = backup.metabolism.poison;
                player.metabolism.radiation_level.value = backup.metabolism.radiation_level;
                player.metabolism.radiation_poison.value = backup.metabolism.radiation_poison;
                player.metabolism.wetness.value = backup.metabolism.wetness;
                player.metabolism.temperature.value = backup.metabolism.temperature;
                player.inventory.Strip();
                backup.RestorePlayer();
                Teleport(backup.position);
                backup = null;
                if (isWinner) {
                    /* Give winner items */
                    foreach (var item in plugin.config.prizeSettings.items) {
                        var container = player.inventory.containerMain.itemList.Count() < 24 ? player.inventory.containerMain : player.inventory.containerBelt;
                        plugin.GiveItem(container, item.shortname, item.amount, 0, item.skinId, item.customName);
                    }
                    /* Execute server commnads */
                    foreach (var command in plugin.config.prizeSettings.commands) {
                        var args = command.Replace("{winner_id}", player.UserIDString).Replace("{winner_name}", player.displayName).Split(' ');
                        plugin.Server.Command(args[0], args.Skip(1));
                    }
                }
            }
            public void SetWinner() {
                isWinner = true;
            }
            public void Teleport(Vector3 position) {
                if (!player.IsValid()) return;
                try {
                    player.UpdateActiveItem(new ItemId(0u));
                    player.EnsureDismounted();
                    if (player.HasParent()) player.SetParent(null, true, true);
                    if (player.IsConnected) {
                        player.EndLooting();
                        if (!player.IsSleeping()) {
                            player.SetPlayerFlag(BasePlayer.PlayerFlags.Sleeping, true);
                            player.sleepStartTime = Time.time;
                            BasePlayer.sleepingPlayerList.Add(player);
                            player.CancelInvoke("InventoryUpdate");
                            player.CancelInvoke("TeamUpdate");
                        }
                    }
                    player.RemoveFromTriggers();
                    player.Teleport(position);
                    if (player.IsConnected && !Net.sv.visibility.IsInside(player.net.group, position)) {
                        player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
                        player.ClientRPCPlayer(null, player, "StartLoading");
                        player.SendEntityUpdate();
                        player.UpdateNetworkGroup();
                        player.SendNetworkUpdateImmediate(false);
                    }
                }
                finally {
                    player.ForceUpdateTriggers();
                }
            }
            public void SetFreeze(bool freeze) {
                if (freeze) {
                    isFreeze = true;
                    freezePosition = player.transform.position;
                }
                else {
                    isFreeze = false;
                    freezePosition = null;
                }
            }
            public void Heal() {
                player.SetHealth(player._maxHealth);
                player.metabolism.bleeding.value = 0;
                player.metabolism.calories.min = 0;
                player.metabolism.calories.value = 500;
                player.metabolism.hydration.min = 0;
                player.metabolism.hydration.value = 250;
                player.metabolism.oxygen.value = 1;
                player.metabolism.poison.value = 0;
                player.metabolism.radiation_level.value = 0;
                player.metabolism.radiation_poison.value = 0;
                player.metabolism.wetness.value = 0;
                player.metabolism.temperature.min = 32;
                player.metabolism.temperature.max = 32;
                player.metabolism.temperature.value = 32;
                player.metabolism.SendChangesToClient();
            }
            public void CreateBackup() {
                backup = new PlayerBackup(player);
            }
            public void ShowGiveTimeWarn(string text, string color) {
                if (IsInvoking(nameof(DestroyGiveTimeWarn))) {
                    CancelInvoke(nameof(DestroyGiveTimeWarn));
                }
                plugin.CreateGiveTimeWarnUI(player, text, color);
                Invoke(nameof(DestroyGiveTimeWarn), 6f);
            }
            public void ShowStartCountdown() {
                plugin.CreateStartCountdownUI(player, plugin.Lang($"StartCountdown_{startCountdown}", player.UserIDString), !(startCountdown > 0));
                Invoke(nameof(DestroyCountdown), .7f);
                if (startCountdown > 0) {
                    startCountdown--;
                    Invoke(nameof(ShowStartCountdown), 1f);
                }
            }
            public void ShowEventStatus(int remainingPlayers, long remainingTime = 0) {
                plugin.CreateEventStatusUI(player, remainingPlayers, remainingTime);
                InvokeRepeating(nameof(UpdateEventStatusUI), 1f, 1f);
            }
            public void UpdateEventStatusUI() {
                var @event = plugin.GetCurrentEvent();
                if (!@event) {
                    Destroy(this);
                    return;
                }
                long remainingTime = plugin.config.eventSettings.autoStopAfter;
                if (@event.startedAt != null && plugin.config.eventSettings.autoStopAfter > 0) {
                    var elapsed = plugin.DateNow() - @event.startedAt;
                    remainingTime = Math.Max(plugin.config.eventSettings.autoStopAfter - (int)elapsed, 0);
                }
                plugin.UpdateEventStatusUI(player, @event.GetRemainingPlayersAmount(), remainingTime );
            }
            private void DestroyGiveTimeWarn() {
                CuiHelper.DestroyUi(player, "GiveTimeWarn");
            }
            private void DestroyCountdown() {
                CuiHelper.DestroyUi(player, "StartCountdown");
            }
            private void DestroyEventStatus() {
            }
            private void DestroyAllUI() {
                DestroyGiveTimeWarn();
                DestroyCountdown();
                CuiHelper.DestroyUi(player, "EventStatus");
            }
        }
        private class GlassBridgeEvent : MonoBehaviour {
            private EventStatus status = EventStatus.Spawning;
            private List<EventPlayer> players = new List<EventPlayer>();
            private List<Glass> glasses = new List<Glass>();
            private List<BaseEntity> foundations = new List<BaseEntity>();
            private List<BaseEntity> arrivalFoundations = new List<BaseEntity>();
            public long? startedAt {
                get;
                private set;
            }
            public long? waitStartedAt {
                get;
                private set;
            }
            public enum PlayerEventPosition {
                Lobby, Bridge, Arrival,
            }
            ;
            public enum FinalizationType {
                Winner, Stop, AutoStop, NoPlayers, MinPlayers,
            }
            ;
            private void Awake() {
                gameObject.layer = (int)Rust.Layer.Reserved1;
                gameObject.name = "[GlassBridge] Event";
                var sphere = GetComponent<SphereCollider>();
                sphere.isTrigger = true;
            }
            private void Start() {
                StartCoroutine(CreateLobby());
            }
            private void OnTriggerEnter(Collider col) {
                var player = col?.GetComponent<BasePlayer>();
                if (player == null || !player.userID.IsSteamId()) {
                    return;
                }
                if (!IsSafePlayer(player)) {
                    player.Invoke(() => player.Hurt(1000f, Rust.DamageType.Explosion, null, false), 0.25f);
                }
            }
            private void OnTriggerExit(Collider col) {
                var player = col?.GetComponent<BasePlayer>();
                if (player == null || !HasPlayer(player)) {
                    return;
                }
                var eventPlayer = player.GetComponent<EventPlayer>();
                players.Remove(eventPlayer);
                Destroy(eventPlayer);
                plugin.SendMessage(player, "LeftFromEventArea");
                if (players.Count < 1 && status == EventStatus.Started) {
                    Finalize(FinalizationType.NoPlayers);
                }
            }
            private void OnDestroy() {
                CancelInvoke(nameof(ShowPlayersJoinLeaveUI));
                DestroyPlayersJoinLeaveUI();
                foreach (var eventPlayer in players) {
                    Destroy(eventPlayer);
                }
                foreach (var glass in glasses) {
                    Destroy(glass);
                }
                foreach (var foundation in foundations) {
                    foundation?.AdminKill();
                }
                foreach (var foundation in arrivalFoundations) {
                    foundation?.AdminKill();
                }
                plugin.currentEvent = null;
            }
            private IEnumerator StartEvent() {
                status = EventStatus.Waiting;
                waitStartedAt = plugin.DateNow();
                Interface.CallHook("OnGlassBridgeEventStarted");
                plugin.BroadcastMessage("EventStarted", plugin.config.commands[0]);
                InvokeRepeating(nameof(ShowPlayersJoinLeaveUI), 0, 1f);
                yield return new WaitForSeconds(plugin.config.eventSettings.waitDuration);
                CancelInvoke(nameof(ShowPlayersJoinLeaveUI));
                DestroyPlayersJoinLeaveUI();
                status = EventStatus.Started;
                waitStartedAt = null;
                if (players.Count < Math.Max(plugin.config.eventSettings.minPlayers, 1)) {
                    Finalize(FinalizationType.MinPlayers);
                    yield break;
                }
                foreach (var eventPlayer in players) {
                    var player = eventPlayer.player;
                    player.Teleport(GetRandomSpawnPoint());
                    eventPlayer.SetFreeze(true);
                    eventPlayer.ShowStartCountdown();
                    eventPlayer.ShowEventStatus(players.Count, plugin.config.eventSettings.autoStopAfter);
                }
                yield return new WaitForSeconds(4f);
                startedAt = plugin.DateNow();
                foreach (var eventPlayer in players) {
                    eventPlayer.SetFreeze(false);
                }
                if (plugin.config.eventSettings.autoStopAfter > 0) {
                    Invoke(nameof(AutoStop), plugin.config.eventSettings.autoStopAfter);
                }
                InvokeRepeating(nameof(TryGiveTime), 0f, 1f);
            }
            public void Finalize(FinalizationType type, BasePlayer winner = null) {
                status = EventStatus.Finishing;
                CancelInvoke(nameof(AutoStop));
                CancelInvoke(nameof(TryGiveTime));
                Interface.CallHook("OnGlassBridgeEventEnded", winner);
                switch (type) {
                    case FinalizationType.Winner : {
                        Destroy(this, 5f);
                        if (winner != null && HasPlayer(winner)) {
                            winner.GetComponent<EventPlayer>().SetWinner();
                            plugin.BroadcastMessage("WinnerBroadcast", winner.displayName);
                            foreach (var eventPlayer in players) {
                                var player = eventPlayer.player;
                                plugin.SendMessage(player, "WaitForTeleport");
                            }
                        }
                        break;
                    }
                    case FinalizationType.Stop : {
                        Destroy(this);
                        plugin.BroadcastMessage("Stopped");
                        break;
                    }
                    case FinalizationType.AutoStop : {
                        Destroy(this);
                        plugin.BroadcastMessage("AutoStopped");
                        break;
                    }
                    case FinalizationType.NoPlayers : {
                        Destroy(this);
                        plugin.BroadcastMessage("NoPlayers");
                        break;
                    }
                    case FinalizationType.MinPlayers : {
                        Destroy(this);
                        plugin.BroadcastMessage("MinPlayers", Math.Max(plugin.config.eventSettings.minPlayers, 1));
                        break;
                    }
                }
            }
            public void AutoStop() => Finalize(FinalizationType.AutoStop);
            private void TryGiveTime() {
                var elapsed = plugin.DateNow() - startedAt;
                if (elapsed == null) {
                    return;
                }
                var gives = plugin.config.eventSettings.giveTimes.Where((x) => x.time == elapsed);
                foreach (var give in gives) {
                    foreach (var eventPlayer in players) {
                        var player = eventPlayer.player;
                        var container = give.container == "belt" ? player.inventory.containerBelt : give.container == "wear" ? player.inventory.containerWear : player.inventory.containerMain;
                        Item item = plugin.GiveItem(container, give.shortname, give.amount, give.loadedAmmo, give.skinId);
                        if (give.showWarn && item != null) {
                            eventPlayer.ShowGiveTimeWarn(string.Format(plugin.Lang(give.langKey, player.UserIDString), give.amount, item.info.displayName.english), give.warnBgColor);
                        }
                    }
                }
            }
            public EventStatus Status() => status;
            private IEnumerator CreateLobby() {
                var columns = plugin.config.glassesSettings.columns;
                for (int i = 0; i < (3.5 * columns / 3);
                i++) {
                    for (int j = 0; j < 4; j++) {
                        var entity = GameManager.server.CreateEntity(foundationPrefab, plugin.config.eventSettings.position + new Vector3(i * 3, 0, j * 3));
                        entity.name = entitiesName;
                        entity.Spawn();
                        var build = entity.GetComponent<BuildingBlock>();
          
// ... [Code preview truncated due to length. Full source in attached file] ...

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