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

FREE FusedRecycler : 1.0.8 1.0.8

Нет прав для скачивания
C#:
/*
 * Copyright (c) 2026
 * Author Bazz3l
 * Discord bazz3l
 *
 * Fused Recycler cannot be copied, edited and/or (re)distributed without the express permission of the Author.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 *
 */

using System.Collections.Generic;
using Oxide.Core.Plugins;
using Newtonsoft.Json;
using UnityEngine;
using HarmonyLib;
using System;

namespace Oxide.Plugins;

[Info("Fused Recycler", "Bazz3l", "1.0.8")]
[Description("Recyclers will now require a fuse to recycle items.")]
internal class FusedRecycler : RustPlugin
{
    #region Fields

    private const string FUSEBOX_PREFAB = "assets/prefabs/io/electric/switches/fusebox/fusebox.prefab";
    private const string DENIED_PREFAB = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";
    private const float INITIALIZE_DELAY_INTERVAL = 30f;
    private const uint FUSEBOX_PREFAB_ID = 3622071578;
    
    private readonly Quaternion _localRotation = new(0f, -0.7071068f, 0, 0.7071068f);
    private readonly Vector3 _localPosition = new(-0.93f, -0.6f, 0.25f);
    private static ConfigData _configData;
    private static readonly object ObjTrue = true;
    private static readonly object ObjFalse = false;

    #endregion

    #region Lang

    protected override void LoadDefaultMessages()
    {
        lang.RegisterMessages(new Dictionary<string, string>
        {
            { LangKeys.NO_FUSE, "Please insert a fuse to power the Recycler." }
        }, this);
    }

    private static class LangKeys
    {
        public const string NO_FUSE = "NoFuse";
    }
    
    private void ShowPlayerToast(BasePlayer player, string key, params object[] args)
    {
        if (player?.net == null) return;
        player.ShowToast(0, string.Format(lang.GetMessage(key, this, player.UserIDString), args));
    }

    #endregion
    
    #region Config

    protected override void LoadDefaultConfig() => _configData = ConfigData.DefaultConfig();

    protected override void LoadConfig()
    {
        base.LoadConfig();

        try
        {
            _configData = Config.ReadObject<ConfigData>() ?? throw new JsonException();
            
            _configData.FuseUseAmount = Math.Clamp(_configData.FuseUseAmount, 1f, float.MaxValue);
        }
        catch(Exception e)
        {
            LoadDefaultConfig();
            PrintWarning("Loaded default config: {0}", e.Message);
        }
    }

    protected override void SaveConfig() => Config.WriteObject(_configData, true);

    private class ConfigData
    {
        [JsonProperty("Enable player placed only recyclers")]
        public bool EnablePlayerPlacedOnly;
        [JsonProperty("Fuse durability per recycle")]
        public float FuseUseAmount;
        
        public string ToJson() => JsonConvert.SerializeObject(this);

        public Dictionary<string, object> ToDictionary() => JsonConvert.DeserializeObject<Dictionary<string, object>>(ToJson());

        public static ConfigData DefaultConfig()
        {
            return new ConfigData
            {
                EnablePlayerPlacedOnly = false,
                FuseUseAmount = 1f
            };
        }
    }

    #endregion

    #region Oxide Hooks

    private void OnServerInitialized()
    {
        PrintWarning("please wait for all recyclers to initialize in {0} seconds.", INITIALIZE_DELAY_INTERVAL);
        
        timer.In(INITIALIZE_DELAY_INTERVAL, () =>
        {
            ModifyRecyclers();
            Subscribe(nameof(OnEntitySpawned));
            PrintWarning("all recyclers are now initialized.");
        });
    }

    private void Init() => Unsubscribe(nameof(OnEntitySpawned));

    private void Unload() => RevertRecyclers();

    private void OnEntitySpawned(Recycler recycler) => TryCreateElectricalRecycler(recycler);
        
    private object? OnRecyclerToggle(Recycler recycler, BasePlayer player)
    {
        if (recycler.IsOn())
            return null;
        
        ItemBasedFlowRestrictor? flowRestrictor = GetChildEntity<ItemBasedFlowRestrictor>(recycler);
        if (flowRestrictor == null) 
            return null;
        
        if (flowRestrictor.HasPassthroughItem()) 
            return null;
        
        ShowPlayerToast(player, LangKeys.NO_FUSE);
        Effect.server.Run(DENIED_PREFAB, recycler, posLocal: Vector3.zero, normLocal: Vector3.zero);
        return ObjFalse;
    }

    private object? CanMoveItem(Item item, PlayerInventory playerLoot, ItemContainerId targetContainer, int targetSlot, int amount)
    {
        ItemContainer? container = item.GetRootContainer();
        if (container?.entityOwner is not ItemBasedFlowRestrictor { prefabID: FUSEBOX_PREFAB_ID } flowRestrictor) 
            return null;
        
        return flowRestrictor.GetParentEntity() is Recycler recycler && recycler.IsOn() ? ObjTrue : null;
    }

    private void OnItemRemovedFromContainer(ItemContainer container, Item item)
    {
        if (container?.entityOwner is not ItemBasedFlowRestrictor { prefabID: FUSEBOX_PREFAB_ID } flowRestrictor) 
            return;
        
        if (flowRestrictor.GetParentEntity() is Recycler recycler && recycler.IsOn())
            recycler.StopRecycling();
    }
        
    #endregion

    #region Fused Recycler

    private void ModifyRecyclers()
    {
        foreach (BaseNetworkable nEntity in BaseNetworkable.serverEntities)
        {
            if (nEntity is Recycler { IsDestroyed: false } recycler)
                TryCreateElectricalRecycler(recycler);
        }
    }
    
    private void RevertRecyclers()
    {
        if (Rust.Application.isQuitting)
            return;
        
        foreach (BaseNetworkable nEntity in BaseNetworkable.serverEntities)
        {
            if (nEntity is Recycler { IsDestroyed: false } recycler) 
                TryRemoveElectricalRecycler(recycler);
        }
    }
    
    private void AttachFuseBox(Recycler recycler)
    {
        ItemBasedFlowRestrictor? fuseBox = GameManager.server.CreateEntity(FUSEBOX_PREFAB, recycler.ServerPosition, recycler.ServerRotation) as ItemBasedFlowRestrictor;
        if (fuseBox == null) 
            return;
        
        fuseBox.transform.localPosition = _localPosition;
        fuseBox.transform.localRotation = _localRotation;        
        fuseBox.SetParent(recycler, 0u, false, true);
        fuseBox.Spawn();
    }

    private void TryCreateElectricalRecycler(Recycler recycler)
    {
        if (_configData.EnablePlayerPlacedOnly && recycler.OwnerID == 0UL) 
            return;
        
        if (HasChildEntity<ItemBasedFlowRestrictor>(recycler)) 
            return;
        
        AttachFuseBox(recycler);
    }

    private void TryRemoveElectricalRecycler(Recycler recycler)
    {
        ItemBasedFlowRestrictor? fuseBox = GetChildEntity<ItemBasedFlowRestrictor>(recycler);
        if (fuseBox == null)
            return;
        
        DropUtil.DropItems(fuseBox.inventory, recycler.GetDropPosition());
        fuseBox.SetParent(null);
        fuseBox.KillMessage();
    }
    
    private static bool HasChildEntity<T>(Recycler recycler) where T : BaseEntity
    {
        if (recycler?.children == null)
            return false;
        
        foreach (BaseEntity childEntity in recycler.children)
        {
            if (childEntity is T { prefabID: FUSEBOX_PREFAB_ID })
                return true;
        }

        return false;
    }    
    
    private static T? GetChildEntity<T>(Recycler recycler) where T : BaseEntity
    {
        if (recycler?.children == null)
            return null;
        
        foreach (BaseEntity childEntity in recycler.children)
        {
            if (childEntity is T { prefabID: FUSEBOX_PREFAB_ID } entity)
                return entity;
        }

        return null;
    }

    #endregion

    #region Harmony Patches
    
    [AutoPatch]
    [HarmonyPatch(typeof(Recycler), nameof(Recycler.RecycleThink))]
    public static class Recycler_FuseBox_Consumption_Patch
    {
        [HarmonyPostfix]
        public static void Postfix(Recycler __instance)
        {
            ItemBasedFlowRestrictor? flowRestrictor = GetChildEntity<ItemBasedFlowRestrictor>(__instance);
            if (flowRestrictor == null)
                return;
            
            Item slot = flowRestrictor.inventory.GetSlot(0);
            if (slot is not { hasCondition: true })
                return;
            
            slot.LoseCondition(_configData.FuseUseAmount);
        }
    }

    #endregion
}

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