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

FREE SpinningXmasTree : 1.3.1 1.3.1

Нет прав для скачивания
C#:
/*
 * Copyright (c) 2026 Bazz3l
 *
 * Spinning Xmas Tree cannot be copied, edited and/or (re)distributed without the express permission of Bazz3l.
 * Discord bazz3l
 *
 * 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 System.Collections;
using Newtonsoft.Json;
using UnityEngine;
using System;
using VLB;

namespace Oxide.Plugins;

[Info("Spinning Xmas Tree", "Bazz3l", "1.3.1")]
[Description("Add decorations to your tree and watch it spin with awesomeness.")]
internal class SpinningXmasTree : RustPlugin
{
    #region Fields

    private const float INITIALIZE_DELAY_INTERVAL = 30f;
    
    private readonly List<ChristmasTree> _christmasTrees = new();
    private Coroutine _routine;
    private ConfigData _configData;
    
    #endregion

    #region Config

    private class ConfigData
    {
        [JsonProperty("required number of items to spin - (default: 2)")]
        public int RequiredItemsToSpin { get; set; }
        
        public static ConfigData DefaultConfig()
        {
            return new ConfigData
            {
                RequiredItemsToSpin = 2,
            };
        }
    }

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

    protected override void LoadConfig()
    {
        base.LoadConfig();
        
        try
        {
            _configData = Config.ReadObject<ConfigData>() ?? throw new Exception();
        }
        catch (Exception e)
        {
            LoadDefaultConfig();
            PrintWarning("Failed to load default config: {0}", e.Message);
        }
    }

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

    #endregion
    
    #region Oxide Hooks

    private void OnServerInitialized() => StartupSetup();

    private void Init() => Unsubscribe(nameof(OnItemAddedToContainer));
    
    private void Unload()
    {
        CancelSetup();
        RemoveSpinners();
    }

    private void OnEntitySpawned(ChristmasTree christmasTree)
    {
        if (christmasTree == null || christmasTree.IsDestroyed)
            return;
        
        NextFrame(() =>
        {
            if (christmasTree.IsDestroyed)
                return;
            
            CreateSpinner(christmasTree);
        });
    }
    
    private void OnEntityKill(ChristmasTree christmasTree) => _christmasTrees.Remove(christmasTree);
    
    private void OnItemAddedToContainer(ItemContainer container, Item item) => OnItemRemovedFromContainer(container, item);

    private void OnItemRemovedFromContainer(ItemContainer container, Item item)
    {
        ChristmasTree christmasTree = container?.entityOwner as ChristmasTree;
        if (christmasTree == null) 
            return;
        
        int amount = container.itemList?.Count ?? 0;
        christmasTree.GetComponent<SpinnerController>()?.TryActivateSpinner(amount, _configData.RequiredItemsToSpin);
    }

    #endregion
    
    #region Spinner Management

    private void StartupSetup()
    {
        CancelSetup();
        
        _routine = ServerMgr.Instance.StartCoroutine(CreateSpinners());
    }
    
    private void CancelSetup()
    {
        if (_routine == null) 
            return;
        
        ServerMgr.Instance.StopCoroutine(_routine);

        _routine = null;
    }
    
    private IEnumerator CreateSpinners()
    {
        Puts("🎄🎄🎄please wait for all trees to initialize in {0} seconds🎄🎄🎄", INITIALIZE_DELAY_INTERVAL);
        
        yield return CoroutineEx.waitForSeconds(INITIALIZE_DELAY_INTERVAL);
        
        int count = 0;
        
        foreach (BaseNetworkable nEntity in BaseNetworkable.serverEntities)
        {
            if (nEntity is not ChristmasTree christmasTree)
                continue;
            
            CreateSpinner(christmasTree);
            
            if (count++ % 20 == 0)
            {
                yield return CoroutineEx.waitForEndOfFrame;
                yield return CoroutineEx.waitForEndOfFrame;
            }
        }
        
        Subscribe(nameof(OnItemAddedToContainer));
        
        Puts("🎄🎄🎄all trees are now initialized, happy spinning 🎄🎄🎄");

        _routine = null;
        
        yield break;
    }

    private void RemoveSpinners()
    {
        if (Rust.Application.isQuitting)
            return;
        
        List<ChristmasTree> christmasTrees = new List<ChristmasTree>(_christmasTrees);
        
        _christmasTrees.Clear();
        
        foreach (ChristmasTree christmasTree in christmasTrees)
        {
            if (christmasTree == null) 
                continue;
            
            RemoveSpinner(christmasTree);
        }
    }
    
    private void CreateSpinner(ChristmasTree christmasTree)
    {
        if (christmasTree == null || christmasTree.IsDestroyed)
            return;
        
        christmasTree.syncPosition = true;
        
        if (christmasTree.NetworkPosTickCallback == null)
        {
            Action action;
            christmasTree.NetworkPosTickCallback = action = new Action(christmasTree.NetworkPositionTick);
        }
        
        _christmasTrees.Add(christmasTree);
        
        christmasTree.InvokeRepeatingFixedTime(christmasTree.NetworkPosTickCallback);
        SpinnerController controller = christmasTree.GetOrAddComponent<SpinnerController>();
        controller.TryActivateSpinner(christmasTree.inventory?.itemList?.Count ?? 0, 2);
    }

    private void RemoveSpinner(ChristmasTree christmasTree)
    {
        if (christmasTree == null || christmasTree.IsDestroyed)
            return;
        
        christmasTree.CancelInvoke(christmasTree.NetworkPosTickCallback);
        UnityEngine.Object.Destroy(christmasTree.GetComponent<SpinnerController>());
    }
    
    #endregion

    #region Spinner Controller

    private class SpinnerController : FacepunchBehaviour
    {
        public float spinSpeed = 1.0f;
        public bool hasRequiredItems;

        private void FixedUpdate()
        {
            if (!hasRequiredItems) 
                return;
            
            transform.Rotate(0, Time.fixedDeltaTime * spinSpeed, 0);
            transform.hasChanged = true;
        }
        
        public void TryActivateSpinner(int amount, int requiredAmount)
        {
            hasRequiredItems = requiredAmount == 0 || amount >= requiredAmount;
        }
    }

    #endregion
}

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