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

FREE APAdminDaylight : 0.0.2 0.0.2

Нет прав для скачивания
C#:
using System;
using System.Collections.Generic;
using System.IO;
using Facepunch;
using Network;
using Oxide.Core;
using Oxide.Core.Plugins;
using ProtoBuf;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("APAdminDaylight", "VORON", "0.0.2")]
    [Description("Personal daylight via EnvSync entity snapshot (Facepunch blocks admintime from server)")]
    public class APAdminDaylight : RustPlugin
    {
        private const string PermUse = "apadmindaylight.use";
        private const float SyncIntervalSeconds = 5f;
        private const float DaylightHour = 12f;

        private readonly HashSet<ulong> _daylightPlayers = new HashSet<ulong>();

        private EnvSync _envSync;
        private GameObject _invokeHost;

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
        }

        private void OnServerInitialized()
        {
            FindEnvSync();
            StartSyncLoop();
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["NoPermission"] = "<color=#ff6666>Access denied.</color>",
                    ["DaylightEnabled"] =
                        "<color=#a7ff83>Admin daylight enabled (personal, only for you).</color>",
                    ["DaylightDisabled"] = "<color=#ffd479>Admin daylight disabled.</color>",
                    ["NoEnvSync"] =
                        "<color=#ff6666>Daylight sync not ready — wait for world load and try again.</color>",
                },
                this,
                "en"
            );

            lang.RegisterMessages(
                new Dictionary<string, string>
                {
                    ["NoPermission"] = "<color=#ff6666>Нет доступа.</color>",
                    ["DaylightEnabled"] =
                        "<color=#a7ff83>Админ-день включён (личный, только для вас).</color>",
                    ["DaylightDisabled"] = "<color=#ffd479>Админ-день выключен.</color>",
                    ["NoEnvSync"] =
                        "<color=#ff6666>Синхронизация дня ещё не готова — подождите загрузку мира и повторите.</color>",
                },
                this,
                "ru"
            );
        }

        private string Lang(BasePlayer player, string key)
        {
            return lang.GetMessage(key, this, player.UserIDString);
        }

        [ChatCommand("aday")]
        private void CmdAdminDay(BasePlayer player, string cmd, string[] args)
        {
            if (player == null || !CanUse(player))
            {
                SendReply(player, Lang(player, "NoPermission"));
                return;
            }

            if (_envSync == null)
                FindEnvSync();

            if (_envSync == null)
            {
                SendReply(player, Lang(player, "NoEnvSync"));
                return;
            }

            if (_daylightPlayers.Contains(player.userID))
            {
                _daylightPlayers.Remove(player.userID);
                RefreshLimitNetworking();
                PushEnvToPlayer(player, lockDaylight: false);
                SendReply(player, Lang(player, "DaylightDisabled"));
                return;
            }

            _daylightPlayers.Add(player.userID);
            RefreshLimitNetworking();
            PushEnvToPlayer(player, lockDaylight: true);
            SendReply(player, Lang(player, "DaylightEnabled"));
        }

        private bool CanUse(BasePlayer player)
        {
            return permission.UserHasPermission(player.UserIDString, PermUse)
                || player.IsAdmin
                || player.net?.connection?.authLevel >= 1;
        }

        private void FindEnvSync()
        {
            foreach (BaseNetworkable entity in BaseNetworkable.serverEntities)
            {
                if (entity is EnvSync sync)
                {
                    _envSync = sync;
                    return;
                }
            }
        }

        private void StartSyncLoop()
        {
            if (_invokeHost != null)
            {
                UnityEngine.Object.Destroy(_invokeHost);
                _invokeHost = null;
            }

            _invokeHost = new GameObject("APAdminDaylight.InvokeHost");
            UnityEngine.Object.DontDestroyOnLoad(_invokeHost);
            SyncDriver driver = _invokeHost.AddComponent<SyncDriver>();
            driver.Initialize(this);
            driver.InvokeRepeating(nameof(SyncDriver.Tick), 1f, SyncIntervalSeconds);
        }

        private void RefreshLimitNetworking()
        {
            if (_envSync == null || _envSync.IsDestroyed)
                return;

            // CHANGE: when anyone has personal daylight, we own EnvSync broadcasts (NightVision pattern)
            _envSync.limitNetworking = _daylightPlayers.Count > 0;
        }

        internal void TickSyncAll()
        {
            if (_daylightPlayers.Count == 0)
                return;

            if (_envSync == null || _envSync.IsDestroyed)
            {
                FindEnvSync();
                if (_envSync == null)
                    return;
            }

            RefreshLimitNetworking();

            foreach (BasePlayer player in BasePlayer.activePlayerList)
            {
                if (player?.IsConnected != true || player.net?.connection == null)
                    continue;

                bool lockDaylight = _daylightPlayers.Contains(player.userID);
                PushEnvToPlayer(player, lockDaylight);
            }
        }

        private void PushEnvToPlayer(BasePlayer player, bool lockDaylight)
        {
            if (player?.IsConnected != true || player.net?.connection == null)
                return;

            if (_envSync == null || _envSync.IsDestroyed)
                return;

            if (!Net.sv.IsConnected())
                return;

            Connection connection = player.net.connection;
            connection.validate.entityUpdates++;

            NetWrite write = Net.sv.StartWrite();
            write.PacketID(Message.Type.Entities);
            write.UInt32(connection.validate.entityUpdates);

            BaseNetworkable.SaveInfo saveInfo = new BaseNetworkable.SaveInfo
            {
                forConnection = connection,
                forDisk = false,
            };

            // CHANGE: per-connection EnvSync snapshot — official path instead of blocked admintime
            using (saveInfo.msg = Pool.Get<Entity>())
            {
                _envSync.Save(saveInfo);

                if (lockDaylight && saveInfo.msg.environment != null)
                {
                    DateTime dayDate =
                        TOD_Sky.Instance != null
                            ? TOD_Sky.Instance.Cycle.DateTime.Date.AddHours(DaylightHour)
                            : new DateTime(2024, 1, 25, 12, 0, 0, DateTimeKind.Utc);

                    saveInfo.msg.environment.dateTime = dayDate.ToBinary();
                    saveInfo.msg.environment.fog = 0f;
                    saveInfo.msg.environment.rain = 0f;
                    saveInfo.msg.environment.clouds = 0f;
                    saveInfo.msg.environment.wind = 0f;
                }

                if (saveInfo.msg.baseEntity == null || saveInfo.msg.baseNetworkable == null)
                {
                    Puts("[APAdminDaylight] EnvSync Save missing base entity data.");
                    return;
                }

                saveInfo.msg.WriteToStream((Stream)(object)write);
                _envSync.PostSave(saveInfo);
            }

            write.Send(new SendInfo(connection));
        }

        private void OnPlayerDisconnected(BasePlayer player, string reason)
        {
            if (player == null)
                return;

            if (_daylightPlayers.Remove(player.userID))
                RefreshLimitNetworking();
        }

        private void Unload()
        {
            if (_invokeHost != null)
            {
                UnityEngine.Object.Destroy(_invokeHost);
                _invokeHost = null;
            }

            if (_envSync != null && !_envSync.IsDestroyed)
                _envSync.limitNetworking = false;

            _daylightPlayers.Clear();
            _envSync = null;
        }

        private sealed class SyncDriver : MonoBehaviour
        {
            private APAdminDaylight _plugin;

            public void Initialize(APAdminDaylight plugin) => _plugin = plugin;

            public void Tick() => _plugin?.TickSyncAll();
        }
    }
}

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