No compile

No compile for last update, fix please.

ZoneManagerTime - Failed to compile: 'ZoneManagerTime.DateController.OnDestroy()': cannot change access modifiers when overriding 'public' inherited member 'SingletonComponent.OnDestroy()' | Line: 113, Pos: 37

Try this

 

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

namespace Oxide.Plugins
{
    [Info("Zone Manager Time", "misticos", "1.0.1")]
    [Description("Set specific time for your zones")]
    class ZoneManagerTime : CovalencePlugin
    {
        #region Variables
        
        [PluginReference]
        // ReSharper disable once InconsistentNaming
        private Plugin ZoneManager = null;
        
        private Dictionary<string, string> _playerZones = new Dictionary<string, string>();
        
        #endregion
        
        #region Configuration

        private Configuration _config;

        private class Configuration
        {
            [JsonProperty(PropertyName = "Zone ID Time", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, TimeSpan> ZoneTime = new Dictionary<string, TimeSpan>
                {{"Zone ID", new TimeSpan(10, 5, 37)}};

            [JsonProperty(PropertyName = "Update Frequency")]
            public float UpdateFrequency = 5f;
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) throw new Exception();
                SaveConfig();
            }
            catch
            {
                PrintError("Your configuration file contains an error. Using default configuration values.");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig() => Config.WriteObject(_config);

        protected override void LoadDefaultConfig() => _config = new Configuration();

        #endregion
        
        #region Hooks

        private void OnServerInitialized()
        {
            new GameObject().AddComponent<DateController>().PluginInstance = this;

            if (ZoneManager != null && ZoneManager.IsLoaded)
            {
                foreach (var player in BasePlayer.activePlayerList)
                {
                    var zones = ZoneManager.Call<string[]>("GetPlayerZoneIDs", player);
                    if (zones == null || zones.Length == 0)
                        continue;
                    
                    _playerZones[player.UserIDString] = zones[zones.Length - 1];
                }
            }
        }

        private void Unload()
        {
            UnityEngine.Object.DestroyImmediate(DateController.Instance.gameObject);
        }

        private void OnEnterZone(string zoneId, BasePlayer player)
        {
            _playerZones[player.UserIDString] = zoneId;
        }

        private void OnExitZone(string zoneId, BasePlayer player)
        {
            _playerZones.Remove(player.UserIDString);
        }

        #endregion
        
        #region Controller

private class DateController : SingletonComponent<DateController>
{
    public ZoneManagerTime PluginInstance = null;
    
    private EnvSync _timeEntity;

    private void Start()
    {
        _timeEntity = FindObjectOfType<EnvSync>();
        _timeEntity.limitNetworking = true;
        
        InvokeRepeating(DoUpdate, PluginInstance._config.UpdateFrequency, PluginInstance._config.UpdateFrequency);
    }


    public override void OnDestroy()
    {
        base.OnDestroy();
        _timeEntity.limitNetworking = false;
    }

    private void DoUpdate()
    {
        var saveInfo = new BaseNetworkable.SaveInfo
        {
            forDisk = false
        };

        using (saveInfo.msg = Facepunch.Pool.Get<ProtoBuf.Entity>())
        {
            _timeEntity.Save(saveInfo);
            var initialDateTime = DateTime.FromBinary(saveInfo.msg.environment.dateTime);

            for (var i = 0; i < BasePlayer.activePlayerList.Count; i++)
            {
                var connection = BasePlayer.activePlayerList[i].net?.connection;
                if (connection == null)
                    continue;

                var write = Net.sv.StartWrite();

                saveInfo.forConnection = connection;

                connection.validate.entityUpdates += 1u;

                write.PacketID(Message.Type.Entities);
                write.UInt32(connection.validate.entityUpdates);

                string zoneId;
                TimeSpan offset;
                if (PluginInstance._playerZones.TryGetValue(BasePlayer.activePlayerList[i].UserIDString,
                    out zoneId) && PluginInstance._config.ZoneTime.TryGetValue(zoneId, out offset))
                {
                    saveInfo.msg.environment.dateTime = (initialDateTime.Date + offset).ToBinary();
                }
                else
                {
                    saveInfo.msg.environment.dateTime = initialDateTime.ToBinary();
                }

                saveInfo.msg.ToProto(write);

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

Thank you so much.

Is there another plugin you all found since this one doesnt work.

nUlA71EA4xExX9M.png WarZombie

Is there another plugin you all found since this one doesnt work.

I was looking for one, too, since there was a different compile error now when using the code BadKop provided.  The downside to all the cool server updates recently, I guess!  This is what ChatGPT gave me as far as what to correct to work with the latest server build, along with the explanation of why it changed what it did.  It's working on my server currently.

using System;
using System.Collections.Generic;
using System.Reflection;               // <-- added
using Network;
using Newtonsoft.Json;
using Oxide.Core.Plugins;
using UnityEngine;

namespace Oxide.Plugins
{
    [Info("Zone Manager Time", "misticos", "1.0.1")]
    [Description("Set specific time for your zones")]
    class ZoneManagerTime : CovalencePlugin
    {
        #region Variables
        
        [PluginReference]
        // ReSharper disable once InconsistentNaming
        private Plugin ZoneManager = null;
        
        private Dictionary<string, string> _playerZones = new Dictionary<string, string>();
        
        #endregion
        
        #region Configuration

        private Configuration _config;

        private class Configuration
        {
            [JsonProperty(PropertyName = "Zone ID Time", ObjectCreationHandling = ObjectCreationHandling.Replace)]
            public Dictionary<string, TimeSpan> ZoneTime = new Dictionary<string, TimeSpan>
                { { "Zone ID", new TimeSpan(10, 5, 37) } };

            [JsonProperty(PropertyName = "Update Frequency")]
            public float UpdateFrequency = 5f;
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null) throw new Exception();
                SaveConfig();
            }
            catch
            {
                PrintError("Your configuration file contains an error. Using default configuration values.");
                LoadDefaultConfig();
            }
        }

        protected override void SaveConfig() => Config.WriteObject(_config);

        protected override void LoadDefaultConfig() => _config = new Configuration();

        #endregion
        
        #region Hooks

        private void OnServerInitialized()
        {
            new GameObject().AddComponent<DateController>().PluginInstance = this;

            if (ZoneManager != null && ZoneManager.IsLoaded)
            {
                foreach (var player in BasePlayer.activePlayerList)
                {
                    var zones = ZoneManager.Call<string[]>("GetPlayerZoneIDs", player);
                    if (zones == null || zones.Length == 0)
                        continue;
                    
                    _playerZones[player.UserIDString] = zones[zones.Length - 1];
                }
            }
        }

        private void Unload()
        {
            UnityEngine.Object.DestroyImmediate(DateController.Instance.gameObject);
        }

        private void OnEnterZone(string zoneId, BasePlayer player)
        {
            _playerZones[player.UserIDString] = zoneId;
        }

        private void OnExitZone(string zoneId, BasePlayer player)
        {
            _playerZones.Remove(player.UserIDString);
        }

        #endregion
        
        #region Controller

        private class DateController : SingletonComponent<DateController>
        {
            public ZoneManagerTime PluginInstance = null;
            
            private EnvSync _timeEntity;

            // --- Reflection cache for ToProto fallbacks
            private static readonly string[] BufferFieldCandidates = { "write", "_write", "stream", "_stream", "buffer", "_buffer" };

            private void Start()
            {
                _timeEntity = FindObjectOfType<EnvSync>();
                _timeEntity.limitNetworking = true;
                
                InvokeRepeating(DoUpdate, PluginInstance._config.UpdateFrequency, PluginInstance._config.UpdateFrequency);
            }

            public override void OnDestroy() // must be public to match base signature
            {
                base.OnDestroy();
                _timeEntity.limitNetworking = false;
            }

            private bool TryWriteEntityProto(object entityMsg, NetWrite nw)
            {
                if (entityMsg == null || nw == null) return false;

                var msgType = entityMsg.GetType();

                // 1) Try ToProto(NetWrite)
                var toProtoNetWrite = msgType.GetMethod(
                    "ToProto",
                    BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                    null,
                    new Type[] { nw.GetType() },
                    null);

                if (toProtoNetWrite != null)
                {
                    try
                    {
                        toProtoNetWrite.Invoke(entityMsg, new object[] { nw });
                        return true;
                    }
                    catch { /* fall through */ }
                }

                // 2) Try common internal BufferStream-like fields on NetWrite
                var nwt = nw.GetType();
                foreach (var fname in BufferFieldCandidates)
                {
                    var f = nwt.GetField(fname, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
                    if (f == null) continue;

                    var buf = f.GetValue(nw);
                    if (buf == null) continue;

                    var toProtoBuf = msgType.GetMethod(
                        "ToProto",
                        BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic,
                        null,
                        new Type[] { buf.GetType() },
                        null);

                    if (toProtoBuf != null)
                    {
                        try
                        {
                            toProtoBuf.Invoke(entityMsg, new object[] { buf });
                            return true;
                        }
                        catch { /* keep searching */ }
                    }
                }

                // If we got here, we couldn't find a compatible overload
                if (PluginInstance != null)
                    PluginInstance.PrintError("Unable to locate ProtoBuf.Entity.ToProto(...) overload for this server build.");
                return false;
            }

            private void DoUpdate()
            {
                var saveInfo = new BaseNetworkable.SaveInfo
                {
                    forDisk = false
                };

                using (saveInfo.msg = Facepunch.Pool.Get<ProtoBuf.Entity>())
                {
                    _timeEntity.Save(saveInfo);
                    var initialDateTime = DateTime.FromBinary(saveInfo.msg.environment.dateTime);

                    for (var i = 0; i < BasePlayer.activePlayerList.Count; i++)
                    {
                        var connection = BasePlayer.activePlayerList[i].net?.connection;
                        if (connection == null)
                            continue;

                        var write = Net.sv.StartWrite();

                        saveInfo.forConnection = connection;

                        connection.validate.entityUpdates += 1u;

                        write.PacketID(Message.Type.Entities);
                        write.UInt32(connection.validate.entityUpdates);

                        string zoneId;
                        TimeSpan offset;
                        if (PluginInstance._playerZones.TryGetValue(BasePlayer.activePlayerList[i].UserIDString,
                            out zoneId) && PluginInstance._config.ZoneTime.TryGetValue(zoneId, out offset))
                        {
                            saveInfo.msg.environment.dateTime = (initialDateTime.Date + offset).ToBinary();
                        }
                        else
                        {
                            saveInfo.msg.environment.dateTime = initialDateTime.ToBinary();
                        }

                        // CHANGED: version-agnostic ToProto
                        if (!TryWriteEntityProto(saveInfo.msg, write))
                        {
                            // Don't send a malformed packet if serialization failed
                            continue;
                        }

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

"

Here’s what changed—and why it matters:

What’s different

  1. Added reflection-based serializer

  • New version: adds using System.Reflection;, a BufferFieldCandidates array, and a helper:

    private bool TryWriteEntityProto(object entityMsg, NetWrite nw) { ... }
    

    In DoUpdate() it now does:

    if (!TryWriteEntityProto(saveInfo.msg, write)) continue;
    
  • Old version: directly calls

    saveInfo.msg.ToProto(write);
    

    (which assumes ToProto(NetWrite) exists, or that NetWrite is implicitly convertible).

  1. Overload selection logic

  • New: Tries ToProto(NetWrite) first. If that overload isn’t present, it reflects common internal fields on NetWrite (write, _write, stream, _stream, buffer, _buffer) and calls ToProto(BufferStreamType) instead.

  • Old: No fallback; it will fail on builds where ToProto expects a BufferStream (or where NetWrite.write isn’t exposed).

  1. Safer failure behavior

  • New: On a mismatch, it logs a clear error and skips sending that packet (avoids malformed frames).

  • Old: Compilation fails (cannot convert from 'Network.NetWrite' to 'BufferStream') or crashes at runtime if the signature doesn’t match.

  1. Access modifier on OnDestroy

  • New:public override void OnDestroy() (matches base SingletonComponent).

  • Old:protected override void OnDestroy() (can cause: “cannot change access modifiers when overriding ‘public’ inherited member”).

Why it matters

  • Cross-version Rust compatibility. Facepunch has changed the ProtoBuf.Entity.ToProto(...) signature across builds. The reflection path lets your plugin work whether the server expects ToProto(NetWrite)orToProto(BufferStream), so you don’t have to keep chasing breaking changes.

  • Fixes your compile error. The old call ToProto(write) produced:
    Argument 1: cannot convert from 'Network.NetWrite' to 'BufferStream'.
    The new code passes the correct thing for your DLLs at runtime.

  • Prevents hard crashes/bad packets. If serialization can’t be resolved, the new code logs and skips one send instead of pushing a malformed Entities packet (which can kick players).

  • Builds cleanly. Making OnDestroy public avoids the access-modifier override error on newer Oxide/Rust.

Everything else (timers, limitNetworking, connection.validate.entityUpdates counter bump, etc.) is unchanged between your two snippets. The big win is the version-agnosticToProto call and the compile-proof OnDestroy override."

Hope this helps!!