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

FREE DynamicWireColors : 1.1.3 1.1.3

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using static WireTool;
using static IOEntity;
namespace Oxide.Plugins {
    [Info("Dynamic Wire Colors", "WhiteThunder", "1.1.3")]
    [Description("Temporarily changes the color of wires and hoses while they are providing insufficient power or fluid.")]
    internal class DynamicWireColors : CovalencePlugin {
#region Fields
        private Configuration _config;
        private const string PermissionUse = "dynamicwirecolors.use";
        private WaitWhile WaitWhileSaving = new(() => SaveRestore.IsSaving);
#endregion
#region Hooks
        private void Init() {
            permission.RegisterPermission(PermissionUse, this);
        }
        private void OnServerInitialized() {
            SetupAllEntities(networkUpdate : true, fixDestinationColor : true);
        }
        private void Unload() {
            ResetAllEntities(networkUpdate : true);
        }
        private void OnOutputUpdate(IOEntity sourceEntity) {
            NextTick(() => {
                if (sourceEntity == null) return;
                ProcessSourceEntity(sourceEntity);
            }
            );
        }
        private void OnServerSave() {
            ServerMgr.Instance.StartCoroutine(ResetColorsWhileSaving());
        }
#endregion
#region Exposed Hooks
        private bool ChangeColorWasBlocked(IOEntity ioEntity, IOSlot slot, WireColour color) {
            return Interface.CallHook("OnDynamicWireColorChange", ioEntity, slot, color) is false;
        }
#endregion
#region Helper Methods
        private IOSlot GetConnectedSourceSlot(IOSlot destinationSlot, out IOEntity sourceEntity) {
            sourceEntity = destinationSlot.connectedTo.Get();
            if (sourceEntity == null) return null;
            return sourceEntity.outputs.ElementAtOrDefault(destinationSlot.connectedToSlot);
        }
        private IOSlot GetConnectedDestinationSlot(IOSlot sourceSlot, out IOEntity destinationEntity) {
            destinationEntity = sourceSlot.connectedTo.Get();
            if (destinationEntity == null) return null;
            return destinationEntity.inputs.ElementAtOrDefault(sourceSlot.connectedToSlot);
        }
        private void CopySourceSlotColorsToDestinationSlots(IOEntity sourceEntity) {
            // This fixes an issue where loading a save does not restore the input slot colors.// This workaround updates the input slot colors to match the output colors when the plugin loads.// Without this workaround, we can't use the input colors to know which color to revert back to.foreach (var sourceSlot in sourceEntity.outputs)
            {
                var destinationSlot = GetConnectedDestinationSlot(sourceSlot, out _);
                if (destinationSlot == null) continue;
                // Note: This intentionally does not check permissions or call a hook because:
                //   a) It shouldn't be necessary.//   b) It would require that other parts of the plugin do the same checks.// This can be changed if it turns out that some other plugin is using the destination slot color for special reasons.if (destinationSlot.wireColour == WireColour.Gray)
                {
                    destinationSlot.wireColour = sourceSlot.wireColour;
                }
            }
        }
        private bool EntityHasPermission(IOEntity ioEntity) {
            if (ioEntity.OwnerID == 0) return _config.AppliesToUnownedEntities;
            if (!_config.RequiresPermission) return true;
            return permission.UserHasPermission(ioEntity.OwnerID.ToString(), PermissionUse);
        }
        private bool EitherEntityHasPermission(IOEntity ioEntity1, IOEntity ioEntity2, string perm) {
            return EntityHasPermission(ioEntity1) || EntityHasPermission(ioEntity2);
        }
        private void ChangeSlotColor(IOEntity ioEntity, IOSlot slot, WireColour color, bool networkUpdate) {
            if (slot.wireColour == color || ChangeColorWasBlocked(ioEntity, slot, color)) return;
            slot.wireColour = color;
            if (networkUpdate) {
                ioEntity.SendNetworkUpdate();
            }
        }
        private void SetupAllEntities(bool networkUpdate, bool fixDestinationColor) {
            foreach (var entity in BaseNetworkable.serverEntities) {
                var ioEntity = entity as IOEntity;
                if (ioEntity == null) continue;
                if (fixDestinationColor) {
                    CopySourceSlotColorsToDestinationSlots(ioEntity);
                }
                ProcessSourceEntity(ioEntity, networkUpdate);
            }
        }
        private void ResetAllEntities(bool networkUpdate) {
            foreach (var entity in BaseNetworkable.serverEntities) {
                var destinationEntity = entity as IOEntity;
                if (destinationEntity == null) continue;
                foreach (var destinationSlot in destinationEntity.inputs) {
                    var sourceSlot = GetConnectedSourceSlot(destinationSlot, out var sourceEntity);
                    if (sourceSlot == null) continue;
                    ChangeSlotColor(sourceEntity, sourceSlot, destinationSlot.wireColour, networkUpdate);
                }
            }
        }
        private bool HasOtherMainInput(IOEntity ioEntity, IOSlot currentSlot) {
            foreach (var slot in ioEntity.inputs) {
                if (slot.type == currentSlot.type && slot.mainPowerSlot && slot != currentSlot) return true;
            }
            return false;
        }
        private bool SufficientPowerOrFluid(IOEntity destinationEntity, IOSlot destinationSlot, int inputAmount) {
            if (inputAmount == 0) return false;
            // Only electrical entities have the concept of "sufficient" power (could be wrong).if (destinationSlot.type != IOType.Electric)
            return true;
            if (inputAmount >= destinationEntity.ConsumptionAmount()) return true;
            // If not providing sufficient power, only change color if there are no other main power inputs.// This avoids dynamically coloring a toggle input, for example, unless that input is providing exactly 0.return HasOtherMainInput(destinationEntity, destinationSlot);
        }
        private void ProcessSourceEntity(IOEntity sourceEntity, bool networkUpdate = true) {
            foreach (var sourceSlot in sourceEntity.outputs) {
                if (sourceSlot.type != IOType.Electric && sourceSlot.type != IOType.Fluidic) continue;
                var destinationSlot = GetConnectedDestinationSlot(sourceSlot, out var destinationEntity);
                if (destinationSlot == null) continue;
                if (!EitherEntityHasPermission(sourceEntity, destinationEntity, PermissionUse)) continue;
                var inputAmount = sourceEntity.GetPassthroughAmount(destinationSlot.connectedToSlot);
                if (SufficientPowerOrFluid(destinationEntity, destinationSlot, inputAmount)) {
                    // Don't check for permission here since we want to be able to reset the color even if the player lost permission.ChangeSlotColor(sourceEntity, sourceSlot, destinationSlot.wireColour, networkUpdate);
                }
                else if (EitherEntityHasPermission(sourceEntity, destinationEntity, PermissionUse)) {
                    ChangeSlotColor(sourceEntity, sourceSlot, _config.GetInsufficientColorForType(sourceSlot.type), networkUpdate);
                }
            }
        }
        private IEnumerator ResetColorsWhileSaving() {
            // Reset colors so they save without modification, in case an ungraceful shutdown does not invoke Unload() before saving.TrackStart();
            ResetAllEntities(networkUpdate : false);
            TrackEnd();
            yield return WaitWhileSaving;
            // Restore dynamic colors, as if the plugin had just loaded.TrackStart();
            SetupAllEntities(networkUpdate : false, fixDestinationColor : false);
            TrackEnd();
        }
#endregion
#region Configuration
        private class Configuration : BaseConfiguration {
            [JsonProperty("InsufficientPowerColor")]
            [JsonConverter(typeof(StringEnumConverter))]
            public WireColour InsufficientPowerColor = WireColour.Red;
            [JsonProperty("InsufficientFluidColor")]
            [JsonConverter(typeof(StringEnumConverter))]
            public WireColour InsufficientFluidColor = WireColour.Red;
            [JsonProperty("RequiresPermission")]
            public bool RequiresPermission = true;
            [JsonProperty("AppliesToUnownedEntities")]
            public bool AppliesToUnownedEntities = false;
            public WireColour GetInsufficientColorForType(IOType ioType) {
                return ioType == IOType.Fluidic ? InsufficientFluidColor : InsufficientPowerColor;
            }
        }
        private Configuration GetDefaultConfig() => new();
#region Configuration Helpers
        private class BaseConfiguration {
            public string ToJson() => JsonConvert.SerializeObject(this);
            public Dictionary<string, object> ToDictionary() => JsonHelper.Deserialize(ToJson()) as Dictionary<string, object>;
        }
        private static class JsonHelper {
            public static object Deserialize(string json) => ToObject(JToken.Parse(json));
            private static object ToObject(JToken token) {
                switch (token.Type) {
                    case JTokenType.Object : return token.Children<JProperty>().ToDictionary(prop => prop.Name, prop => ToObject(prop.Value));
                    case JTokenType.Array : return token.Select(ToObject).ToList();
                    default : return ((JValue)token).Value;
                }
            }
        }
        private bool MaybeUpdateConfig(BaseConfiguration config) {
            var currentWithDefaults = config.ToDictionary();
            var currentRaw = Config.ToDictionary(x => x.Key, x => x.Value);
            return MaybeUpdateConfigDict(currentWithDefaults, currentRaw);
        }
        private bool MaybeUpdateConfigDict(Dictionary<string, object> currentWithDefaults, Dictionary<string, object> currentRaw) {
            var changed = false;
            foreach (var key in currentWithDefaults.Keys) {
                if (currentRaw.TryGetValue(key, out var currentRawValue)) {
                    var currentDictValue = currentRawValue as Dictionary<string, object>;
                    if (currentWithDefaults[key] is Dictionary<string, object> defaultDictValue) {
                        if (currentDictValue == null) {
                            currentRaw[key] = currentWithDefaults[key];
                            changed = true;
                        }
                        else if (MaybeUpdateConfigDict(defaultDictValue, currentDictValue)) {
                            changed = true;
                        }
                    }
                }
                else {
                    currentRaw[key] = currentWithDefaults[key];
                    changed = true;
                }
            }
            return changed;
        }
        protected override void LoadDefaultConfig() => _config = GetDefaultConfig();
        protected override void LoadConfig() {
            base.LoadConfig();
            try {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) {
                    throw new JsonException();
                }
                if (MaybeUpdateConfig(_config)) {
                    LogWarning("Configuration appears to be outdated; updating and saving");
                    SaveConfig();
                }
            }
            catch (Exception e) {
                LogError(e.Message);
                LogWarning($"Configuration file {Name}.json is invalid; using defaults");
                LoadDefaultConfig();
            }
        }
        protected override void SaveConfig() {
            Log($"Configuration changes saved to {Name}.json");
            Config.WriteObject(_config, true);
        }
#endregion
#endregion
    }
}

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