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

FREE NoDecay : 1.0.99 1.0.99

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
#region License (GPL v2)
/*
    NoDecay - Scales or disables decay of items for Rust by Facepunch
    Copyright (c) 2020 RFC1920 <desolationoutpostpve@gmail.com>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License v2.0.This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the
    GNU General Public License for more details.You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.Optionally you can also view the license at <http://www.gnu.org/licenses/>.*/
#endregion License (GPL v2)
using HarmonyLib;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("NoDecay", "RFC1920", "1.0.99", ResourceId = 1160)]
    //Original Credit to Deicide666ra/Piarb and Diesel_42o
    //Thanks to Deicide666ra for allowing me to continue his work on this plugin
    [Description("Scales or disables decay of items")]
    internal class NoDecay : RustPlugin {
        private ConfigData configData;
        private bool enabled = true;
#region main
        private Dictionary<string, long> lastConnected = new();
        private List<ulong> disabled = new();
        private Dictionary<string, List<string>> entityinfo = new();
        private int targetLayer = LayerMask.GetMask("Construction", "Construction Trigger", "Trigger", "Deployed");
        private const string permNoDecayUse = "nodecay.use";
        private const string permNoDecayAdmin = "nodecay.admin";
        private const string TCOVR = "nodecay.overlay";
        [PluginReference]
        private readonly Plugin ZoneManager, GridAPI;
#region Message
        private string Lang(string key, string id = null, params object[] args) => string.Format(lang.GetMessage(key, this, id), args);
        private void Message(IPlayer player, string key, params object[] args) => player.Message(Lang(key, player.Id, args));
        private void LMessage(IPlayer player, string key, params object[] args) => player.Reply(Lang(key, player.Id, args));
        protected override void LoadDefaultMessages() {
            lang.RegisterMessages(new Dictionary<string, string> {
                ["ndisoff"]
                = "NoDecay has been turned OFF for your owned entities and buildings", ["ndison"] = "NoDecay has been turned ON for your owned entities and buildings", ["ndstatus"] = "NoDecay enabled set to {0}", ["nddebug"] = "Debug logging set to {0}", ["perm"] = "You have permission to use NoDecay.", ["noperm"] = "You DO NOT have permission to use NoDecay.", ["protby"] = "Protected by NoDecay", ["ndsettings"] = "NoDecay current settings:\n  Multipliers:"
            }
            , this);
        }
#endregion
#region Harmony
        // Prevents materials consumption for upkeep
        [AutoPatch]
        [HarmonyPatch(typeof(BuildingPrivlidge), "PurchaseUpkeepTime", new Type[] {
            typeof(DecayEntity), typeof(float)
        }
        )] public static class UpkeepPatch {
            [HarmonyPrefix]
            private static bool Prefix(ref float __result, ref DecayEntity entity, ref float deltaTime) {
                if ((bool)Interface.Call("NoDecayGet", entity?.OwnerID, true)) {
                    __result = 0;
                    return false;
                }
                return true;
            }
        }
        // Prevents wallpaper decay
        [AutoPatch]
        [HarmonyPatch(typeof(BuildingBlock), "DamageWallpaper", new Type[] {
            typeof(float), typeof(int)
        }
        )] public static class PaperPatch {
            [HarmonyPrefix]
            private static bool Prefix(BuildingBlock __instance, float totalDamage, int side) {
                if (side == 0) {
                    Interface.Call("NoDecayLogHook", $"Disabling wallpaper decay for {__instance.net.ID.Value}:{__instance?.OwnerID}");
                    return false;
                }
                return true;
            }
        }
#endregion Harmony
        private void Init() {
            AddCovalenceCommand("nodecay", "CmdInfo");
            permission.RegisterPermission(permNoDecayUse, this);
            permission.RegisterPermission(permNoDecayAdmin, this);
            LoadData();
            if (entityinfo.Count == 0) UpdateEnts();
        }
        private void Unload() {
            foreach (BasePlayer player in BasePlayer.activePlayerList) {
                CuiHelper.DestroyUi(player, TCOVR);
            }
        }
        private void OnServerInitialized() {
            // Workaround for no decay on horses, even if set to decay here
            if (configData.multipliers["horse"] > 0) {
                float newdecaytime = (180f / configData.multipliers["horse"]) - 180f;
                FieldInfo nextDecayTime = typeof(RidableHorse).GetField("nextDecayTime", (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
                foreach (RidableHorse horse in Resources.FindObjectsOfTypeAll<RidableHorse>()) {
                    if (horse is null) continue;
                    try {
                        float nextDecayTimeValue = (float)nextDecayTime?.GetValue(horse);
                        DoLog($"Got RidableHorse nextDecayTimeValue of {nextDecayTimeValue}");
                        if (newdecaytime > 0 & nextDecayTimeValue < newdecaytime) {
                            DoLog($"Adding {Math.Floor(newdecaytime)} minutes of decay time to horse {horse.net.ID}, now {Math.Floor(180f + newdecaytime)} minutes", true);
                            if (nextDecayTimeValue < Time.time) {
                                nextDecayTime?.SetValue(horse, Time.time + 5f);
                            }
                            else {
                                nextDecayTime?.SetValue(horse, nextDecayTimeValue + newdecaytime);
                            }
                        }
                        else if (newdecaytime > 0) {
                            DoLog($"Subtracting {Math.Abs(Math.Floor(newdecaytime))} minutes of decay time from horse {horse.net.ID}, now {Math.Floor(180f + newdecaytime)} minutes", true);
                            nextDecayTime?.SetValue(horse, nextDecayTimeValue + newdecaytime);
                        }
                    }
                    catch {
                    }
                }
            }
        }
        private object CanLootEntity(BasePlayer player, StorageContainer container) {
            if (!player.userID.IsSteamId()) return null;
            if (!configData.Global.disableLootWarning) return null;
            if (!permission.UserHasPermission(player.UserIDString, permNoDecayUse) && configData.Global.usePermission) return null;
            if (container == null) return null;
            BuildingPrivlidge privs = container.GetComponentInParent<BuildingPrivlidge>();
            if (privs != null && configData.Global.EnableGui) TcOverlay(player);
            return null;
        }
        private void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity) {
            if (!player.userID.IsSteamId()) return;
            CuiHelper.DestroyUi(player, TCOVR);
        }
        private void TcOverlay(BasePlayer player) {
            CuiHelper.DestroyUi(player, TCOVR);
            CuiElementContainer container = UI.Container(TCOVR, UI.Color("3E3C37", 1f), "0.651 0.604", "0.946 0.6365", true, "Overlay");
            UI.Label(ref container, TCOVR, UI.Color("#cacaca", 1f), Lang("protby"), 14, "0 0", "1 1");
            CuiHelper.AddUi(player, container);
        }
        private void Loaded() => LoadConfigVariables();
        private void OnEntitySaved(BuildingPrivlidge buildingPrivilege, BaseNetworkable.SaveInfo saveInfo) {
            if (configData.Global.disableWarning) {
                if (configData.Global.usePermission) {
                    string owner = buildingPrivilege.OwnerID.ToString();
                    if (permission.UserHasPermission(owner, permNoDecayUse) || owner == "0") {
                        if (owner != "0") {
                            DoLog($"TC owner {owner} has NoDecay permission!");
                        }
                    }
                    else {
                        return;
                    }
                }
                if (disabled.Contains(buildingPrivilege.OwnerID)) {
                    DoLog($"TC owner {buildingPrivilege.OwnerID} has disabled NoDecay.");
                    return;
                }
                saveInfo.msg.buildingPrivilege.protectedMinutes = configData.Global.protectedDisplayTime;
                saveInfo.msg.buildingPrivilege.upkeepPeriodMinutes = configData.Global.protectedDisplayTime;
            }
        }
        private void OnUserConnected(IPlayer player) => OnUserDisconnected(player);
        private void OnUserDisconnected(IPlayer player) {
            lastConnected[player.Id] = ToEpochTime(DateTime.UtcNow);
            SaveData();
        }
        private void LoadData() {
            entityinfo = Interface.GetMod().DataFileSystem.ReadObject<Dictionary<string, List<string>>>(Name + "/entityinfo");
            lastConnected = Interface.GetMod().DataFileSystem.ReadObject<Dictionary<string, long>>(Name + "/lastconnected");
            disabled = Interface.GetMod().DataFileSystem.ReadObject<List<ulong>>(Name + "/disabled");
        }
        private void SaveData() {
            Interface.GetMod().DataFileSystem.WriteObject(Name + "/entityinfo", entityinfo);
            Interface.GetMod().DataFileSystem.WriteObject(Name + "/lastconnected", lastConnected);
            Interface.GetMod().DataFileSystem.WriteObject(Name + "/disabled", disabled);
        }
        // Heal damage to entities over time since there may be no other way with decay disabled.private object OnDecayDamage(DecayEntity entity)
        {
            if (!enabled) return null;
            if (!(configData.Global.healBuildings || configData.Global.healEntities)) return null;
            //float single = Time.time - entity.lastDecayTick;
            if (entity == null) return null;
            if (entity?.OwnerID == 0) return null;
            if (entity.health == entity.MaxHealth()) return null;
            if (!CheckPerm(entity, entity?.OwnerID.ToString())) return null;
            float entityHealAmount = entity.MaxHealth() * configData.Global.healPercentage;
            if (entity is BuildingBlock block && configData.Global.healBuildings) {
                if (configData.Global.cupboardCheckEntity && !CheckCupboardBlock(block)) {
                    DoLog($"[NoHeal] Skipping healing for {entity?.ShortPrefabName} owned by {entity?.OwnerID} – No TC nearby.");
                    return null;
                }
                DoLog($"Healing damage to {entity?.ShortPrefabName}/{block?.grade} owned by {entity?.OwnerID} (amount={entityHealAmount}).Current health: {entity.health}");
                entity?.Heal(entityHealAmount);
                return true;
            }
            else if (configData.Global.healEntities) {
                if (configData.Global.cupboardCheckEntity && !CheckCupboardEntity(entity)) {
                    DoLog($"[NoHeal] Skipping healing for {entity?.ShortPrefabName} owned by {entity?.OwnerID} – No TC nearby.");
                    return null;
                }
                DoLog($"Healing damage to {entity?.ShortPrefabName} owned by {entity?.OwnerID} (amount={entityHealAmount}).Current health {entity?.health}");
                entity?.Heal(entityHealAmount);
                return true;
            }
            return null;
        }
        //private object OnDecayHeal(DecayEntity entity)
        private bool CheckPerm(BaseCombatEntity entity, string owner) {
            string entity_name = entity.LookupPrefab().name.ToLower();
            ulong bpOwner = 0;
            if (configData.Global.usePermission) {
                if (permission.UserHasPermission(owner, permNoDecayUse) || owner == "0") {
                    if (owner != "0") {
                        DoLog($"{entity_name} owner {owner} has NoDecay permission!");
                    }
                }
                else if (configData.Global.useTCOwnerToCheckPermission) {
                    BuildingPrivlidge bp = entity?.GetBuildingPrivilege();
                    if (bp?.OwnerID != 0 && permission.UserHasPermission(bp?.OwnerID.ToString(), permNoDecayUse)) {
                        bpOwner = bp.OwnerID;
                        DoLog($"{entity_name} TC owner {bp?.OwnerID} has NoDecay permission!");
                    }
                }
                else {
                    DoLog($"{entity_name} owner {owner} does NOT have NoDecay permission.Standard decay in effect.");
                    return false;
                }
                if (disabled.Contains(entity.OwnerID)) {
                    DoLog($"Entity owner {entity.OwnerID} has disabled NoDecay.");
                    return false;
                }
                else if (bpOwner > 0 && disabled.Contains(bpOwner)) {
                    DoLog($"Entity TC owner {bpOwner} has disabled NoDecay.");
                    return false;
                }
            }
            if (configData.Global.protectedDays > 0 && entity.OwnerID > 0) {
                lastConnected.TryGetValue(entity.OwnerID.ToString(), out long lc);
                if (lc > 0) {
                    long now = ToEpochTime(DateTime.UtcNow);
                    float days = Math.Abs((now - lc) / 86400);
                    bool friend = false;
                    if (configData.Global.useBPAuthListForProtectedDays) {
                        BuildingPrivlidge bp = entity?.GetBuildingPrivilege();
                        if (bp != null) {
                            foreach (ProtoBuf.PlayerNameID p in bp.authorizedPlayers) {
                                if (p?.userid == entity.OwnerID) continue;
                                lastConnected.TryGetValue(p.userid.ToString(), out long lastcon);
                                days = Math.Abs((now - lastcon) / 86400);
                                if (days <= configData.Global.protectedDays) {
                                    friend = true;
                                    break;
                                }
                            }
                        }
                    }
                    if (days > configData.Global.protectedDays) {
                        DoLog($"Allowing decay for owner offline for {days} day(s).Limit is {configData.Global.protectedDays}.");
                        return false;
                    }
                    else if (friend) {
                        string day = days.ToString();
                        if (days < 1) day = "less than 1";
                        DoLog($"Friend authorized on local TC was last connected {day} day(s) ago and is still protected...");
                    }
                    else {
                        string day = days.ToString();
                        if (days < 1) day = "less than 1";
                        DoLog($"Owner was last connected {day} day(s) ago and is still protected...");
                    }
                }
            }
            return true;
        }
        //private object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo)
        private object OnEntityTakeDamage(DecayEntity entity, HitInfo hitInfo) {
            if (!enabled) return null;
            if (entity == null || hitInfo == null) return null;
            if (hitInfo.damageTypes.GetMajorityDamageType() != Rust.DamageType.Decay) return null;
            float damageAmount = 0f;
            DateTime tick = DateTime.Now;
            string entity_name = entity.LookupPrefab().name.ToLower();
            //Puts($"Decay Entity: {entity_name}");
            string owner = entity.OwnerID.ToString();
            bool mundane = false;
            bool isBlock = false;
            if (!CheckPerm(entity, owner)) return null;
            try {
                float before = hitInfo.damageTypes.Get(Rust.DamageType.Decay);
                if (entity is BuildingBlock) {
                    damageAmount = ProcessBuildingDamage(entity, before);
                    isBlock = true;
                }
                else if (entity.GetComponent<ModularCar>() != null) {
                    ModularCarGarage garage = entity.GetComponentInParent<ModularCarGarage>();
                    if (garage != null && configData.Global.protectVehicleOnLift) {
                        return true;
                    }
                }
                else {
                    // Main check for non-building entities/deployables
                    KeyValuePair<string, List<string>> entity_type = entityinfo.FirstOrDefault(x => x.Value.Contains(entity_name));
                    if (!entity_type.Equals(default(KeyValuePair<string, List<string>>))) {
                        if (entity_type.Key.Equals("vehicle") || entity_type.Key.Equals("boat") || entity_type.Key.Equals("balloon") || entity_type.Key.Equals("horse")) {
                            mundane = true;
                        }
                        DoLog($"Found {entity_name} listed in {entity_type.Key}", mundane);
                        if (configData.multipliers.ContainsKey(entity_type.Key)) {
                            damageAmount = before * configData.multipliers[entity_type.Key];
                        }
                    }
                }
                // Check non-building entities for cupboard in range
                if (configData.Global.requireCupboard && configData.Global.cupboardCheckEntity && !isBlock) {
                    // Verify that we should check for a cupboard and ensure that one exists.// If so, multiplier will be set to entityCupboardMultiplier.DoLog("NoDecay checking for local cupboard.", mundane);
                    if (CheckCupboardEntity(entity, mundane)) {
                        damageAmount = before * configData.multipliers["entityCupboard"];
                    }
                }
                string pos = "";
                string zones = "";
                bool inzone = false;
                string[] zonedata = GetEntityZones(entity);
                if (zonedata.Length > 0) {
                    inzone = true;
                    bool skipCat = false;
                    string cat = entityinfo.FirstOrDefault(y => y.Value.Contains(entity_name)).Key;
                    if (configData.Global.overrideZoneManager.Count > 0 && configData.Global.overrideZoneManager.Contains(cat)) {
                        DoLog($"Skipping zone check for {entity_name} based on category {cat} exclusion.");
                        skipCat = true;
                    }
                    if (ZoneManager && configData.Global.honorZoneManagerFlag && !skipCat) {
                        foreach (string zoneId in zonedata) {
                            if ((bool)ZoneManager?.Call("HasFlag", zoneId, "nodecay")) {
                                DoLog($"{entity_name} in zone {zoneId}, which has the nodecay flag.Setting damage to 0.");
                                damageAmount = 0f;
                            }
                        }
                    }
                }
                if (configData.Debug.logPosition) {
                    pos = $" at {PositionToGrid(entity.transform.position)} {entity.transform.position}";
                    zones = string.Join(",", zonedata);
                }
                NextTick(() => {
                    DoLog($"Decay [{entity_name}{pos} - {entity.net.ID}] before: {before} after: {damageAmount}, item health {entity.health}", mundane);
                    if (inzone) {
                        DoLog($"Decay [{entity_name}] in ZoneManager zone(s): {zones}", mundane);
                    }
                    entity.health -= damageAmount;
                    if (entity.health == 0 && configData.Global.DestroyOnZero) {
                        DoLog($"Entity {entity_name}{pos} completely decayed - destroying!", mundane);
                        if (entity == null) return;
                        entity.Kill(BaseNetworkable.DestroyMode.Gib);
                    }
                }
                );
                return true;
                // Cancels this hook for any of the entities above unless unsupported (for decay only).}
                finally {
                    double ms = (DateTime.Now - tick).TotalMilliseconds;
                    if (ms > configData.Global.warningTime || configData.Debug.outputMundane) Puts($"NoDecay.OnEntityTakeDamage on {entity_name} took {ms} ms to execute.");
                }
            }
            private void OnEntitySpawned(BaseVehicle horse) {
                // Workaround for no decay on horses, even if set to decay here
                if (horse == null) return;
                if (horse is not RidableHorse) return;
                if (horse.net == null) return;
                if (configData.multipliers["horse"] > 0) {
                    float newdecaytime = (180f / configData.multipliers["horse"]) - 180f;
                    FieldInfo nextDecayTime = typeof(RidableHorse).GetField("nextDecayTime", (BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic));
                    float nextDecayTimeValue = (float)nextDecayTime?.GetValue(horse);
                    DoLog($"Got RidableHorse nextDecayTimeValue of {nextDecayTimeValue} and would like to set it to at least {newdecaytime}");
                    if (newdecaytime > 0f) {
                        DoLog($"Adding {Math.Floor(newdecaytime)} minutes of decay time to horse {horse.net.ID}, now {Math.Floor(180f + newdecaytime)} minutes");
                        if (nextDecayTimeValue < Time.time) {
                            nextDecayTime?.SetValue(horse, Time.time + 5f);
                        }
                        else {
                            nextDecayTime?.SetValue(horse, nextDecayTimeValue + newdecaytime);
                        }
                    }
                    else {
                        DoLog($"Subtracting {Math.Abs(Math.Floor(newdecaytime))} minutes of decay time from horse {horse.net.ID}, now {Math.Floor(180f + newdecaytime)} minutes");
                        nextDecayTime?.SetValue(horse, nextDecayTimeValue + newdecaytime);
                    }
                    //horse.SetDecayActive(true);
                }
            }
            // Workaround for car chassis that won't die
            private void OnEntityDeath(ModularCar car, HitInfo hitinfo) {
                DoLog("Car died!  Checking for associated parts...");
                List<BaseEntity> ents = new();
                Vis.Entities(car.transform.position, 1f, ents);
                foreach (BaseEntity ent in ents) {
                    if (ent == null) continue;
                    if (ent.name.Contains("module_car_spawned") && !ent.IsDestroyed) {
                        DoLog($"Killing {ent.ShortPrefabName}");
                        ent?.Kill(BaseNetworkable.DestroyMode.Gib);
                    }
                }
            }
            private void OnNewSave() {
                UpdateEnts();
            }
            private void UpdateEnts() {
                entityinfo["balloon"] = new List<string>();
                entityinfo["barricade"] = new List<string>();
                entityinfo["bbq"] = new List<string>();
                entityinfo["boat"] = new List<string>();
                entityinfo["box"] = new List<string>();
                entityinfo["building"] = new List<string>();
                entityinfo["campfire"] = new List<string>();
                entityinfo["candle"] = new List<string>();
                entityinfo["deployables"] = new List<string>();
                entityinfo["furnace"] = new List<string>();
                entityinfo["horse"] = new List<string>();
                entityinfo["minicopter"] = new List<string>();
                entityinfo["attackcopter"] = new List<string>();
                entityinfo["sam"] = new List<string>();
                entityinfo["scrapcopter"] = new List<string>();
                entityinfo["sedan"] = new List<string>();
                entityinfo["trap"] = new List<string>();
                entityinfo["vehicle"] = new List<string>();
                entityinfo["watchtower"] = new List<string>();
                entityinfo["water"] = new List<string>();
                entityinfo["stonewall"] = new List<string>();
                entityinfo["woodwall"] = new List<string>();
                entityinfo["mining"] = new List<string>();
                List<string> names = new();
                foreach (BaseCombatEntity ent in Resources.FindObjectsOfTypeAll<BaseCombatEntity>())  //foreach (BaseCombatEntity ent in UnityEngine.Object.FindObjectsOfType<BaseCombatEntity>())
                {
                    string entity_name = ent.ShortPrefabName?.ToLower();
                    DoLog($"Checking {entity_name}");
                    if (entity_name == "cupboard.tool.deployed") continue;
                    if (entity_name == null) continue;
                    if (names.Contains(entity_name)) continue;
                    // Saves 20-30 seconds of processing time.names.Add(entity_name);
                    if (entity_name.Contains("campfire") || entity_name.Contains("skull_fire_pit")) {
                        entityinfo["campfire"].Add(entity_name);
                    }
                    else if (entity_name.Contains("box") || entity_name.Contains("coffin")) {
                        entityinfo["box"].Add(entity_name);
                    }
                    else if (entity_name.Contains("shutter") || (entity_name.Contains("door") && !entity_name.Contains("doorway")) || entity_name.Contains("hatch") || entity_name.Contains("garagedoor") || entity_name.Contains("bars") || entity_name.Contains("netting") || entity_name.Contains("cell") || entity_name.Contains("fence") || entity_name.Contains("reinforced") || entity_name.Contains("composter") || entity_name.Contains("workbench") || entity_name.Contains("shopfront") || entity_name.Contains("grill") || entity_name.Contains("wall.window.bars")) {
                        entityinfo["building"].Add(entity_name);
                    }
                    else if (entity_name.Contains("deployed") || entity_name.Contains("speaker") || entity_name.Contains("strobe") || entity_name.Contains("fog") || entity_name.Contains("graveyard") || entity_name.Contains("jackolantern") || entity_name.Contains("hatchet")) {
                        entityinfo["deployables"].Add(entity_name);
                    }
                    else if (entity_name.Contains("candle")) {
                        entityinfo["candle"].Add(entity_name);
                    }
                    else if (entity_name.Contains("furnace")) {
                        entityinfo["furnace"].Add(entity_name);
                    }
                    else if (entity_name.Contains("sedan")) {
                        entityinfo["sedan"].Add(entity_name);
                    }
                    else if (entity_name.Contains("sam_static")) {
                        entityinfo["sam"].Add(entity_name);
                    }
                    else if (entity_name.Contains("balloon")) {
                        entityinfo["balloon"].Add(entity_name);
                    }
                    else if (entity_name.Contains("bbq")) {
                        entityinfo["bbq"].Add(entity_name);
                    }
                    else if (entity_name.Contains("watchtower")) {
                        entityinfo["watchtower"].Add(entity_name);
                    }
                    else if (entity_name.Contains("water_catcher") || entity_name.Equals("waterbarrel")) {
                        entityinfo["water"].Add(entity_name);
                    }
                    else if (entity_name.Contains("beartrap") || entity_name.Contains("landmine") || entity_name.Contains("spikes.floor")) {
                        entityinfo["trap"].Add(entity_name);
                    }
                    else if (entity_name.Contains("barricade")) {
                        entityinfo["barricade"].Add(entity_name);
                    }
                    else if (entity_name.Contains("external.high.stone")) {
                        entityinfo["stonewall"].Add(entity_name);
                    }
                    else if (entity_name.Contains("external.high.wood") || entity_name.Contains("external.high.ice") || entity_name.Contains("icewall")) {
                        entityinfo["woodwall"].Add(entity_name);
                    }
                    else if (entity_name.Contains("mining")) {
                        entityinfo["mining"].Add(entity_name);
                    }
                    else if (entity_name.Contains("rowboat") || entity_name.Contains("rhib") || entity_name.Contains("kayak") || entity_name.Contains("submarine")) {
                        entityinfo["boat"].Add(entity_name);
                    }
                    else if (entity_name.Contains("minicopter")) {
                        entityinfo["minicopter"].Add(entity_name);
                    }
                    else if (entity_name.Contains("attackhelicopter")) {
                        entityinfo["attackcopter"].Add(entity_name);
                    }
                    else if (entity_name.Contains("horse")) {
                        entityinfo["horse"].Add(entity_name);
                    }
                    else if (entity_name.Contains("scraptransport")) {
                        entityinfo["scrapcopter"].Add(entity_name);
                    }
                    else if (entity_name.Contains("vehicle") || entity_name.Contains("chassis_") || entity_name.Contains("1module_") || entity_name.Contains("2module_") || entity_name.Contains("3module_") || entity_name.Contains("snowmobile") || entity_name.Contains("4module_")) {
                        entityinfo["vehicle"].Add(entity_name);
                    }
                }
                SaveData();
            }
            private float ProcessBuildingDamage(BaseEntity entity, float before) {
                BuildingBlock block = entity as BuildingBlock;
                float multiplier = 1.0f;
                bool isHighWall = block.LookupPrefab().name.Contains("wall.external");
                bool isHighGate = block.LookupPrefab().name.Contains("gates.external");
                string type = null;
                bool hascup = true;
                // Assume true (has cupboard or we don't require one)
                DoLog($"NoDecay checking for block damage to {block.LookupPrefab().name}");
                // Verify that we should check for a cupboard and ensure that one exists.// If not, multiplier will be standard of 1.0f (hascup true).if (configData.Global.requireCupboard)
                {
                    DoLog("NoDecay checking for local cupboard.");
                    hascup = CheckCupboardBlock(block, entity.LookupPrefab().name, block.grade.ToString().ToLower());
                }
                else {
                    DoLog("NoDecay not checking for local cupboard.");
                }
                switch (block.grade) {
                    case BuildingGrade.Enum.Twigs : if (hascup) multiplier = configData.multipliers["twig"];
                    type = "twig";
                    break;
                    case BuildingGrade.Enum.Wood : if (isHighWall) {
                        if (hascup) multiplier = configData.multipliers["highWoodWall"];
                        type = "high wood wall";
                    }
                    else if (isHighGate) {
                        if (hascup) multiplier = configData.multipliers["highWoodWall"];
                        type = "high wood gate";
                    }
                    else {
                        if (hascup) multiplier = configData.multipliers["wood"];
                        type = "wood";
                    }
                    break;
                    case BuildingGrade.Enum.Stone : if (isHighWall) {
                        if (hascup) multiplier = configData.multipliers["highStoneWall"];
                        type = "high stone wall";
                    }
                    else if (isHighGate) {
                        if (hascup) multiplier = configData.multipliers["highStoneWall"];
                        type = "high stone gate";
                    }
                    else {
                        if (hascup) multiplier = configData.multipliers["stone"];
                        type = "stone";
                    }
                    break;
                    case BuildingGrade.Enum.Metal : if (hascup) multiplier = configData.multipliers["sheet"];
                    type = "sheet";
                    break;
                    case BuildingGrade.Enum.TopTier : if (hascup) multiplier = configData.multipliers["armored"];
                    type = "armored";
                    break;
                    default : DoLog($"Decay ({type}) has unknown grade type.");
                    type = "unknown";
                    break;
                }
                float damageAmount = before * multiplier;
                DoLog($"Decay ({type}) before: {before} after: {damageAmount}");
                return damageAmount;
            }
            public BuildingPrivlidge GetBuildingPrivilege(BuildingManager.Building building, BuildingBlock block = null) {
                BuildingPrivlidge buildingPrivlidge = null;
                if (building.HasBuildingPrivileges()) {
                    for (int i = 0; i < building.buildingPrivileges.Count; i++) {
                        BuildingPrivlidge item = building.buildingPrivileges[i];
                        if (!(item == null) && item.IsOlderThan(buildingPrivlidge)) {
                            DoLog("CheckCupboardBlock:     Found block connected to cupboard!");
                            buildingPrivlidge = item;
                        }
                    }
                }
                else if (configData.Global.cupboardRange > 0) {
                    // Disconnected building with no TC, but possibly in cupboard range
                    List<BuildingPrivlidge> cups = new();
                    Vis.Entities(block.transform.position, configData.Global.cupboardRange, cups, targetLayer);
                    foreach (BuildingPrivlidge cup in cups) {
                        foreach (ProtoBuf.PlayerNameID p in cup.authorizedPlayers.ToArray()) {
                            if (p.userid == block.OwnerID) {
                                DoLog("CheckCupboardBlock:     Found block in range of cupboard!");
                                return cup;
                            }
                        }
                    }
                }
                return buildingPrivlidge;
            }
            // Check that a building block is owned by/attached to a cupboard
            private bool CheckCupboardBlock(BuildingBlock block, string ename = "unknown", string grade = "") {
                BuildingManager.Building building = block.GetBuilding();
                DoLog($"CheckCupboardBlock:   Checking for cupboard connected to {grade} {ename}.");
                if (building != null) {
                    // cupboard overlap.Block safe from decay.//if (building.GetDominatingBuildingPrivilege() == null)
                    if (GetBuildingPrivilege(building, block) == null) {
                        DoLog("CheckCupboardBlock:     Block NOT owned by cupboard!");
                        return false;
                    }
                    DoLog("CheckCupboardBlock:     Block owned by cupboard!");
                    return true;
                }
                else {
                    DoLog("CheckCupboardBlock:     Unable to find cupboard.");
                    return false;
                }
            }
            // Non-block entity check
            private bool CheckCupboardEntity(BaseEntity entity, bool mundane = false) {
                if (configData.Global.useCupboardRange) {
                    // This is the old way using cupboard distance instead of BP.It's less efficient but some may have made use of this range concept, so here it is.List<BuildingPrivlidge> cups = new();
                    Vis.Entities(entity.transform.position, configData.Global.cupboardRange, cups, targetLayer);
                    DoLog($"CheckCupboardEntity:   Checking for cupboard within {configData.Global.cupboardRange}m of {entity.ShortPrefabName}.", mundane);
                    if (cups.Count > 0) {
                        // cupboard overlap.Entity safe from decay.DoLog("CheckCupboardEntity:     Found entity layer in range of cupboard!", mundane);
                        return true;
                    }
                    DoLog("CheckCupboardEntity:     Unable to find entity layer in range of cupboard.", mundane);
                    return false;
                }
                // New method of simply checking for the entity's building privilege.DoLog($"CheckCupboardEntity:   Checking for building privilege for {entity.ShortPrefabName}.", mundane);
                BuildingPrivlidge tc = entity.GetBuildingPrivilege();
                if (tc != null) {
                    // cupboard overlap.Entity safe from decay.DoLog("CheckCupboardEntity:     Found entity layer in range of cupboard!", mundane);
                    return true;
                }
                DoLog("CheckCupboardEntity:     Unable to find entity layer in range of cupboard.", mundane);
                return false;
            }
            // Prevent players from adding building resources to cupboard if so configured
            //private object CanMoveItem(Item item, PlayerInventory inventory, uint targetContainer, int targetSlot)
            private ItemContainer.CanAcceptResult? CanAcceptItem(ItemContainer container, Item item, int targetPos) {
                BaseEntity cup = container?.entityOwner;
                if (cup == null) return null;
                if (cup is not BuildingPrivlidge) return null;
                if (!(configData.Global.blockCupboardResources || configData.Global.blockCupboardWood)) return null;
                string res = item?.info?.shortname;
                DoLog($"Player trying to add {res} to a cupboard!");
                if (res.Equals("wood") && configData.Global.blockCupboardWood) {
                    DoLog($"Player blocked from adding {res} to a cupboard!");
                    return ItemContainer.CanAcceptResult.CannotAcceptRightNow;
                }
                else if (configData.Global.blockCupboardResources) {
                    if ((res.Equals("stones") && configData.Global.blockCupboardStone) || (res.Equals("metal.fragments") && configData.Global.blockCupboardMetal) || (res.Equals("metal.refined") && configData.Global.blockCupboardArmor)) {
                        DoLog($"Player blocked from adding {res} to a cupboard!");
                        return ItemContainer.CanAcceptResult.CannotAcceptRightNow;
                    }
                }
                return null;
            }
#endregion
#region command
            [Command("nodecay")]
            private void CmdInfo(IPlayer iplayer, string command, string[] args) {
                if ((permission.UserHasPermission(iplayer.Id, permNoDecayAdmin) && args.Length > 0) || iplayer.IsServer || iplayer.IsAdmin) {
                    switch (args[0]) {
                        case "enable" : enabled = !enabled;
                        Message(iplayer, "ndstatus", enabled.ToString());
                        SaveConfig();
                        return;
                        case "log" : configData.Debug.outputToRcon = !configData.Debug.outputToRcon;
                        Message(iplayer, "nddebug", configData.Debug.outputToRcon.ToString());
                        return;
                        case "update" : UpdateEnts();
                        return;
                        case "info" : string info = Lang("ndsettings");
                        info += "\n\tarmored: " + configData.multipliers["armored"].ToString();
                        info += "\n\tballoon: " + configData.multipliers["balloon"].ToString();
                        info += "\n\tbarricade: " + configData.multipliers["barricade"].ToString();
                        info += "\n\tbbq: " + configData.multipliers["bbq"].ToString();
                        info += "\n\tboat: " + configData.multipliers["boat"].ToString();
                        info += "\n\tbox: " + configData.multipliers["box"].ToString();
                        info += "\n\tbuilding: " + configData.multipliers["building"].ToString();
                        info += "\n\tcampfire" + configData.multipliers["campfire"].ToString();
                        info += "\n\tcandle" + configData.multipliers["candle"].ToString();
                        info += "\n\tdeployables: " + configData.multipliers["deployables"].ToString();
                        info += "\n\tentityCupboard: " + configData.multipliers["entityCupboard"].ToString();
                        info += "\n\tfurnace: " + configData.multipliers["furnace"].ToString();
                        info += "\n\thighWoodWall: " + configData.multipliers["highWoodWall"].ToString();
                        info += "\n\thighStoneWall: " + configData.multipliers["highStoneWall"].ToString();
                        info += "\n\thorse: " + configData.multipliers["horse"].ToString();
                        info += "\n\tminicopter: " + configData.multipliers["minicopter"].ToString();
                        info += "\n\tattackcopter: " + configData.multipliers["attackcopter"].ToString();
                        info += "\n\tscrapcopter: " + configData.multipliers["scrapcopter"].ToString();
                        info += "\n\tsam: " + configData.multipliers["sam"].ToString();
                        info += "\n\tsedan: " + configData.multipliers["sedan"].ToString();
                        info += "\n\tsheet: " + configData.multipliers["sheet"].ToString();
                        info += "\n\tstone: " + configData.multipliers["stone"].ToString();
                        info += "\n\ttrap: " + configData.multipliers["trap"].ToString();
                        info += "\n\ttwig: " + configData.multipliers["twig"].ToString();
                        info += "\n\tvehicle: " + configData.multipliers["vehicle"].ToString();
                        info += "\n\twatchtower: " + configData.multipliers["watchtower"].ToString();
                        info += "\n\twater: " + configData.multipliers["water"].ToString();
                        info += "\n\twood: " + configData.multipliers["wood"].ToString();
                        info += "\n\n\tEnabled: " + enabled.ToString();
                        info += "\n\tdisableWarning: " + configData.Global.disableWarning.ToString();
                        info += "\n\tprotectedDays: " + configData.Global.protectedDays.ToString();
                        info += "\n\tprotectVehicleOnLift: " + configData.Global.protectVehicleOnLift.ToString();
                        info += "\n\tusePermission: " + configData.Global.usePermission.ToString();
                        info += "\n\trequireCupboard: " + configData.Global.requireCupboard.ToString();
                        info += "\n\tCupboardEntity: " + configData.Global.cupboardCheckEntity.ToString();
                        info += "\n\tcupboardRange: " + configData.Global.cupboardRange.ToString();
                        info += "\n\tblockCupboardResources: " + configData.Global.blockCupboardResources.ToString();
                        info += "\n\tblockCupboardWood: " + configData.Global.blockCupboardWood.ToString();
                        info += "\n\tblockCupboardStone: " + configData.Global.blockCupboardStone.ToString();
                        info += "\n\tblockCupboardMetal: " + configData.Global.blockCupboardMetal.ToString();
                        info += "\n\tblockCupboardArmor: " + configData.Global.blockCupboardArmor.ToString();
                        Message(iplayer, info);
                        return;
                    }
                }
                if (iplayer.Id == "server_console") return;
                if (args.Length > 0) {
                    bool save = false;
                    ulong id = ulong.Parse(iplayer.Id);
                    switch (args[0]) {
                        case "off" : if (!disabled.Contains(id)) {
                            save = true;
                            disabled.Add(id);
                        }
                        Message(iplayer, "ndstatus", enabled.ToString());
                        if (permission.UserHasPermission(iplayer.Id, permNoDecayUse)) {
                            Message(iplayer, "perm");
                        }
                        else {
                            Message(iplayer, "noperm");
                        }
                        Message(iplayer, "ndisoff");
                        break;
                        case "on" : if (disabled.Contains(id)) {
                            save = true;
                            disabled.Remove(id);
                        }
                        Message(iplayer, "ndstatus", enabled.ToString());
                        if (permission.UserHasPermission(iplayer.Id, permNoDecayUse)) {
                            Message(iplayer, "perm");
                        }
                        else {
                            Message(iplayer, "noperm");
                        }
                        Message(iplayer, "ndison");
                        break;
                        case "?" : Message(iplayer, "ndstatus", enabled.ToString());
                        if (permission.UserHasPermission(iplayer.Id, permNoDecayUse)) {
                            Message(iplayer, "perm");
                        }
                        else {
                            Message(iplayer, "noperm");
                        }
                        if (disabled.Contains(id)) {
                            Message(iplayer, "ndisoff");
                        }
                        else {
                            Message(iplayer, "ndison");
                        }
                        break;
                    }
                    if (save) SaveData();
                }
            }
#endregion
#region inbound_hooks
            // Returns player status if playerid > 0
// ... [Code preview truncated due to length. Full source in attached file] ...

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