Hi Everyone,
i noticed nightvision hadnt been updated in a while and i really liked this plugin. im not the original developer i just had help fix the code https://umod.org/plugins/night-vision
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Network;
using Oxide.Core;
namespace Oxide.Plugins
{
[Info("NightVision", "Clearshot","killatacitcs", "2.4.2")]
[Description("Allows players to see at night")]
class NightVision : CovalencePlugin
{
private PluginConfig _config;
private Game.Rust.Libraries.Player _rustPlayer = Interface.Oxide.GetLibrary<Game.Rust.Libraries.Player>("Player");
private EnvSync _envSync;
private Dictionary<ulong, NVPlayerData> _playerData = new Dictionary<ulong, NVPlayerData>();
private Dictionary<ulong, float> _playerTimes = new Dictionary<ulong, float>();
private DateTime _nvDate;
private List<ulong> _connected = new List<ulong>();
private string PERM_ALLOWED = "nightvision.allowed";
private string PERM_UNLIMITEDNVG = "nightvision.unlimitednvg";
private string PERM_AUTO = "nightvision.auto";
private bool API_blockEnvUpdates = false;
private void SendChatMsg(BasePlayer pl, string msg, string prefix = null)
{
if (pl == null || !pl.IsConnected) return;
_rustPlayer.Message(pl, msg, prefix != null ? prefix : lang.GetMessage("ChatPrefix", this, pl.UserIDString), Convert.ToUInt64(_config.chatIconID), Array.Empty<object>());
}
private void Init()
{
permission.RegisterPermission(PERM_ALLOWED, this);
permission.RegisterPermission(PERM_UNLIMITEDNVG, this);
permission.RegisterPermission(PERM_AUTO, this);
try
{
_playerTimes = Interface.Oxide.DataFileSystem.ReadObject<Dictionary<ulong, float>>($"{Name}\\playerTimes");
}
catch (Exception ex)
{
LogError($"Failed to load playerTimes data: {ex.Message}");
_playerTimes = new Dictionary<ulong, float>();
}
}
private void OnServerInitialized()
{
_envSync = BaseNetworkable.serverEntities.OfType<EnvSync>().FirstOrDefault();
if (_envSync == null)
{
LogError("EnvSync entity not found! NightVision plugin cannot function.");
return;
}
timer.Every(5f, () => {
if (!_envSync.limitNetworking)
_envSync.limitNetworking = true;
List<Connection> subscribers = _envSync.net?.group?.subscribers;
if (subscribers == null || subscribers.Count == 0)
{
LogWarning("No subscribers found for EnvSync.");
return;
}
foreach (Connection connection in subscribers)
{
if (connection == null || !connection.active) continue;
global::BasePlayer basePlayer = connection.player as global::BasePlayer;
if (basePlayer == null || !basePlayer.IsConnected) continue;
NVPlayerData nvPlayerData = GetNVPlayerData(basePlayer);
if (API_blockEnvUpdates && !nvPlayerData.timeLocked) continue;
try
{
var write = Net.sv.StartWrite();
if (write == null)
{
LogError("Failed to start network write for player: " + basePlayer.UserIDString);
continue;
}
connection.validate.entityUpdates = connection.validate.entityUpdates + 1;
BaseNetworkable.SaveInfo saveInfo = new global::BaseNetworkable.SaveInfo
{
forConnection = connection,
forDisk = false
};
write.PacketID(Message.Type.Entities);
write.UInt32(connection.validate.entityUpdates);
using (saveInfo.msg = Facepunch.Pool.Get<ProtoBuf.Entity>())
{
_envSync.Save(saveInfo);
if (nvPlayerData.timeLocked)
{
if (saveInfo.msg.environment == null)
{
LogError("Environment data is null for player: " + basePlayer.UserIDString);
continue;
}
saveInfo.msg.environment.dateTime = _nvDate.AddHours(nvPlayerData.time).ToBinary();
saveInfo.msg.environment.fog = 0;
saveInfo.msg.environment.rain = 0;
saveInfo.msg.environment.clouds = 0;
saveInfo.msg.environment.wind = 0;
}
if (saveInfo.msg.baseEntity == null)
{
LogError("ToStream - no BaseEntity for player: " + basePlayer.UserIDString);
continue;
}
if (saveInfo.msg.baseNetworkable == null)
{
LogError("ToStream - no baseNetworkable for player: " + basePlayer.UserIDString);
continue;
}
if (saveInfo.msg == null)
{
LogError("saveInfo.msg is null for player: " + basePlayer.UserIDString);
continue;
}
try
{
// Serialize ProtoBuf.Entity to a byte array
byte[] buffer = saveInfo.msg.ToProtoBytes();
if (buffer == null || buffer.Length == 0)
{
LogError("Failed to serialize ProtoBuf.Entity to bytes for player: " + basePlayer.UserIDString);
continue;
}
write.Write(buffer, 0, buffer.Length);
}
catch (Exception ex)
{
LogError($"Failed to serialize ProtoBuf.Entity for player {basePlayer.UserIDString}: {ex.Message}");
continue;
}
_envSync.PostSave(saveInfo);
write.Send(new SendInfo(connection));
}
}
catch (Exception ex)
{
LogError($"Failed to send environment update to player {basePlayer.UserIDString}: {ex.Message}");
}
}
});
}
private void OnPlayerConnected(BasePlayer player)
{
if (player != null && !_connected.Contains(player.userID))
_connected.Add(player.userID);
}
private void OnPlayerDisconnected(BasePlayer pl, string reason)
{
if (pl != null && _playerData.ContainsKey(pl.userID))
_playerData.Remove(pl.userID);
if (pl != null && _connected.Contains(pl.userID))
_connected.Remove(pl.userID);
}
private void OnPlayerSleepEnded(BasePlayer pl)
{
if (pl == null || !pl.IsConnected)
return;
if (!_connected.Contains(pl.userID))
return;
if (permission.UserHasPermission(pl.UserIDString, PERM_AUTO))
NightVisionCommand(pl.IPlayer, "nv", new string[] { _playerTimes.ContainsKey(pl.userID) ? _playerTimes[pl.userID].ToString() : "" });
_connected.Remove(pl.userID);
}
private void Unload()
{
if (_envSync != null)
_envSync.limitNetworking = false;
}
private void SaveData()
{
try
{
Interface.Oxide.DataFileSystem.WriteObject($"{Name}\\playerTimes", _playerTimes);
}
catch (Exception ex)
{
LogError($"Failed to save playerTimes data: {ex.Message}");
}
}
[Command("nightvision", "nv", "unlimitednvg", "unvg")]
private void NightVisionCommand(IPlayer player, string command, string[] args)
{
if (player == null) return;
BasePlayer pl = (BasePlayer)player.Object;
if (pl == null || !pl.IsConnected) return;
if (args.Length != 0 && args[0] == "help")
{
StringBuilder sb = new StringBuilder();
sb.AppendLine(lang.GetMessage("HelpTitle", this, pl.UserIDString));
sb.AppendLine(lang.GetMessage("Help1", this, pl.UserIDString));
if (permission.UserHasPermission(pl.UserIDString, PERM_UNLIMITEDNVG))
sb.AppendLine(lang.GetMessage("Help2", this, pl.UserIDString));
SendChatMsg(pl, sb.ToString(), "");
return;
}
NVPlayerData nvpd;
switch (command)
{
case "nightvision":
case "nv":
if (!permission.UserHasPermission(pl.UserIDString, PERM_ALLOWED))
{
SendChatMsg(pl, lang.GetMessage("NoPerms", this, pl.UserIDString));
return;
}
nvpd = GetNVPlayerData(pl);
nvpd.timeLocked = !nvpd.timeLocked;
float time;
nvpd.time = args.Length > 0 && float.TryParse(args[0], out time) && time >= 0 && time <= 24 ? time : _config.time;
if (permission.UserHasPermission(pl.UserIDString, PERM_AUTO))
{
_playerTimes[pl.userID] = nvpd.time;
SaveData();
}
SendChatMsg(pl, string.Format(lang.GetMessage(nvpd.timeLocked ? "TimeLocked" : "TimeUnlocked", this, pl.UserIDString), nvpd.time));
break;
case "unlimitednvg":
case "unvg":
if (!permission.UserHasPermission(pl.UserIDString, PERM_UNLIMITEDNVG))
{
SendChatMsg(pl, lang.GetMessage("NoPerms", this, pl.UserIDString));
return;
}
List<Item> unvgInv = pl.inventory.containerWear?.itemList?.FindAll((Item x) => x.info.name == "hat.nvg.item") ?? new List<Item>();
if (unvgInv.Count > 0)
{
foreach (Item i in unvgInv)
{
if (i.condition == 1 && i.amount == 0)
{
i.SwitchOnOff(false);
i.Remove();
}
}
pl.inventory.containerWear.capacity = 7;
SendChatMsg(pl, lang.GetMessage("RemoveUNVG", this, pl.UserIDString));
}
else
{
var item = ItemManager.CreateByName("nightvisiongoggles", 1, 0UL);
if (item != null)
{
item.OnVirginSpawn();
item.SwitchOnOff(true);
item.condition = 1;
item.amount = 0;
pl.inventory.containerWear.capacity = 8;
item.MoveToContainer(pl.inventory.containerWear, 7);
SendChatMsg(pl, lang.GetMessage("EquipUNVG", this, pl.UserIDString));
}
else
{
LogError("Failed to create nightvisiongoggles item for player: " + pl.UserIDString);
}
}
break;
}
}
private object CanWearItem(PlayerInventory inventory, Item item, int targetSlot)
{
if (item == null || inventory == null) return null;
if (item.info.name == "hat.nvg.item" && item.condition == 1 && item.amount == 0) return null;
NextTick(() =>
{
try
{
if (inventory.containerMain != null)
{
foreach (Item i in inventory.containerMain.itemList.FindAll((Item x) => x.info.name == "hat.nvg.item"))
{
if (i != null && i.condition == 1 && i.amount == 0)
{
i.SwitchOnOff(false);
i.Remove();
inventory.containerWear.capacity = 7;
}
}
}
if (inventory.containerBelt != null)
{
foreach (Item i in inventory.containerBelt.itemList.FindAll((Item x) => x.info.name == "hat.nvg.item"))
{
if (i != null && i.condition == 1 && i.amount == 0)
{
i.SwitchOnOff(false);
i.Remove();
inventory.containerWear.capacity = 7;
}
}
}
if (inventory.containerWear != null)
{
foreach (Item i in inventory.containerWear.itemList.FindAll((Item x) => x.info.name == "hat.nvg.item"))
{
if (i != null && i.condition == 1 && i.amount == 0)
{
i.SwitchOnOff(false);
i.Remove();
inventory.containerWear.capacity = 7;
}
}
}
}
catch (Exception ex)
{
LogError($"Error in CanWearItem: {ex.Message}");
}
});
return null;
}
private void OnItemDropped(Item item, BaseEntity entity)
{
if (item != null && item.info?.name == "hat.nvg.item" && item.condition == 1 && item.amount == 0)
{
item.Remove();
}
}
private NVPlayerData GetNVPlayerData(BasePlayer pl)
{
if (pl == null) return new NVPlayerData();
if (!_playerData.ContainsKey(pl.userID))
_playerData[pl.userID] = new NVPlayerData();
_playerData[pl.userID].timeLocked = !(!_playerData[pl.userID].timeLocked || !permission.UserHasPermission(pl.UserIDString, PERM_ALLOWED));
return _playerData[pl.userID];
}
#region Plugin-API
[HookMethod("LockPlayerTime")]
void LockPlayerTime_PluginAPI(BasePlayer player, float time)
{
var data = GetNVPlayerData(player);
data.timeLocked = true;
data.time = time;
}
[HookMethod("UnlockPlayerTime")]
void UnlockPlayerTime_PluginAPI(BasePlayer player)
{
var data = GetNVPlayerData(player);
data.timeLocked = false;
}
[HookMethod("IsPlayerTimeLocked")]
bool IsPlayerTimeLocked_PluginAPI(BasePlayer player)
{
var data = GetNVPlayerData(player);
return data.timeLocked;
}
[HookMethod("BlockEnvUpdates")]
void BlockEnvUpdates_PluginAPI(bool blockEnv)
{
API_blockEnvUpdates = blockEnv;
}
#endregion
#region Config
private DateTime _defaultDate = new DateTime(2024, 1, 25);
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
["ChatPrefix"] = "<color=#00ff00>[Night Vision]</color>",
["NoPerms"] = "You do not have permission to use this command!",
["TimeLocked"] = "Time locked to {0}",
["TimeUnlocked"] = "Time unlocked",
["HelpTitle"] = "<size=16><color=#00ff00>Night Vision</color> Help</size>\n",
["Help1"] = "<color=#00ff00>/nightvision <0-24>(/nv)</color> - Toggle time lock night vision with optional time 0-24",
["Help2"] = "<color=#00ff00>/unlimitednvg (/unvg)</color> - Equip/remove unlimited night vision goggles",
["EquipUNVG"] = "Equipped unlimited night vision goggles",
["RemoveUNVG"] = "Removed unlimited night vision goggles"
}, this);
}
protected override void LoadDefaultConfig()
{
Config.WriteObject(GetDefaultConfig(), true);
}
private PluginConfig GetDefaultConfig()
{
PluginConfig config = new PluginConfig();
config.date = _defaultDate.ToString("M/d/yyyy");
config.time = 12;
return config;
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_config = Config.ReadObject<PluginConfig>();
if (_config == null)
{
LogError("Failed to load config, using default.");
_config = GetDefaultConfig();
}
if (_config.time < 0 || _config.time > 24)
_config.time = 12;
if (!DateTime.TryParse(_config.date, out _nvDate))
{
LogError("Invalid date in config, using default: " + _defaultDate.ToString("M/d/yyyy"));
_nvDate = _defaultDate;
_config.date = _defaultDate.ToString("M/d/yyyy");
if (_config.time == 0)
_config.time = 12;
}
Config.WriteObject(_config, true);
}
catch (Exception ex)
{
LogError($"Failed to load config: {ex.Message}");
_config = GetDefaultConfig();
Config.WriteObject(_config, true);
}
}
private class PluginConfig
{
public string chatIconID = "0";
public string date;
public float time;
}
#endregion
private class NVPlayerData
{
public bool timeLocked = false;
public float time = 12f;
}
}
}