C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System.Globalization;
using System.Reflection;
using System.Text.RegularExpressions;
using AirdropExtended;
using AirdropExtended.Airdrop.Services;
using AirdropExtended.Airdrop.Settings;
using AirdropExtended.Airdrop.Settings.Generate;
using AirdropExtended.Behaviors;
using AirdropExtended.Commands;
using AirdropExtended.Diagnostics;
using AirdropExtended.Permissions;
using AirdropExtended.Rust.Extensions;
using AirdropExtended.WeightedSearch;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Oxide.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Libraries;
using Oxide.Plugins;
using Rust;
using UnityEngine;
using Constants = AirdropExtended.Constants;
using LogType = Oxide.Core.Logging.LogType;
using Timer = Oxide.Core.Libraries.Timer;
// ReSharper disable once CheckNamespace
namespace Oxide.Plugins
{
[Info(Constants.PluginName, "baton", "1.0.9", ResourceId = 1210)]
[Description("Customizable airdrop")]
public class AirdropExtended : RustPlugin
{
private readonly SettingsContext _settingsContext;
private readonly AirdropController _airdropController;
private Dictionary<string, AirdropExtendedCommand> _commands;
public AirdropExtended()
{
_settingsContext = new SettingsContext(() => Config);
_airdropController = new AirdropController(_settingsContext);
}
private void OnServerInitialized()
{
LoadConfig();
Bootstrap();
}
protected override void LoadDefaultConfig()
{
var settings = AirdropSettingsFactory.CreateDefault();
Config.WriteObject(settings);
}
private void Bootstrap()
{
LoadAireSettings();
var commands = CommandFactory.Create(_settingsContext, _airdropController);
PermissionService.RegisterPermissions(this, commands);
_commands = commands.ToDictionary(c => c.Name, c => c);
var consoleSystem = Interface.Oxide.GetLibrary<Command>();
foreach (var command in commands.Where(c => !c.IsChatOnly))
{
var command1 = command;
consoleSystem.AddConsoleCommand(command.Name, this, arg =>
{
command1.Execute(arg, arg.Player());
return true;
});
}
}
private void LoadAireSettings()
{
Diagnostics.MessageToServer("Loaded settings");
var previousSetting = Config.Get<string>("settingsName");
if (!string.IsNullOrEmpty(previousSetting))
{
_settingsContext.Settings = AidropSettingsRepository.LoadFrom(previousSetting);
Diagnostics.MessageToServer("Saved current config settings: {0} to normal config in config/AirdropExtended.json", previousSetting);
Diagnostics.MessageToServer("Copied old settings file to data/{0}.json", previousSetting);
AidropSettingsRepository.Save(_settingsContext.ConfigFile(), _settingsContext.Settings);
AidropSettingsRepository.SaveTo(previousSetting, _settingsContext.Settings);
}
else
{
_settingsContext.Settings = AidropSettingsRepository.Load(Config);
}
_airdropController.ApplySettings();
}
private void Unload()
{
_airdropController.Cleanup();
}
void OnLootEntity(BasePlayer player, BaseEntity entity)
{
var supplyDrop = entity as SupplyDrop;
if (entity == null || player == null || supplyDrop == null)
return;
var settings = _settingsContext.Settings;
Diagnostics.MessageTo(
settings.Localization.NotifyOnPlayerLootingStartedMessage,
settings.CommonSettings.NotifyOnPlayerLootingStarted,
player.displayName);
}
private void OnEntitySpawned(BaseEntity entity)
{
if (_airdropController.IsInitialized())
_airdropController.OnEntitySpawned(entity);
}
private void OnExplosiveThrown(BasePlayer player, BaseEntity entity)
{
if (entity is SupplySignal)
_airdropController.OnSupplySignal(player, entity);
}
#region command handlers
[ChatCommand("aire.load")]
private void LoadSettingsChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.load"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.save")]
private void SaveSettingsChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.save"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.generate")]
private void GenerateSettingsChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.generate"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.reload")]
private void ReloadSettingsChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.reload"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.players")]
private void SetPlayersChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.players"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.event")]
private void SetEventEnabledChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.event"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.supply")]
private void SetSupplyEnabledChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.supply"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.timer")]
private void SetTimerEnabledChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.timer"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.despawntime")]
private void SetDespawnTimeChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.despawntime"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.minfreq")]
private void SetMinFrequencyChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.minfreq"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.maxfreq")]
private void SetMaxFrequencyChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.maxfreq"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.setitem")]
private void SetItemChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.setitem"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.setitemgroup")]
private void SetItemGroupChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.setitemgroup"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.capacity")]
private void SetDropCapacityChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.capacity"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.enableplanelimit")]
private void EnablePlaneLimitChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.enableplanelimit"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.planelimit")]
private void SetPlaneLimitChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.planelimit"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.planespeed")]
private void SetPlaneSpeedChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.planespeed"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.crates")]
private void SetCratesChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.crates"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.onelocation")]
private void SetDropToOneLocationChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.onelocation"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.drop")]
private void CallRandomDropChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.drop"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.massdrop")]
private void CallMassDropChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.massdrop"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.topos")]
private void CallDropToPosChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.topos"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.toplayer")]
private void CallDropToPlayerChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.toplayer"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.tome")]
private void CallDropToMeChatCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.tome"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.localize")]
private void CallLocalizeCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.localize"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.notify")]
private void CallNotifyCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.notify"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.customloot")]
private void CallSetCustomLootCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.customloot"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.pick")]
private void CallSetPickStrategyCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.pick"].ExecuteFromChat(player, command, args);
}
[ChatCommand("aire.test")]
private void CallTestLootCommand(BasePlayer player, string command, string[] args)
{
_commands["aire.test"].ExecuteFromChat(player, command, args);
}
#endregion
}
}
namespace AirdropExtended
{
public sealed class Constants
{
public const string PluginName = "AirdropExtended";
public const string CargoPlanePrefab = "assets/prefabs/npc/cargo plane/cargo_plane.prefab";
}
public sealed class SettingsContext
{
public SettingsContext([NotNull] Func<DynamicConfigFile> configFile)
{
if (configFile == null) throw new ArgumentNullException("configFile");
ConfigFile = configFile;
}
public AirdropSettings Settings { get; set; }
public Func<DynamicConfigFile> ConfigFile { get; set; }
}
}
namespace AirdropExtended.Rust.Extensions
{
public static class LocalizationExtensions
{
public static string GetDirectionsFromAngle(float angle, DirectionLocalizationSettings settings)
{
if (settings == null) throw new ArgumentNullException("settings");
if (angle > 337.5 || angle < 22.5)
return settings.North;
if (angle > 22.5 && angle < 67.5)
return settings.NorthEast;
if (angle > 67.5 && angle < 112.5)
return settings.East;
if (angle > 112.5 && angle < 157.5)
return settings.SouthEast;
if (angle > 157.5 && angle < 202.5)
return settings.South;
if (angle > 202.5 && angle < 247.5)
return settings.SouthWest;
if (angle > 247.5 && angle < 292.5)
return settings.West;
if (angle > 292.5 && angle < 337.5)
return settings.NorthWest;
return string.Empty;
}
}
public static class CargoPlaneExtensions
{
public static void SetPlaneEndPosition(
this CargoPlane plane,
Vector3 startPosition,
Vector3 endPosition,
int planeSpeedInSeconds)
{
if (plane == null) throw new ArgumentNullException("plane");
CargoPlaneFields.StartPositionField.SetValue(plane, startPosition);
CargoPlaneFields.EndPositionField.SetValue(plane, endPosition);
plane.SetSpeed(startPosition, endPosition, planeSpeedInSeconds);
}
public static void SetSpeed(this CargoPlane plane, Vector3 startPosition, Vector3 endPosition, int planeSpeedInSeconds)
{
if (plane == null) throw new ArgumentNullException("plane");
var speed = Vector3.Distance(endPosition, startPosition) / planeSpeedInSeconds;
plane.transform.rotation = Quaternion.LookRotation(endPosition - startPosition);
CargoPlaneFields.SecondsTakenField.SetValue(plane, 0);
CargoPlaneFields.SecondsToTakeField.SetValue(plane, speed);
}
public static void SetSpeed(this CargoPlane plane, int planeSpeedInSeconds)
{
if (plane == null) throw new ArgumentNullException("plane");
var startPosition = (Vector3)CargoPlaneFields.StartPositionField.GetValue(plane);
var endPosition = (Vector3)CargoPlaneFields.EndPositionField.GetValue(plane);
plane.SetSpeed(startPosition, endPosition, planeSpeedInSeconds);
}
public static void NotifyNextDropPosition(this CargoPlane plane, Vector3 dropPos, AirdropSettings settings)
{
Diagnostics.Diagnostics.MessageTo(
settings.Localization.NotifyOnNextDropPositionMessage,
settings.CommonSettings.NotifyOnNextDropPosition,
dropPos.x,
dropPos.y,
dropPos.z);
}
}
}
namespace AirdropExtended.Behaviors
{
public sealed class SupplyDropLandedBehavior : MonoBehaviour
{
private const string DefaultNotifyOnCollisionMessage = "Supply drop has landed at {0:F0},{1:F0},{2:F0}";
private bool _isTriggered;
public string NotifyOnLandedMessage { get; set; }
public bool NotifyOnLanded { get; set; }
public bool NotifyAboutPlayersAroundOnDropLand { get; set; }
public string NotifyAboutPlayersAroundOnDropLandMessage { get; set; }
public bool NotifyAboutDirectionAroundOnDropLand { get; set; }
public string NotifyAboutDirectionAroundOnDropLandMessage { get; set; }
public int DropNotifyMaxDistance { get; set; }
public DirectionLocalizationSettings Settings { get; set; }
public SupplyDropLandedBehavior()
{
NotifyOnLandedMessage = DefaultNotifyOnCollisionMessage;
NotifyOnLanded = true;
}
void OnCollisionEnter(Collision col)
{
if (_isTriggered || col.gameObject.GetComponent<CargoPlane>() != null)
return;
_isTriggered = true;
var baseEntity = GetComponent<BaseEntity>();
var dropPosition = baseEntity.transform.position;
var landedX = dropPosition.x;
var landedY = dropPosition.y;
var landedZ = dropPosition.z;
Diagnostics.Diagnostics.MessageTo(NotifyOnLandedMessage, NotifyOnLanded, landedX, landedY, landedZ);
if (NotifyAboutDirectionAroundOnDropLand || NotifyAboutPlayersAroundOnDropLand)
NotifyPlayersAround(dropPosition, baseEntity);
var despawnBehavior = baseEntity.GetComponent<SupplyDropDespawnBehavior>();
if (despawnBehavior != null)
despawnBehavior.Despawn();
}
private void NotifyPlayersAround(Vector3 dropPosition, BaseEntity baseEntity)
{
var players = BasePlayer.activePlayerList;
var nearbyPlayers = players.Where(p => Vector3.Distance(p.transform.position, dropPosition) < DropNotifyMaxDistance).ToList();
foreach (var player in nearbyPlayers)
{
var distance = Vector3.Distance(player.transform.position, dropPosition);
var dropVector = (baseEntity.transform.position - player.eyes.position).normalized;
var rotation = Quaternion.LookRotation(dropVector);
var compassDirection = LocalizationExtensions.GetDirectionsFromAngle(rotation.eulerAngles.y, Settings);
if (NotifyAboutDirectionAroundOnDropLand)
Diagnostics.Diagnostics.MessageToPlayer(player, NotifyAboutDirectionAroundOnDropLandMessage, distance, compassDirection);
if (NotifyAboutPlayersAroundOnDropLand)
Diagnostics.Diagnostics.MessageToPlayer(player, NotifyAboutPlayersAroundOnDropLandMessage, nearbyPlayers.Count);
}
}
public static void AddTo(
BaseEntity entity,
AirdropSettings settings)
{
if (entity == null) throw new ArgumentNullException("entity");
if (settings == null) throw new ArgumentNullException("settings");
entity.gameObject.AddComponent<SupplyDropLandedBehavior>();
var dropCollisionCheck = entity.gameObject.GetComponent<SupplyDropLandedBehavior>();
dropCollisionCheck.NotifyOnLanded = settings.CommonSettings.NotifyOnCollision;
dropCollisionCheck.NotifyOnLandedMessage = settings.Localization.NotifyOnCollisionMessage;
dropCollisionCheck.DropNotifyMaxDistance = settings.CommonSettings.DropNotifyMaxDistance;
dropCollisionCheck.NotifyAboutDirectionAroundOnDropLand = settings.CommonSettings.NotifyAboutDirectionAroundOnDropLand;
dropCollisionCheck.NotifyAboutDirectionAroundOnDropLandMessage = settings.Localization.NotifyAboutDirectionAroundOnDropLandMessage;
dropCollisionCheck.NotifyAboutPlayersAroundOnDropLand = settings.CommonSettings.NotifyAboutPlayersAroundOnDropLand;
dropCollisionCheck.NotifyAboutPlayersAroundOnDropLandMessage = settings.Localization.NotifyAboutPlayersAroundOnDropLandMessage;
dropCollisionCheck.Settings = settings.Localization.Directions;
}
}
public sealed class SupplyDropDespawnBehavior : MonoBehaviour
{
private const string DefaultNotifyOnDespawnMessage = "Supply drop has been despawned at <color=red>{0:F0},{1:F0},{2:F0}</color>";
private const float DefaultSupplyStayTime = 300.0f;
private bool _isTriggered;
private Timer.TimerInstance _timerInstance;
private BaseEntity _baseEntity;
public float TimeoutInSeconds { get; set; }
public string NotifyOnDespawnMessage { get; set; }
public bool NotifyOnDespawn { get; set; }
public SupplyDropDespawnBehavior()
{
TimeoutInSeconds = DefaultSupplyStayTime;
NotifyOnDespawnMessage = DefaultNotifyOnDespawnMessage;
NotifyOnDespawn = false;
}
public void Despawn()
{
if (_isTriggered)
return;
_baseEntity = gameObject.GetComponent<BaseEntity>();
_isTriggered = true;
_timerInstance = Interface.Oxide.GetLibrary<Timer>("Timer").Once(TimeoutInSeconds, DespawnCallback);
}
private void DespawnCallback()
{
var x = _baseEntity.transform.position.x;
var y = _baseEntity.transform.position.y;
var z = _baseEntity.transform.position.z;
Diagnostics.Diagnostics.MessageTo(NotifyOnDespawnMessage, NotifyOnDespawn, x, y, z);
_baseEntity.KillMessage();
OnDestroy();
}
void OnDestroy()
{
_baseEntity = null;
if (_timerInstance == null || _timerInstance.Destroyed)
return;
_timerInstance.Destroy();
_timerInstance = null;
_isTriggered = false;
}
public static void AddTo(BaseEntity supplyDrop, AirdropSettings settings)
{
if (supplyDrop == null) throw new ArgumentNullException("supplyDrop");
if (settings == null) throw new ArgumentNullException("settings");
var supplyCrateDespawnTime = settings.CommonSettings.SupplyCrateDespawnTime;
if (supplyCrateDespawnTime <= TimeSpan.Zero)
return;
var timeoutInSeconds = Convert.ToSingle(supplyCrateDespawnTime.TotalSeconds);
supplyDrop.gameObject.AddComponent<SupplyDropDespawnBehavior>();
var despawnBehavior = supplyDrop.gameObject.GetComponent<SupplyDropDespawnBehavior>();
despawnBehavior.TimeoutInSeconds = timeoutInSeconds;
despawnBehavior.NotifyOnDespawn = settings.CommonSettings.NotifyOnDespawn;
despawnBehavior.NotifyOnDespawnMessage = settings.Localization.NotifyOnDespawnMessage;
}
}
public sealed class PlaneNotifyOnDestroyBehavior : MonoBehaviour
{
public Action<CargoPlane> Callback { get; set; }
void OnDestroy()
{
Diagnostics.Diagnostics.MessageToServer("On destroy plane");
if (Callback == null)
return;
var cargoPlane = GetComponent<CargoPlane>();
if (cargoPlane != null)
{
Callback(cargoPlane);
Diagnostics.Diagnostics.MessageToServer("cargoPlane [id:{0}] was destroyed", cargoPlane.GetInstanceID());
}
Callback = null;
}
}
public sealed class MultipleCratesBehavior : MonoBehaviour
{
public int TotalCratesToDrop { get; set; }
public Vector3 InitialEndPosition { get; set; }
public bool DropToOneLocation { get; set; }
public int DroppedCrates { get; set; }
private Vector3 IntersectionPoint { get; set; }
public void OnPlaneDroppedCrate(CargoPlane plane, AirdropSettings settings, Vector3 position)
{
DroppedCrates++;
var planeSpeedInSeconds = settings.CommonSettings.PlaneSpeedInSeconds;
if (DroppedCrates >= TotalCratesToDrop)
{
plane.SetPlaneEndPosition(position, InitialEndPosition, planeSpeedInSeconds);
return;
}
if (IntersectionPoint == Vector3.zero)
IntersectionPoint = GetIntersectionPoint(settings.DropLocation, position, InitialEndPosition);
CargoPlaneFields.DroppedField.SetValue(plane, false);
Vector3 currentEndPos;
Vector3 nextDropPosition;
if (DropToOneLocation)
{
currentEndPos = Vector3.MoveTowards(position, InitialEndPosition, 50f);
nextDropPosition = Vector3.MoveTowards(position, InitialEndPosition,
25f);
}
else
{
var cratesToDrop = (TotalCratesToDrop - DroppedCrates);
var distanceToNextEndPos = Vector3.Distance(position, IntersectionPoint) / cratesToDrop;
var distanceToNextDrop = distanceToNextEndPos / 2;
currentEndPos = Vector3.MoveTowards(position, IntersectionPoint, distanceToNextEndPos);
nextDropPosition = Vector3.MoveTowards(position, IntersectionPoint, distanceToNextDrop);
}
plane.NotifyNextDropPosition(nextDropPosition, settings);
CargoPlaneFields.DropPositionField.SetValue(plane, nextDropPosition);
plane.SetPlaneEndPosition(position, currentEndPos, planeSpeedInSeconds);
}
public Vector3 GetIntersectionPoint(DropLocationSettings settings, Vector3 position, Vector3 endpos)
{
var lines = new List<Vector2[]>
{
new[] {new Vector2(settings.MinX, settings.MinZ), new Vector2(settings.MinX, settings.MaxZ)},
new[] {new Vector2(settings.MinX, settings.MaxZ), new Vector2(settings.MaxX, settings.MaxZ)},
new[] {new Vector2(settings.MaxX, settings.MaxZ), new Vector2(settings.MaxX, settings.MinZ)},
new[] {new Vector2(settings.MaxX, settings.MinZ), new Vector2(settings.MinX, settings.MinZ)},
};
var lineStart = new Vector2(position.x, position.z);
var lineEnd = new Vector2(endpos.x, endpos.z);
foreach (var line in lines)
{
var intersectionPoint = LineIntersectionPoint(line[0], line[1], lineStart, lineEnd);
if (intersectionPoint != Vector2.zero)
return new Vector3(intersectionPoint.x, position.y, intersectionPoint.y);
}
return Vector3.zero;
}
private Vector2 LineIntersectionPoint(Vector2 lineOneStart, Vector2 lineOneEnd1, Vector2 lineTwoStart, Vector2 lineTwoEnd)
{
var d = (lineOneStart.x - lineOneEnd1.x) * (lineTwoStart.y - lineTwoEnd.y) - (lineOneStart.y - lineOneEnd1.y) * (lineTwoStart.x - lineTwoEnd.x);
if (Math.Abs(d) < 0.01)
return Vector2.zero;
var xi = ((lineTwoStart.x - lineTwoEnd.x) * (lineOneStart.x * lineOneEnd1.y - lineOneStart.y * lineOneEnd1.x) - (lineOneStart.x - lineOneEnd1.x) * (lineTwoStart.x * lineTwoEnd.y - lineTwoStart.y * lineTwoEnd.x)) / d;
var yi = ((lineTwoStart.y - lineTwoEnd.y) * (lineOneStart.x * lineOneEnd1.y - lineOneStart.y * lineOneEnd1.x) - (lineOneStart.y - lineOneEnd1.y) * (lineTwoStart.x * lineTwoEnd.y - lineTwoStart.y * lineTwoEnd.x)) / d;
var p = new Vector2(xi, yi);
if (xi < Math.Min(lineOneStart.x, lineOneEnd1.x) || xi > Math.Max(lineOneStart.x, lineOneEnd1.x))
return Vector2.zero;
if (xi < Math.Min(lineTwoStart.x, lineTwoEnd.x) || xi > Math.Max(lineTwoStart.x, lineTwoEnd.x))
return Vector2.zero;
return p;
}
}
public static class SupplyDropBehaviorService
{
public static void AttachCustomBehaviorsToSupplyDrops(AirdropSettings settings)
{
if (settings == null)
throw new ArgumentNullException("settings");
var supplyDrops = UnityEngine.Object.FindObjectsOfType<SupplyDrop>();
foreach (var supplyDrop in supplyDrops)
{
var despawnBehavior = supplyDrop.GetComponent<SupplyDropDespawnBehavior>();
if (Equals(despawnBehavior, null))
SupplyDropDespawnBehavior.AddTo(supplyDrop, settings);
despawnBehavior = supplyDrop.GetComponent<SupplyDropDespawnBehavior>();
var hasParachute = HasParachute(supplyDrop);
var collisionBehavior = supplyDrop.GetComponent<SupplyDropLandedBehavior>();
if (hasParachute && Equals(collisionBehavior, null))
SupplyDropLandedBehavior.AddTo(supplyDrop, settings);
if (hasParachute)
continue;
despawnBehavior.Despawn();
}
}
private static bool HasParachute(SupplyDrop supplyDrop)
{
var parachuteField = typeof(SupplyDrop).GetField("parachute",
Interface.Oxide.GetLibrary<Oxide.Game.Rust.Libraries.Rust>().PrivateBindingFlag());
if (parachuteField == null)
return false;
return parachuteField.GetValue(supplyDrop) != null;
}
public static void RemoveCustomBehaviorsFromSupplyDrops()
{
var despawnBehaviors = UnityEngine.Object.FindObjectsOfType<SupplyDropDespawnBehavior>();
if (despawnBehaviors != null && despawnBehaviors.Any())
{
foreach (var despawnBehavior in despawnBehaviors)
UnityEngine.Object.Destroy(despawnBehavior);
}
var landBehaviors = UnityEngine.Object.FindObjectsOfType<SupplyDropLandedBehavior>();
if (landBehaviors != null && landBehaviors.Any())
{
foreach (var landBehavior in landBehaviors)
UnityEngine.Object.Destroy(landBehavior);
}
}
}
}
namespace AirdropExtended.Diagnostics
{
public static class Diagnostics
{
public static string Prefix = "aire:";
public static string Color = "orange";
private const string Format = "<color={0}>{1}</color>";
public static void MessageTo(string message, bool sendToAll, params object[] args)
{
if (sendToAll)
MessageToAll(message, args);
MessageToServer(message, args);
}
public static void MessageToPlayer(BasePlayer player, string message, params object[] args)
{
player.SendConsoleCommand("chat.add", new object[] { 0, string.Format(Format, Color, Prefix) + string.Format(message, args), 1f });
}
public static void MessageToAll(string message, params object[] args)
{
var msg = string.Format(Format, Color, Prefix) + string.Format(message, args);
ConsoleSystem.Broadcast("chat.add \"SERVER\" " + msg.Quote() + " 1.0", new object[0]);
}
public static void MessageToServer(string message, params object[] args)
{
Interface.GetMod().RootLogger.Write(LogType.Info, string.Format("{0}{1}", Prefix, message), args);
}
public static void MessageToServerAndPlayer(BasePlayer player, string message, params object[] args)
{
if (player != null)
MessageToPlayer(player, message, args);
MessageToServer(message, args);
}
}
}
namespace AirdropExtended.Permissions
{
public static class PermissionService
{
public static Permission Permission = Interface.GetMod().GetLibrary<Permission>();
public static bool HasPermission(BasePlayer player, string permissionName)
{
if (player == null || string.IsNullOrEmpty(permissionName))
return false;
var uid = Convert.ToString(player.userID);
if (Permission.UserHasPermission(uid, permissionName))
return true;
return false;
}
public static void RegisterPermissions(Plugin owner, List<AirdropExtendedCommand> commands)
{
if (owner == null) throw new ArgumentNullException("owner");
if (commands == null) throw new ArgumentNullException("commands");
foreach (var permissionName in commands.Select(c => c.PermissionName))
{
if (!Permission.PermissionExists(permissionName))
Permission.RegisterPermission(permissionName, owner);
}
}
}
}
namespace AirdropExtended.Commands
{
public abstract class AirdropExtendedCommand
{
public string Name { get; private set; }
public string PermissionName { get; private set; }
public bool IsChatOnly { get; private set; }
protected AirdropExtendedCommand(string name, string permissionName = "", bool chatOnly = false)
{
if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
Name = name;
PermissionName = permissionName;
IsChatOnly = chatOnly;
}
public virtual void ExecuteFromChat(BasePlayer player, string command, string[] args)
{
if (player == null || !PermissionService.HasPermission(player, PermissionName) || !player.IsAdmin())
{
Diagnostics.Diagnostics.MessageToPlayer(player, "You are not admin.You are required to have permission \"{0}\" to run command: {1}", PermissionName, Name);
return;
}
var commandString = args.Aggregate(command, (s, s1) => s + " " + s1.Quote());
Diagnostics.Diagnostics.MessageToServer("'{0}' called by {1}", commandString, player.displayName);
var commandArgs = new ConsoleSystem.Arg(commandString);
ExecuteInternal(commandArgs, player);
}
public virtual void Execute(ConsoleSystem.Arg arg, BasePlayer player)
{
if (player != null && !PermissionService.HasPermission(player, PermissionName) && !player.IsAdmin())
{
Diagnostics.Diagnostics.MessageToPlayer(player, "You are not admin.You are required to have permission \"{0}\" to run command: {1}", PermissionName, Name);
return;
}
ExecuteInternal(arg, player);
}
protected abstract void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player);
protected void PrintUsage(BasePlayer player)
{
var message = GetUsageString();
if (player != null)
Diagnostics.Diagnostics.MessageToPlayer(player, message);
Diagnostics.Diagnostics.MessageToServer(message);
}
protected virtual string GetUsageString()
{
return GetDefaultUsageString();
}
protected string GetDefaultUsageString(params string[] parameters)
{
var parameterString = string.Join(" ", parameters);
return string.Format("Command use {0} {1}", Name, parameterString);
}
}
public class LoadSettingsCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public LoadSettingsCommand(
SettingsContext context,
AirdropController controller)
: base("aire.load", "airdropextended.canLoad")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var settingsName = arg.GetString(0);
if (string.IsNullOrEmpty(settingsName))
{
PrintUsage(player);
return;
}
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Loading settings: {0}", settingsName);
var settings = AidropSettingsRepository.LoadFrom(settingsName);
if (settings == null)
{
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Failed to load settings, no such file: ", settingsName);
return;
}
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("settingsName");
}
}
public class ReloadSettingsCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public ReloadSettingsCommand(
SettingsContext context,
AirdropController controller)
: base("aire.reload", "airdropextended.canReload")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Reloading plugin");
_context.Settings = AidropSettingsRepository.Load(_context.ConfigFile());
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("settingsName");
}
}
public class SaveSettingsCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
public SaveSettingsCommand(SettingsContext context)
: base("aire.save", "airdropextended.canSave")
{
if (context == null) throw new ArgumentNullException("context");
_context = context;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
var settingsName = arg.GetString(0, string.Empty);
if (string.IsNullOrEmpty(settingsName))
{
AidropSettingsRepository.Save(_context.ConfigFile(), _context.Settings);
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Saved settings to default config");
return;
}
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Saving settings to: {0}", settingsName);
AidropSettingsRepository.SaveTo(settingsName, _context.Settings);
}
protected override string GetUsageString()
{
return GetDefaultUsageString("settingsName");
}
}
public class GenerateDefaultSettingsAndSaveCommand : AirdropExtendedCommand
{
public GenerateDefaultSettingsAndSaveCommand()
: base("aire.generate", "airdropextended.canGenerate")
{ }
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var settingsName = arg.GetString(0);
if (string.IsNullOrEmpty(settingsName))
{
PrintUsage(player);
return;
}
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Generating default settings to {0}", settingsName);
var settings = AirdropSettingsFactory.CreateDefault();
AidropSettingsRepository.SaveTo(settingsName, settings);
}
protected override string GetUsageString()
{
return GetDefaultUsageString("settingsName");
}
}
public class SetDropMinFrequencyCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetDropMinFrequencyCommand(SettingsContext context, AirdropController controller)
: base("aire.minfreq", "airdropextended.canMinFreq")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var frequency = arg.GetInt(0);
frequency = frequency < 0 ? 0 : frequency;
_context.Settings.CommonSettings.MinDropFrequency = TimeSpan.FromSeconds(frequency);
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting min frequency to {0}", frequency);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("3600");
}
}
public class SetDropMaxFrequencyCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetDropMaxFrequencyCommand(SettingsContext context, AirdropController controller)
: base("aire.maxfreq", "airdropextended.canMaxFreq")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var frequency = arg.GetInt(0);
frequency = frequency < 0 ? 0 : frequency;
_context.Settings.CommonSettings.MaxDropFrequency = TimeSpan.FromSeconds(frequency);
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting max frequency to {0}", frequency);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("3600");
}
}
public class SetPlayersCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetPlayersCommand(SettingsContext context, AirdropController controller)
: base("aire.players", "airdropextended.canPlayers")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var players = arg.GetInt(0);
players = players < 0 ? 0 : players;
_context.Settings.CommonSettings.MinimumPlayerCount = players;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting min players to {0}", players);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("25");
}
}
public class SetTimerEnabledCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetTimerEnabledCommand(SettingsContext context, AirdropController controller)
: base("aire.timer", "airdropextended.canTimer")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var pluginAirdropTimerEnabled = arg.GetBool(0);
_context.Settings.CommonSettings.PluginAirdropTimerEnabled = pluginAirdropTimerEnabled;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting plugin timer enabled to {0}", pluginAirdropTimerEnabled);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("true");
}
}
public class SetEventEnabledCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetEventEnabledCommand(SettingsContext context, AirdropController controller)
: base("aire.event", "airdropextended.canEvent")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var builtInAirdropEnabled = arg.GetBool(0);
_context.Settings.CommonSettings.BuiltInAirdropEnabled = builtInAirdropEnabled;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting built in airdrop enabled to {0}", builtInAirdropEnabled);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("true");
}
}
public class SetSupplyDropEnabledCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetSupplyDropEnabledCommand(SettingsContext context, AirdropController controller)
: base("aire.supply", "airdropextended.canSupply")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var supplyDropTimerEnabled = arg.GetBool(0);
_context.Settings.CommonSettings.SupplySignalsEnabled = supplyDropTimerEnabled;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting supply signals enabled to {0}", supplyDropTimerEnabled);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("true");
}
}
public class SetPlaneSpeedCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetPlaneSpeedCommand(SettingsContext context, AirdropController controller)
: base("aire.planespeed", "airdropextended.canPlaneSpeed")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var planeSpeedInSeconds = arg.GetInt(0);
_context.Settings.CommonSettings.PlaneSpeedInSeconds = planeSpeedInSeconds;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting plane speed in seconds to {0}", planeSpeedInSeconds);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("300");
}
}
public class SetCrateCountCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetCrateCountCommand(SettingsContext context, AirdropController controller)
: base("aire.crates", "airdropextended.canCrates")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var minCrates = arg.GetInt(0);
var maxCrates = arg.HasArgs(2) ? arg.GetInt(1) : minCrates;
_context.Settings.CommonSettings.MinCrates = minCrates;
_context.Settings.CommonSettings.MaxCrates = maxCrates;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting min/max crates to {0}-{1}", minCrates, maxCrates);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("300");
}
}
public class SetDropToOneLocationCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetDropToOneLocationCommand(SettingsContext context, AirdropController controller)
: base("aire.onelocation", "airdropextended.canOneLocation")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var oneLocation = arg.GetBool(0);
_context.Settings.CommonSettings.DropToOneLocation = oneLocation;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting drop to one location to {0}", oneLocation);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("true");
}
}
public class SetPlaneLimitEnabledCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetPlaneLimitEnabledCommand(SettingsContext context, AirdropController controller)
: base("aire.enableplanelimit", "airdropextended.canEnablePlaneLimit")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var maximumPlaneLimitEnabled = arg.GetBool(0);
_context.Settings.CommonSettings.MaximumPlaneLimitEnabled = maximumPlaneLimitEnabled;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting plane limit enabled to {0}", maximumPlaneLimitEnabled);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("true");
}
}
public class SetPlaneLimitCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetPlaneLimitCommand(SettingsContext context, AirdropController controller)
: base("aire.planelimit", "airdropextended.canPlaneLimit")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var planeLimit = arg.GetInt(0);
planeLimit = planeLimit < 0 ? 0 : planeLimit;
_context.Settings.CommonSettings.MaximumNumberOfPlanesInTheAir = planeLimit;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Setting plane in air limit to {0}", planeLimit);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("10");
}
}
public class SetDespawnTimeCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
public SetDespawnTimeCommand(SettingsContext context, AirdropController controller)
: base("aire.despawntime", "airdropextended.canDespawnTime")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
var despawnTimeInSeconds = arg.GetInt(0);
despawnTimeInSeconds = despawnTimeInSeconds < 0 ? 0 : despawnTimeInSeconds;
_context.Settings.CommonSettings.SupplyCrateDespawnTime = TimeSpan.FromSeconds(despawnTimeInSeconds);
Diagnostics.Diagnostics.MessageToServerAndPlayer(player, "Set SupplyCrateDespawnTime to {0}", _context.Settings.CommonSettings.SupplyCrateDespawnTime);
_controller.ApplySettings();
}
protected override string GetUsageString()
{
return GetDefaultUsageString("300");
}
}
public class SetItemSettingsCommand : AirdropExtendedCommand
{
private readonly SettingsContext _context;
private readonly AirdropController _controller;
private readonly string _usageString;
public SetItemSettingsCommand(SettingsContext context, AirdropController controller)
: base("aire.setitem", "airdropextended.canSetItem")
{
if (context == null) throw new ArgumentNullException("context");
if (controller == null) throw new ArgumentNullException("controller");
_context = context;
_controller = controller;
var usageStrings = new[]
{
GetDefaultUsageString("item_name [category] [chance] [min] [max]"),
string.Format("Example: {0} Weapon rocket_launcher 15 1 1 false.", Name),
"default chance=0, min=0, max=0."
};
_usageString = string.Join(Environment.NewLine, usageStrings);
}
protected override void ExecuteInternal(ConsoleSystem.Arg arg, BasePlayer player)
{
if (!arg.HasArgs())
{
PrintUsage(player);
return;
}
string categoryName;
string itemName;
float chance;
int minAmount;
int maxAmount;
try
{
categoryName = arg.GetString(0);
itemName = arg.GetString(1);
chance = arg.GetFloat(2);
minAmount = arg.GetInt(3);
maxAmount = arg.GetInt(4);
}
catch (Exception)
{
PrintUsage(player);
return;
}
var item = _context.Settings.FindItem(categoryName, itemName);
item.ChanceInPercent = chance;
item.MinAmount = minAmount;
item.MaxAmount = maxAmount;
Diagnostics.Diagnostics.MessageToServerAndPlayer(player,
"Set settings to item:{0}, chance:{1}, min_amount:{2}, max_amount:{3}",
itemName,
chance,
minAmount,
maxAmount);
_control
// ... [Code preview truncated due to length. Full source in attached file] ...