C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using static Oxide.Plugins.CRaidController.ConfigData;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEngine;
namespace Oxide.Plugins {
[Info("CRaidController", "https://discord.gg/TrJ7jnS233", "4.0.7")]
[Description("System for managing raid")]
class CRaidController : RustPlugin {
#region FIELDS
[PluginReference]
readonly Plugin ImageLibrary;
[PluginReference]
readonly Plugin CustomStatusFramework;
[PluginReference]
readonly Plugin RaidableBases;
private static CRaidController _instance;
private static MainController _mainController;
private static Dictionary<ulong, PlayerController> _playerControllers;
private static Dictionary<ulong, AdminController> _adminControllers;
private static Images _images;
private static CodeFlingApi _codeFlingApi;
private static Feed _feed;
private static FireBallManager _fireBallManager;
private static PlayerSetting _playerSetting;
private static PlayerData _playerData;
private static TcController _tcController;
private const string UI_ADMIN_PANEL = "craidcontroller.ui.admin.panel";
private const string UI_ADMIN_PANEL_LOCKER = "craidcontroller.ui.admin.panel.locker";
private const string UI_PLAYER_PANEL = "craidcontroller.ui.player.panel";
private const string UI_PLAYER_PANEL_LOCKER = "craidcontroller.ui.player.panel.locker";
private const string UI_PLAYER_UI_STATIC = "craidcontroller.player.ui.static";
private const string UI_PLAYER_UI_PROGRESS = "craidcontroller.player.ui.progress";
private const string UI_PLAYER_TC_PANEL = "craidcontroller.player.tc.panel";
private const string COLOR_ERROR = "#cd4632";
private const string COLOR_SUCCESS = "#6c9633";
private const string COLOR_PRIMARY = "#bf8e51";
private const string ITEM_TYPE_ADD = "add";
private const string ITEM_TYPE_ADD_COMPLETE = "addComplete";
private const string ITEM_TC_PROTECT = "Bypass.TcProtectItem";
private const string ITEM_TC_NO_PROTECT = "Bypass.TcNoProtectItem";
private const string ITEM_TYPE_PAGE = "page";
private const string ITEM_TYPE_REMOVE = "remove";
private const string SOUND_ERROR = "assets/prefabs/weapons/toolgun/effects/repairerror.prefab";
private const string SOUND_ALERT = "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab";
private readonly List<string> _uiList = new List<string> {
"Default"
}
;
private readonly List<string> _forceRefresh = new List<string> {
"Ui.Ymax", "Ui.BackgroundOpacity", "Ui.BackgroundColor", "Ui.HideNotTime", "Ui.HideIsTime", "Ui.AllowPlayerHide", "Ui.AllowPlayerChange"
}
;
private readonly List<string> _timezones = new List<string> {
"-12", "-11", "-10", "-9", "-8", "-7", "-6", "-5", "-4", "-3", "-2", "-1", "0", "+1", "+2", "+3", "+4", "+5", "+6", "+7", "+8", "+9", "+10", "+11", "+12", "+13", "+14"
}
;
private readonly List<string> _languages = new List<string> {
"en", "fr", "es", "de", "it", "pt", "nl", "ru", "zh", "ja"
}
;
private readonly List<string> _messageType = new List<string> {
"Chat", "Notifications"
}
;
private readonly List<string> _forcedEntityBypass = new List<string> {
"door_barricade", "door_barricade_a", "door_barricade_b", "cover"
}
;
public enum ActiveUI {
Disabled, Activated, CustomStatusFramework
}
public enum AdminPanelTab {
Global, Bypass, Message, Ui, Schedule
}
public enum ScheduleStatus {
AllowedAllDay, NotAllowedAllDay, AllowDuringSchedule
}
public enum TcBypass {
Disabled, AllPlayer, LeaderOnly
}
public enum UiType {
PlayerUI, AdminUI, AllUI
}
#endregion
#region SERVER HOOKS
private void OnServerInitialized() {
if (ImageLibrary == null) PrintWarning("ImageLibrary not found, image not loaded !");
_instance = this;
GameObject mainObject = new GameObject("CRaidController.MainControllerObject");
GameObject fireballObject = new GameObject("CRaidController.FireballObject");
_mainController = mainObject.AddComponent<MainController>();
_adminControllers = new Dictionary<ulong, AdminController>();
_playerControllers = new Dictionary<ulong, PlayerController>();
_images = new Images();
_codeFlingApi = new CodeFlingApi();
_feed = new Feed();
_fireBallManager = fireballObject.AddComponent<FireBallManager>();
_playerSetting = new PlayerSetting();
_playerData = new PlayerData();
_tcController = new TcController();
cmd.AddChatCommand(_cfg == null ? "craid" : _cfg.Global.Command, this, "CmdDrawInterface");
foreach (var player in BasePlayer.activePlayerList) OnPlayerConnected(player);
}
private void Unload() {
PlayerController[] playerObjects = UnityEngine.Object.FindObjectsOfType<PlayerController>();
if (playerObjects != null) {
foreach (var obj in playerObjects) UnityEngine.Object.DestroyImmediate(obj);
}
AdminController[] adminObjects = UnityEngine.Object.FindObjectsOfType<AdminController>();
if (adminObjects != null) {
foreach (var obj in adminObjects) UnityEngine.Object.DestroyImmediate(obj);
}
if (_mainController != null) UnityEngine.Object.DestroyImmediate(_mainController.gameObject);
if (_fireBallManager != null) UnityEngine.Object.DestroyImmediate(_fireBallManager.gameObject);
_playerData.SaveData();
_tcController.SaveData();
}
private void OnNewSave(string filename) {
_playerData.ResetData();
_tcController.ResetData();
}
private void OnPlayerConnected(BasePlayer player) {
if (player?.IsReceivingSnapshot != false || player.IsSleeping()) {
timer.In(1, () => OnPlayerConnected(player));
return;
}
if (!_playerControllers.ContainsKey(player.userID) && !player.GetComponent<PlayerController>()) _playerControllers[player.userID] = player.gameObject.AddComponent<PlayerController>();
if (player.IsAdmin && !_adminControllers.ContainsKey(player.userID) && !player.GetComponent<AdminController>()) _adminControllers[player.userID] = player.gameObject.AddComponent<AdminController>();
}
private void OnPlayerDisconnected(BasePlayer player) {
if (_playerControllers.ContainsKey(player.userID)) {
UnityEngine.Object.Destroy(_playerControllers[player.userID]);
_playerControllers.Remove(player.userID);
}
if (_adminControllers.ContainsKey(player.userID)) {
UnityEngine.Object.Destroy(_adminControllers[player.userID]);
_adminControllers.Remove(player.userID);
}
}
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
if (!_cfg.Enable || entity == null || info == null || info?.Initiator == null) return;
if (RaidableBases != null && IsRaidableBase(entity)) return;
if (entity is Barricade && (_forcedEntityBypass.Contains(entity.ShortPrefabName))) return;
if (!(entity is BuildingBlock || entity is SimpleBuildingBlock || entity is Door || entity.PrefabName.Contains("deploy"))) return;
if (info?.Initiator is FireBall && entity != null && _fireBallManager.IsExist(entity.net.ID.Value)) {
if (info?.damageTypes.GetMajorityDamageType() != Rust.DamageType.Heat) return;
info?.damageTypes.ScaleAll(0f);
FireBall fireball = info?.Initiator as FireBall;
if (fireball != null && !fireball.IsDestroyed) fireball.Kill();
}
else if (info?.Initiator is BasePlayer && info?.InitiatorPlayer != null) {
BasePlayer attacker = info?.InitiatorPlayer;
if (_cfg.Global.BlockDamage && !IsOnline(attacker)) //Catch player disconnect for taking damage
{
Nullify(info, entity);
return;
}
if (attacker.IsNpc) return;
if (_cfg.Global.BlockDamage) {
if (_mainController.currentSchedule.isRaidTime) {
if (_playerData.data[attacker.userID].TimePlayed > _cfg.Global.RaidDelay) {
return;
}
else {
_playerControllers[attacker.userID].alertMessage.AddAlert("Alert.RaidDelay", 1);
Nullify(info, entity);
}
if (_playerData.data[entity.OwnerID].TimePlayed > _cfg.Global.RaidProtectionDuration) {
return;
}
else {
_playerControllers[attacker.userID].alertMessage.AddAlert("Alert.RaidProtectionDuration", 1);
Nullify(info, entity);
}
return;
}
if (_cfg.Bypass.Admin && attacker.IsAdmin) return;
if (_cfg.Bypass.Owner && IsOwner(attacker.userID, entity.OwnerID)) return;
if (_cfg.Bypass.Mate && IsMate(attacker, entity.OwnerID)) return;
if (_cfg.Bypass.Twig && IsTwigs(entity)) return;
if (_cfg.Bypass.NoTc && !IsProtectedByTC(entity)) return;
if (_cfg.Bypass.TcDecay && IsProtectedByTCAndDecaying(entity)) return;
if (_cfg.Bypass.TcProtectItem.Contains(GetItemShortnameFromEntity(entity)) && IsProtectedByTC(entity)) return;
if (_cfg.Bypass.TcNoProtectItem.Contains(GetItemShortnameFromEntity(entity)) && !IsProtectedByTC(entity)) return;
if (_cfg.Bypass.BuildingPrivilege && entity.GetBuildingPrivilege().IsAuthed(attacker.userID)) return;
if (_cfg.Bypass.TcBypass != TcBypass.Disabled && _tcController.TcDisabledProtection(entity.net.ID.Value)) return;
Nullify(info, entity);
}
_playerControllers[attacker.userID].alertMessage.AddAlert("Alert.NotRaidTime", 1);
}
}
private void OnLootEntity(BasePlayer player, BuildingPrivlidge tc) {
if (!_cfg.Enable || !_cfg.Global.BlockDamage || _cfg.Bypass.TcBypass == TcBypass.Disabled || player == null || tc == null) return;
if (_cfg.Bypass.TcBypass == TcBypass.LeaderOnly && (player.Team == null || player.userID != player.Team.teamLeader)) return;
if (_playerControllers.ContainsKey(player.userID)) {
PlayerController playerController = _playerControllers[player.userID];
playerController.DrawTCBypassPanel(tc.net.ID.Value);
}
}
private void OnLootEntityEnd(BasePlayer player, BaseCombatEntity entity) {
if (player == null || !_playerControllers.ContainsKey(player.userID)) return;
PlayerController playerController = _playerControllers[player.userID];
playerController.DestroyUI(tc : true);
playerController.inTc = 0;
}
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) {
if (!_cfg.Enable && entity == null && info == null && info?.Initiator == null) return;
if (!(info?.Initiator is BasePlayer) && info?.InitiatorPlayer == null) return;
if (_mainController.currentSchedule.isRaidTime) return;
if (_cfg.Global.BlockDamage) return;
BasePlayer attacker = info?.InitiatorPlayer;
if(attacker == null) return;
if (_cfg.Global.CmdAllTeam && attacker.Team != null) {
List<ulong> members = GetTeamMembers(attacker);
if (members != null) {
foreach (var p in members) {
string cmd = _cfg.Global.CmdExecute.Replace("{player}", p.ToString());
rust.RunServerCommand(cmd);
}
}
}
else {
string cmd = _cfg.Global.CmdExecute.Replace("{player}", attacker.UserIDString);
rust.RunServerCommand(cmd);
}
}
#endregion
#region MAIN CONTOLLER
internal class MainController : FacepunchBehaviour {
public DateTime now;
public bool configChanged;
public CurrentSchedule currentSchedule;
private DateTime cacheMessage;
private DateTime cacheNextStartMessage;
private DateTime cacheNextEndMessage;
private bool raidStartedAlert;
public class CurrentSchedule {
private static MainController _parent;
public Dictionary<DayOfWeek, ScheduleSetting> schedule;
public DateTime cachedTime;
public DayOfWeek day;
public ScheduleStatus status;
public bool isRaidTime;
public Range start;
public Range end;
public class Range {
public DayOfWeek day;
public int hour;
public int minute;
}
public CurrentSchedule(MainController parent) {
_parent = parent;
schedule = _cfg.Schedule;
CheckAndCleanScheduleStatus();
cachedTime = _parent.now;
day = cachedTime.DayOfWeek;
status = schedule[day].Status;
isRaidTime = false;
start = new Range();
end = new Range();
LoadCurrentSchedule();
/* //******************************************************************** DEBUG ****************************************************
_instance.Puts("--------------------------------------------------------------");
_instance.Puts("cachedTime: " + cachedTime);
_instance.Puts("dayOfWeek: " + ToDateLangFormat(day, "fr"));
_instance.Puts("status: " + status);
_instance.Puts("isRaidTime: " + isRaidTime);
_instance.Puts("startDay: " + ToDateLangFormat(start.day, "fr"));
_instance.Puts("startHour: " + start.hour);
_instance.Puts("startMinute: " + start.minute);
_instance.Puts("endDay: " + ToDateLangFormat(end.day, "fr"));
_instance.Puts("endHour: " + end.hour);
_instance.Puts("endMinute: " + end.minute);
_instance.Puts("ProgressBarMaxWidth: " + ProgressBarMaxWidth());
_instance.Puts("ProgressPercent: " + ProgressPercent());
_instance.Puts("StartValue: " + StartValue(null));
_instance.Puts("EndValue: " + EndValue(null));
_instance.Puts("--------------------------------------------------------------");
//******************************************************************************************************************************* */
}
public void LoadCurrentSchedule() {
Range startBestValue = GetStartCurrentSchedule().Item1;
bool raidTime = GetStartCurrentSchedule().Item2;
Range endBestValue = GetEndCurrentSchedule(raidTime);
start.day = startBestValue.day;
start.hour = startBestValue.hour;
start.minute = startBestValue.minute;
end.day = endBestValue.day;
end.hour = endBestValue.hour;
end.minute = endBestValue.minute;
isRaidTime = raidTime;
}
private Tuple<Range, bool> GetStartCurrentSchedule(Range startBestValue = null, bool raidTime = false) {
for (int daysChecked = 0; daysChecked < 7; daysChecked++) {
DayOfWeek prevDay = cachedTime.AddDays(-daysChecked).DayOfWeek;
ScheduleStatus prevDayStatus = schedule[prevDay].Status;
if (prevDayStatus == ScheduleStatus.AllowedAllDay) {
if (daysChecked == 0) raidTime = true;
if (!raidTime) break;
startBestValue = new Range() {
day = prevDay, hour = 0, minute = 0
}
;
continue;
}
else if (prevDayStatus == ScheduleStatus.NotAllowedAllDay) {
if (daysChecked == 0) raidTime = false;
if (raidTime) break;
startBestValue = new Range() {
day = prevDay, hour = 0, minute = 0
}
;
continue;
}
else if (prevDayStatus == ScheduleStatus.AllowDuringSchedule) {
if (daysChecked == 0) {
raidTime = false;
foreach (var range in schedule[prevDay].TimeRange) {
TimeSpan startTime = new TimeSpan(range.StartHour, range.StartMinute, 0);
TimeSpan endTime = new TimeSpan(range.EndHour, range.EndMinute, 0);
if (_parent.now.TimeOfDay >= startTime && _parent.now.TimeOfDay <= endTime) {
raidTime = true;
startBestValue = new Range() {
day = prevDay, hour = range.StartHour, minute = range.StartMinute
}
;
if (range.StartHour == 0 && range.StartMinute == 0) continue;
return Tuple.Create<Range, bool>(startBestValue, raidTime);
}
}
if (!raidTime) {
foreach (var range in schedule[prevDay].TimeRange) {
TimeSpan endTime = new TimeSpan(range.EndHour, range.EndMinute, 0);
if (_parent.now.TimeOfDay > endTime) {
startBestValue = new Range() {
day = prevDay, hour = range.EndHour, minute = range.EndMinute
}
;
return Tuple.Create<Range, bool>(startBestValue, raidTime);
}
}
startBestValue = new Range() {
day = prevDay, hour = 0, minute = 0
}
;
continue;
}
break;
}
else {
if (raidTime) {
TimeRange range = schedule[prevDay].TimeRange.LastOrDefault();
if (range.StartHour == 0 && range.StartMinute == 0) {
if (range.EndHour == 23 && range.EndMinute == 59) {
startBestValue = new Range() {
day = prevDay, hour = range.StartHour, minute = range.StartMinute
}
;
continue;
}
else {
break;
}
}
else {
if (range.EndHour == 23 && range.EndMinute == 59) startBestValue = new Range() {
day = prevDay, hour = range.StartHour, minute = range.StartMinute
}
;
break;
}
}
else {
TimeRange range = schedule[prevDay].TimeRange.LastOrDefault();
if (range.EndHour == 23 && range.EndMinute == 59) break;
startBestValue = new Range() {
day = prevDay, hour = range.EndHour, minute = range.EndMinute
}
;
break;
}
}
}
}
return Tuple.Create<Range, bool>(startBestValue, raidTime);
}
private Range GetEndCurrentSchedule(bool raidTime, Range endBestValue = null) {
for (int daysChecked = 0; daysChecked < 7; daysChecked++) {
DayOfWeek nextDay = cachedTime.AddDays(daysChecked).DayOfWeek;
ScheduleStatus nextDayStatus = schedule[nextDay].Status;
if (nextDayStatus == ScheduleStatus.AllowedAllDay) {
if (!raidTime) break;
endBestValue = new Range() {
day = nextDay, hour = 23, minute = 59
}
;
continue;
}
else if (nextDayStatus == ScheduleStatus.NotAllowedAllDay) {
if (raidTime) break;
endBestValue = new Range() {
day = nextDay, hour = 23, minute = 59
}
;
continue;
}
else if (nextDayStatus == ScheduleStatus.AllowDuringSchedule) {
if (daysChecked == 0) {
if (raidTime) {
foreach (var range in schedule[nextDay].TimeRange) {
TimeSpan startTime = new TimeSpan(range.StartHour, range.StartMinute, 0);
TimeSpan endTime = new TimeSpan(range.EndHour, range.EndMinute, 0);
if (_parent.now.TimeOfDay >= startTime && _parent.now.TimeOfDay <= endTime) {
endBestValue = new Range() {
day = nextDay, hour = range.EndHour, minute = range.EndMinute
}
;
if (range.EndHour == 23 && range.EndMinute == 59) continue;
return endBestValue;
}
}
}
else {
foreach (var range in schedule[nextDay].TimeRange) {
TimeSpan startTime = new TimeSpan(range.StartHour, range.StartMinute, 0);
if (_parent.now.TimeOfDay < startTime) {
endBestValue = new Range() {
day = nextDay, hour = range.StartHour, minute = range.StartMinute
}
;
return endBestValue;
}
}
endBestValue = new Range() {
day = nextDay, hour = 23, minute = 59
}
;
continue;
}
}
else {
if (raidTime) {
TimeRange range = schedule[nextDay].TimeRange.FirstOrDefault();
if (range.StartHour == 0 && range.StartMinute == 0) {
if (range.EndHour == 23 && range.EndMinute == 59) {
endBestValue = new Range() {
day = nextDay, hour = range.EndHour, minute = range.EndMinute
}
;
continue;
}
else {
endBestValue = new Range() {
day = nextDay, hour = range.EndHour, minute = range.EndMinute
}
;
break;
}
}
else break;
}
else {
TimeRange range = schedule[nextDay].TimeRange.FirstOrDefault();
endBestValue = new Range() {
day = nextDay, hour = range.StartHour, minute = range.StartMinute
}
;
break;
}
}
}
}
return endBestValue;
}
private void CheckAndCleanScheduleStatus() {
foreach (var schedule in schedule) {
if (schedule.Value.Status == ScheduleStatus.AllowDuringSchedule) {
if(schedule.Value.TimeRange.Count == 0) {
schedule.Value.Status = ScheduleStatus.NotAllowedAllDay;
}
else {
foreach(var x in schedule.Value.TimeRange) {
if (x.StartHour == 0 && x.StartMinute == 0 && x.EndHour == 23 && x.EndMinute == 59) schedule.Value.Status = ScheduleStatus.AllowedAllDay;
}
}
}
}
}
private double CalculateProgressPercentage() {
int startDayValue = ((int)start.day + 6) % 7;
int nowDayValue = ((int)_parent.now.DayOfWeek + 6) % 7;
int endDayValue = ((int)end.day + 6) % 7;
int startDaysDifference = nowDayValue == startDayValue ? 0 : startDayValue - nowDayValue;
int endDaysDifference = nowDayValue == endDayValue ? 0 : endDayValue - nowDayValue;
if (startDaysDifference < 0) startDaysDifference -= 7;
if (endDaysDifference < 0) endDaysDifference += 7;
DateTime startTime = _parent.now.AddDays(startDaysDifference).Date.AddHours(start.hour).AddMinutes(start.minute);
DateTime endTime = _parent.now.AddDays(endDaysDifference).Date.AddHours(end.hour).AddMinutes(end.minute);
TimeSpan totalDuration = endTime - startTime;
TimeSpan timeElapsed = _parent.now - startTime;
return (timeElapsed.TotalSeconds / totalDuration.TotalSeconds) * 100;
}
public float ProgressBarMaxWidth() => 1 - ((float) CalculateProgressPercentage() / 100);
public string ProgressPercent() => Math.Round(CalculateProgressPercentage()).ToString();
public string StartValue(BasePlayer player) => $"{ToDateLangFormat(start.day, player == null ? "en" : _playerSetting.data[player.userID].Language).ToUpper()}: {ToDateLangFormat(start.hour+"h"+start.minute, player == null ? "en" : _playerSetting.data[player.userID].Language)}";
public string EndValue(BasePlayer player) => $"{ToDateLangFormat(end.day, player == null ? "en" : _playerSetting.data[player.userID].Language).ToUpper()}: {ToDateLangFormat(end.hour + "h" + end.minute, player == null ? "en" : _playerSetting.data[player.userID].Language)}";
}
private void Awake() {
if (AllowDuringScheduleNoData() != null) AlertAllowDuringScheduleNoData();
now = UpdateTime();
cacheMessage = now;
cacheNextStartMessage = now;
cacheNextEndMessage = now;
currentSchedule = new CurrentSchedule(this);
InvokeRepeating(UpdateController, 0f, 1f);
InvokeRepeating(NotifyPlayers, 0f, 1f);
}
private void UpdateController() {
now = UpdateTime();
bool isTimeToUpdate = false;
if (now.TimeOfDay > new TimeSpan(currentSchedule.end.hour, currentSchedule.end.minute, 0) || now.DayOfWeek != currentSchedule.day) isTimeToUpdate = true;
if (isTimeToUpdate || CfgScheduleHasChanged()) {
if (AllowDuringScheduleNoData() != null) AlertAllowDuringScheduleNoData();
currentSchedule = new CurrentSchedule(this);
configChanged = false;
raidStartedAlert = false;
cacheMessage = now;
cacheNextStartMessage = now;
cacheNextEndMessage = now;
}
}
private void NotifyPlayers() {
if (cacheMessage.Minute == now.Minute) return;
cacheMessage = now;
if (currentSchedule.status == ScheduleStatus.AllowedAllDay) {
if (_cfg.Message.AllowedMessage && !raidStartedAlert) {
raidStartedAlert = true;
_instance.SendToAllPlayerControllers(key : "Alert.AllowedMessage");
}
if (_cfg.Message.MinuteToEndMessage > 0 && cacheNextEndMessage < now) {
_instance.SendToAllPlayerControllers(key : "Alert.AllowedAllDayMessage", args : new object[] {
currentSchedule.end.day, $"{ToTimeString(currentSchedule.end.hour)}h{ToTimeString(currentSchedule.end.minute)}"
}
);
cacheNextEndMessage = now.AddMinutes(_cfg.Message.MinuteToEndMessage);
}
}
else if (currentSchedule.status == ScheduleStatus.NotAllowedAllDay) {
if (_cfg.Message.FinishedMessage && raidStartedAlert) {
raidStartedAlert = false;
_instance.SendToAllPlayerControllers(key : "Alert.NotAllowedMessage", style : 1);
}
if (_cfg.Message.MinuteToStartMessage > 0 && cacheNextStartMessage < now) {
_instance.SendToAllPlayerControllers(key : "Alert.NotAllowedAllDayMessage", style : 1, args : new object[] {
currentSchedule.end.day, $"{ToTimeString(currentSchedule.end.hour)}h{ToTimeString(currentSchedule.end.minute)}"
}
);
cacheNextStartMessage = now.AddMinutes(_cfg.Message.MinuteToStartMessage);
}
}
else if (currentSchedule.status == ScheduleStatus.AllowDuringSchedule) {
if (currentSchedule.isRaidTime) {
if (_cfg.Message.AllowedMessage && !raidStartedAlert) {
raidStartedAlert = true;
_instance.SendToAllPlayerControllers(key : "Alert.AllowedMessage");
}
if (_cfg.Message.MinuteToEndMessage > 0 && cacheNextEndMessage < now) {
if (now.DayOfWeek == currentSchedule.end.day) _instance.SendToAllPlayerControllers(key : "Alert.MinuteToEndMessageSameDay", style : 1, args : new object[] {
GetRemainingTime(currentSchedule.end.day, currentSchedule.end.hour, currentSchedule.end.minute)
}
);
else _instance.SendToAllPlayerControllers(key : "Alert.MinuteToEndMessage", style : 1, args : new object[] {
currentSchedule.end.day, $"{ToTimeString(currentSchedule.end.hour)}h{ToTimeString(currentSchedule.end.minute)}"
}
);
cacheNextEndMessage = now.AddMinutes(_cfg.Message.MinuteToEndMessage);
}
}
else {
if (_cfg.Message.FinishedMessage && raidStartedAlert) {
raidStartedAlert = false;
_instance.SendToAllPlayerControllers(key : "Alert.NotAllowedMessage", style : 1);
}
if (_cfg.Message.MinuteToStartMessage > 0 && cacheNextStartMessage < now) {
if (now.DayOfWeek == currentSchedule.end.day) _instance.SendToAllPlayerControllers(key : "Alert.MinuteToStartMessageSameDay", args : new object[] {
GetRemainingTime(currentSchedule.end.day, currentSchedule.end.hour, currentSchedule.end.minute)
}
);
else _instance.SendToAllPlayerControllers(key : "Alert.MinuteToStartMessage", args : new object[] {
currentSchedule.end.day, $"{ToTimeString(currentSchedule.end.hour)}h{ToTimeString(currentSchedule.end.minute)}"
}
);
cacheNextStartMessage = now.AddMinutes(_cfg.Message.MinuteToStartMessage);
}
}
}
}
public string GetRemainingTime(DayOfWeek day, int hour, int minute) {
DateTime nextRaidEndTime = new DateTime(now.Year, now.Month, now.Day, hour, minute, 0);
if (nextRaidEndTime <= now) nextRaidEndTime = nextRaidEndTime.AddDays(1);
TimeSpan timeSpan = nextRaidEndTime - now;
int hours = timeSpan.Hours;
int minutes = timeSpan.Minutes;
return $"{hours}h{ToTimeString(minutes + 1)}m";
}
public List<string> AllowDuringScheduleNoData(BasePlayer player = null) {
List<string> scheduleNoData = null;
foreach (var scheduleStatus in _cfg.Schedule) {
if (scheduleStatus.Value.Status == ScheduleStatus.AllowDuringSchedule && scheduleStatus.Value.TimeRange.Count == 0) (scheduleNoData ?? (scheduleNoData = new List<string>())).Add(ToDateLangFormat(scheduleStatus.Key, player != null ? _playerSetting.data[player.userID].Language : "en"));
}
return scheduleNoData;
}
private void AlertAllowDuringScheduleNoData() => _instance.PrintWarning(Lang("AdminPanel.Error.AllowDuringScheduleNoData", null, new object[] {
string.Join(", ", AllowDuringScheduleNoData())
}
));
public bool CfgScheduleHasChanged() => configChanged;
private DateTime UpdateTime() => DateTime.UtcNow.AddHours(Convert.ToInt32(_cfg.Global.Timezone));
private void OnDestroy() {
CancelInvoke(UpdateController);
CancelInvoke(NotifyPlayers);
}
}
#endregion
#region PLAYER CONTOLLER
internal class PlayerController : FacepunchBehaviour {
private BasePlayer player;
private PlayerSetting.Setting playerSetting;
private PlayerData.Data playerData;
public AlertMessage alertMessage;
public DateTime cachedTime;
public DayOfWeek currentDay;
public bool staticUICreated;
public bool forceUpdate;
public bool locker;
public ulong inTc;
private void Awake() {
player = GetComponent<BasePlayer>();
if (!_playerSetting.data.ContainsKey(player.userID)) _playerSetting.data[player.userID] = new PlayerSetting.Setting();
playerSetting = _playerSetting.data[player.userID];
if (!_playerData.data.ContainsKey(player.userID)) _playerData.data[player.userID] = new PlayerData.Data();
playerData = _playerData.data[player.userID];
if(!player.GetComponent<AlertMessage>()) alertMessage = player.gameObject.AddComponent<AlertMessage>();
cachedTime = _mainController.currentSchedule.cachedTime;
currentDay = _mainController.now.DayOfWeek;
InvokeRepeating(DrawPlayerGameUI, 0f, _cfg.Ui.Rate);
InvokeRepeating(UpdatePlayerTimes, 0f, 60f);
}
public void DrawLocker() {
CuiHelper.AddUi(player, UI.CreateContainer(name : UI_PLAYER_PANEL_LOCKER, needsCursor : true, parent : "Under"));
locker = true;
}
public void DrawPanel() {
if (!locker) DrawLocker();
var container = UI.CreateContainer(name : UI_PLAYER_PANEL, color : GetColor(hex : "#000000", alpha : 0.75f), parent : "Hud", blur : false);
UI.CreatePanel(ref container, parent : UI_PLAYER_PANEL, name : "playerPanel", color : GetColor(hex : "#000000", alpha : 0.8f), xMin : 0.35f, xMax : 0.65f, yMin : 0.2f, yMax : 0.85f, blur : true);
UI.CreateSprite(ref container, parent : "playerPanel", name : "left", sprite : "assets/content/ui/ui.background.transparent.linear.psd", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.5f), xMax : 0.005f);
UI.CreateSprite(ref container, parent : "playerPanel", name : "right", sprite : "assets/content/ui/ui.background.transparent.linear.psd", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.5f), xMin : 0.995f);
UI.CreatePanel(ref container, parent : "playerPanel", name : "main", color : GetColor(hex : "#000000", alpha : 0.7f), xMin : 0.005f, xMax : 0.995f);
UI.CreatePanel(ref container, parent : "main", name : "title", xMin : 0.05f, xMax : 0.95f, yMin : 0.9f);
UI.CreateText(ref container, parent : "title", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.3f), text : $"» {_instance.Title.ToUpper()}", size : 25, xMin : 0.05f, align : TextAnchor.LowerLeft, font : "robotocondensed-bold.ttf", outlineColor : GetColor(hex : "#000000", alpha : 0.1f));
UI.CreatePanel(ref container, parent : "main", name : "marge", xMin : 0.05f, xMax : 0.95f, yMin : 0.1f, yMax : 0.875f);
if (_adminControllers.ContainsKey(player.userID)) {
UI.CreateSprite(ref container, parent : "title", name : "admin", sprite : "assets/content/ui/ui.background.transparent.linear.psd", color : GetColor(hex : COLOR_ERROR, alpha : 0.4f), outlineColor : GetColor(hex : "#000000", alpha : 0.1f), xMin : 0.75f, yMax : 0.7f, DistanceX : 2f);
UI.CreatePanel(ref container, parent : "admin", name : "separator", color : GetColor(hex : "#000000", alpha : 0.6f), xMax : 0.991f, yMax : 0.05f);
UI.CreateProtectedButton(ref container, parent : "title", name : "btn", xMin : 0.75f, yMax : 0.7f, command : "craidcontroller.admin.open");
UI.CreateText(ref container, parent : "btn", color : GetColor(hex : COLOR_ERROR), text : _instance.lang.GetMessage("PlayerPanel.Btn.Admin", _instance, player.UserIDString), size : 11, outlineColor : GetColor(hex : "#000000", alpha : 0.3f));
}
int index = 0;
const float height = 0.1f;
const float spacing = 0.02f;
float yMax1 = 1 - (index * (height + spacing));
float yMin1 = yMax1 - height;
UI.CreatePanel(ref container, parent : "marge", name : "language", color : GetColor(hex : "#FFFFFF", alpha : 0.1f), yMin : yMin1, yMax : yMax1);
UI.CreateImage(ref container, parent : "language", name : "img", image : "assets/icons/translate.png", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.5f), outlineColor : GetColor(hex : "#000000", alpha : 0.8f), xMin : 0.05f, xMax : 0.1f, yMin : 0.25f, yMax : 0.75f, DistanceX : 0.1f, DistanceY : 0.1f);
UI.CreateText(ref container, parent : "language", color : GetColor(hex : "#FFFFFF"), text : _instance.lang.GetMessage("PlayerPanel.Language", _instance, player.UserIDString), size : 10, xMin : 0.125f, align : TextAnchor.MiddleLeft, outlineColor : GetColor(hex : "#000000", alpha : 0.3f));
index++;
yMax1 = 1 - (index * (height + spacing));
yMin1 = yMax1 - height;
UI.CreatePanel(ref container, parent : "marge", name : "languageInput", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.35f), xMin : 0.1f, yMin : yMin1, yMax : yMax1);
UI.CreateText(ref container, parent : "languageInput", color : GetColor(hex : "#FFFFFF"), text : _instance.lang.GetMessage("PlayerPanel.Language.Input", _instance, player.UserIDString), size : 10, xMin : 0.05f, xMax : 0.5f, align : TextAnchor.MiddleLeft, outlineColor : GetColor(hex : "#000000", alpha : 0.3f));
UI.CreatePanel(ref container, parent : "languageInput", name : "languageInputLabel", color : GetColor(hex : "#000000", alpha : 0.5f), xMin : 0.55f, xMax : 0.975f, yMin : 0.15f, yMax : 0.85f);
UI.CreateSlider(ref container, parent : "languageInputLabel", name : "slider", current : playerSetting.Language, command : "craidcontroller.player.setting Language");
index++;
if (_cfg.Ui.ActiveUi == ActiveUI.Activated) {
if (_cfg.Ui.AllowPlayerHide) {
float yMax = 1 - (index * (height + spacing));
float yMin = yMax - height;
UI.CreatePanel(ref container, parent : "marge", name : "hideUi", color : GetColor(hex : "#FFFFFF", alpha : 0.1f), yMin : yMin, yMax : yMax);
UI.CreateImage(ref container, parent : "hideUi", name : "img", image : "assets/icons/clear_list.png", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.5f), outlineColor : GetColor(hex : "#000000", alpha : 0.8f), xMin : 0.05f, xMax : 0.1f, yMin : 0.25f, yMax : 0.75f, DistanceX : 0.1f, DistanceY : 0.1f);
UI.CreateText(ref container, parent : "hideUi", color : GetColor(hex : "#FFFFFF"), text : _instance.lang.GetMessage("PlayerPanel.HideUi", _instance, player.UserIDString), size : 10, xMin : 0.125f, align : TextAnchor.MiddleLeft, outlineColor : GetColor(hex : "#000000", alpha : 0.3f));
index++;
yMax = 1 - (index * (height + spacing));
yMin = yMax - height;
UI.CreatePanel(ref container, parent : "marge", name : "hideUiInput", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.35f), xMin : 0.1f, yMin : yMin, yMax : yMax);
UI.CreateText(ref container, parent : "hideUiInput", color : GetColor(hex : "#FFFFFF"), text : _instance.lang.GetMessage("PlayerPanel.HideUi.Input", _instance, player.UserIDString), size : 10, xMin : 0.05f, xMax : 0.5f, align : TextAnchor.MiddleLeft, outlineColor : GetColor(hex : "#000000", alpha : 0.3f));
UI.CreatePanel(ref container, parent : "hideUiInput", name : "hideUiInputLabel", color : GetColor(hex : "#000000", alpha : 0.5f), xMin : 0.875f, xMax : 0.95f, yMin : 0.2f, yMax : 0.75f);
UI.CreateCheckbox(ref container, parent : "hideUiInputLabel", name : "checkbox", color : GetColor(COLOR_PRIMARY, 0.7f), command : $"craidcontroller.player.setting HideUi {playerSetting.HideUi}", isOn : playerSetting.HideUi);
index++;
}
if (_cfg.Ui.AllowPlayerChange && !playerSetting.HideUi) {
float yMax = 1 - (index * (height + spacing));
float yMin = yMax - height;
UI.CreatePanel(ref container, parent : "marge", name : "ui", color : GetColor(hex : "#FFFFFF", alpha : 0.1f), yMin : yMin, yMax : yMax);
UI.CreateImage(ref container, parent : "ui", name : "img", image : "assets/icons/workshop.png", color : GetColor(hex : COLOR_PRIMARY, alpha : 0.5f), outlineColor : GetColor(hex : "#000000", alpha : 0.8f), xMin : 0.05f, xMax : 0.1f, yMin : 0.25f, yMax : 0.75f, DistanceX : 0.1f, DistanceY : 0.1f);
UI.CreateText(ref container, parent : "ui", color : GetColor(hex : "#FFFFFF"), text : _instance.lang.GetMessage("PlayerPanel.Ui", _instance, player.UserIDStr
// ... [Code preview truncated due to length. Full source in attached file] ...