C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// #define DEBUG
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using Facepunch;
using Network;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Plugins;
using Oxide.Game.Rust;
using Rust.Modular;
using UnityEngine;
namespace Oxide.Plugins {
[Info("Vehicle Licence", "Sorrow/TheDoc/Arainrr", "1.7.25")]
[Description("Allows players to buy vehicles and then spawn or store it")]
public class VehicleLicence : RustPlugin {
#region Fields
[PluginReference]
private readonly Plugin Economics, ServerRewards, Friends, Clans, NoEscape, LandOnCargoShip, RustTranslationAPI;
private const string PERMISSION_USE = "vehiclelicence.use";
private const string PERMISSION_ALL = "vehiclelicence.all";
private const string PERMISSION_ADMIN = "vehiclelicence.admin";
private const string PERMISSION_BYPASS_COST = "vehiclelicence.bypasscost";
private const int ITEMID_FUEL = -946369541;
private const string PREFAB_ITEM_DROP = "assets/prefabs/misc/item drop/item_drop.prefab";
private const string PREFAB_ROWBOAT = "assets/content/vehicles/boats/rowboat/rowboat.prefab";
private const string PREFAB_RHIB = "assets/content/vehicles/boats/rhib/rhib.prefab";
private const string PREFAB_SEDAN = "assets/content/vehicles/sedan_a/sedantest.entity.prefab";
private const string PREFAB_HOTAIRBALLOON = "assets/prefabs/deployable/hot air balloon/hotairballoon.prefab";
private const string PREFAB_MINICOPTER = "assets/content/vehicles/minicopter/minicopter.entity.prefab";
private const string PREFAB_TRANSPORTCOPTER = "assets/content/vehicles/scrap heli carrier/scraptransporthelicopter.prefab";
private const string PREFAB_CHINOOK = "assets/prefabs/npc/ch47/ch47.entity.prefab";
private const string PREFAB_RIDABLEHORSE = "assets/rust.ai/nextai/testridablehorse.prefab";
private const string PREFAB_WORKCART = "assets/content/vehicles/workcart/workcart.entity.prefab";
private const string PREFAB_MAGNET_CRANE = "assets/content/vehicles/crane_magnet/magnetcrane.entity.prefab";
private const string PREFAB_SUBMARINE_DUO = "assets/content/vehicles/submarine/submarineduo.entity.prefab";
private const string PREFAB_SUBMARINE_SOLO = "assets/content/vehicles/submarine/submarinesolo.entity.prefab";
private const string PREFAB_CHASSIS_SMALL = "assets/content/vehicles/modularcar/car_chassis_2module.entity.prefab";
private const string PREFAB_CHASSIS_MEDIUM = "assets/content/vehicles/modularcar/car_chassis_3module.entity.prefab";
private const string PREFAB_CHASSIS_LARGE = "assets/content/vehicles/modularcar/car_chassis_4module.entity.prefab";
private const string PREFAB_SNOWMOBILE = "assets/content/vehicles/snowmobiles/snowmobile.prefab";
private const string PREFAB_SNOWMOBILE_TOMAHA = "assets/content/vehicles/snowmobiles/tomahasnowmobile.prefab";
private const int LAYER_GROUND = Rust.Layers.Solid | Rust.Layers.Mask.Water;
private static object False;
private Timer _checkVehiclesTimer;
public static VehicleLicence Instance {
get;
private set;
}
public readonly Dictionary<BaseEntity, Vehicle> vehiclesCache = new Dictionary<BaseEntity, Vehicle>();
public readonly Dictionary<string, BaseVehicleS> allBaseVehicleSettings = new Dictionary<string, BaseVehicleS>();
public readonly Dictionary<string, string> commandToVehicleType = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public enum NormalVehicleType {
Rowboat, RHIB, Sedan, HotAirBalloon, MiniCopter, TransportHelicopter, Chinook, RidableHorse, WorkCart, MagnetCrane, SubmarineSolo, SubmarineDuo, Snowmobile, TomahaSnowmobile,
}
public enum ChassisType {
Small, Medium, Large
}
#endregion Fields
#region Oxide Hooks
private void Init() {
LoadData();
False = false;
Instance = this;
permission.RegisterPermission(PERMISSION_USE, this);
permission.RegisterPermission(PERMISSION_ALL, this);
permission.RegisterPermission(PERMISSION_ADMIN, this);
permission.RegisterPermission(PERMISSION_BYPASS_COST, this);
foreach (NormalVehicleType value in Enum.GetValues(typeof(NormalVehicleType))) {
allBaseVehicleSettings.Add(value.ToString(), GetBaseVehicleS(value));
}
foreach (var entry in configData.modularCarS) {
allBaseVehicleSettings.Add(entry.Key, entry.Value);
}
foreach (var entry in allBaseVehicleSettings) {
var baseVehicleS = entry.Value;
if (baseVehicleS.usePermission && !string.IsNullOrEmpty(baseVehicleS.permission) && !permission.PermissionExists(baseVehicleS.permission, this)) {
permission.RegisterPermission(baseVehicleS.permission, this);
}
foreach (var perm in baseVehicleS.cooldownPermissions.Keys) {
if (!permission.PermissionExists(perm, this)) {
permission.RegisterPermission(perm, this);
}
}
foreach (var command in baseVehicleS.commands) {
if (string.IsNullOrEmpty(command)) continue;
if (!commandToVehicleType.ContainsKey(command)) {
commandToVehicleType.Add(command, entry.Key);
}
else {
PrintError($"You have the same two commands({command}).");
}
if (configData.chatS.useUniversalCommand) {
cmd.AddChatCommand(command, this, nameof(CmdUniversal));
}
if (!string.IsNullOrEmpty(configData.chatS.customKillCommandPrefix)) {
cmd.AddChatCommand(configData.chatS.customKillCommandPrefix + command, this, nameof(CmdCustomKill));
}
}
}
cmd.AddChatCommand(configData.chatS.helpCommand, this, nameof(CmdLicenseHelp));
cmd.AddChatCommand(configData.chatS.buyCommand, this, nameof(CmdBuyVehicle));
cmd.AddChatCommand(configData.chatS.spawnCommand, this, nameof(CmdSpawnVehicle));
cmd.AddChatCommand(configData.chatS.recallCommand, this, nameof(CmdRecallVehicle));
cmd.AddChatCommand(configData.chatS.killCommand, this, nameof(CmdKillVehicle));
Unsubscribe(nameof(CanMountEntity));
Unsubscribe(nameof(OnEntityTakeDamage));
Unsubscribe(nameof(OnEntityDismounted));
Unsubscribe(nameof(OnEntityEnter));
Unsubscribe(nameof(CanLootEntity));
Unsubscribe(nameof(OnEntitySpawned));
}
private void OnServerInitialized() {
if (configData.globalS.storeVehicle) {
var currentTimestamp = TimeEx.currentTimestamp;
foreach (var vehicleEntries in storedData.playerData) {
foreach (var vehicleEntry in vehicleEntries.Value) {
vehicleEntry.Value.lastRecall = vehicleEntry.Value.lastDismount = currentTimestamp;
vehicleEntry.Value.playerID = vehicleEntries.Key;
vehicleEntry.Value.vehicleType = vehicleEntry.Key;
if (vehicleEntry.Value.entityID == 0) {
continue;
}
vehicleEntry.Value.entity = BaseNetworkable.serverEntities.Find(vehicleEntry.Value.entityID) as BaseEntity;
if (vehicleEntry.Value.entity == null || vehicleEntry.Value.entity.IsDestroyed) {
vehicleEntry.Value.entityID = 0;
}
else {
vehiclesCache.Add(vehicleEntry.Value.entity, vehicleEntry.Value);
}
}
}
}
if (configData.globalS.preventMounting) {
Subscribe(nameof(CanMountEntity));
}
if (configData.globalS.noDecay) {
Subscribe(nameof(OnEntityTakeDamage));
}
if (configData.globalS.preventDamagePlayer) {
Subscribe(nameof(OnEntityEnter));
}
if (configData.globalS.preventLooting) {
Subscribe(nameof(CanLootEntity));
}
if (configData.globalS.autoClaimFromVendor) {
Subscribe(nameof(OnEntitySpawned));
Subscribe(nameof(OnRidableAnimalClaimed));
}
if (configData.globalS.checkVehiclesInterval > 0 && allBaseVehicleSettings.Any(x => x.Value.wipeTime > 0)) {
Subscribe(nameof(OnEntityDismounted));
_checkVehiclesTimer = timer.Every(configData.globalS.checkVehiclesInterval, CheckVehicles);
}
}
private void Unload() {
_checkVehiclesTimer?.Destroy();
if (!configData.globalS.storeVehicle) {
foreach (var entry in vehiclesCache.ToArray()) {
if (entry.Key != null && !entry.Key.IsDestroyed) {
RefundVehicleItems(entry.Value, entry.Key, isUnload : true);
entry.Key.Kill(BaseNetworkable.DestroyMode.Gib);
}
entry.Value.entityID = 0;
}
}
SaveData();
False = Instance = null;
}
private void OnServerSave() => timer.Once(UnityEngine.Random.Range(0f, 60f), SaveData);
private void OnPlayerConnected(BasePlayer player) {
if (player == null || !player.userID.IsSteamId()) return;
if (permission.UserHasPermission(player.UserIDString, PERMISSION_BYPASS_COST)) {
PurchaseAllVehicles(player.userID);
}
}
private void OnEntityDismounted(BaseMountable entity, BasePlayer player) {
var vehicleParent = entity?.VehicleParent();
if (vehicleParent == null || vehicleParent.IsDestroyed) return;
Vehicle vehicle;
if (!vehiclesCache.TryGetValue(vehicleParent, out vehicle)) {
return;
}
vehicle.OnDismount();
}
#region Mount
private object CanMountEntity(BasePlayer friend, BaseMountable entity) {
if (friend == null || entity == null) return null;
var vehicleParent = entity.VehicleParent();
if (vehicleParent == null || vehicleParent.IsDestroyed) return null;
Vehicle vehicle;
if (!vehiclesCache.TryGetValue(vehicleParent, out vehicle)) return null;
if (AreFriends(vehicle.playerID, friend.userID)) return null;
if (configData.globalS.preventDriverSeat && vehicleParent.HasMountPoints()) {
foreach (var allMountPoint in vehicleParent.allMountPoints) {
if (allMountPoint != null && allMountPoint.mountable == entity) {
if (!allMountPoint.isDriver) {
return null;
}
break;
}
}
}
if (HasAdminPermission(friend)) {
return null;
}
SendCantUseMessage(friend, vehicle);
return False;
}
#endregion Mount
#region Loot
private object CanLootEntity(BasePlayer friend, StorageContainer container) {
if (friend == null || container == null) return null;
var parentEntity = container.GetParentEntity();
if (parentEntity == null) return null;
Vehicle vehicle;
if (!vehiclesCache.TryGetValue(parentEntity, out vehicle)) {
var vehicleParent = (parentEntity as BaseVehicleModule)?.Vehicle;
if (vehicleParent == null || !vehiclesCache.TryGetValue(vehicleParent, out vehicle)) {
return null;
}
}
if (AreFriends(vehicle.playerID, friend.userID)) {
return null;
}
if (HasAdminPermission(friend)) {
return null;
}
SendCantUseMessage(friend, vehicle);
return False;
}
#endregion Loot
#region Claime
private void OnEntitySpawned(MotorRowboat motorRowboat) {
NextFrame(() => {
var player = motorRowboat?.creatorEntity as BasePlayer;
if (player == null || !player.userID.IsSteamId() || !motorRowboat.OnlyOwnerAccessible()) return;
TryClaimVehicle(player, motorRowboat, motorRowboat is RHIB ? NormalVehicleType.RHIB : NormalVehicleType.Rowboat);
}
);
}
private void OnEntitySpawned(MiniCopter miniCopter) {
NextFrame(() => {
var player = miniCopter?.creatorEntity as BasePlayer;
if (player == null || !player.userID.IsSteamId() || !miniCopter.OnlyOwnerAccessible()) return;
TryClaimVehicle(player, miniCopter, miniCopter is ScrapTransportHelicopter ? NormalVehicleType.TransportHelicopter : NormalVehicleType.MiniCopter);
}
);
}
private void OnRidableAnimalClaimed(BaseRidableAnimal baseRidableAnimal, BasePlayer player) {
if (player == null || !player.userID.IsSteamId()) return;
TryClaimVehicle(player, baseRidableAnimal, NormalVehicleType.RidableHorse);
}
#endregion Claime
#region Decay
private void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitInfo) {
if (entity == null | hitInfo?.damageTypes == null) return;
if (hitInfo.damageTypes.Has(Rust.DamageType.Decay)) {
if (!vehiclesCache.ContainsKey(entity)) {
var vehicle = (entity as BaseVehicleModule)?.Vehicle;
if (vehicle == null || !vehiclesCache.ContainsKey(vehicle)) {
return;
}
}
hitInfo.damageTypes.Scale(Rust.DamageType.Decay, 0);
}
}
#endregion Decay
#region Damage
// ScrapTransportHelicopter / ModularCar / TrainEngine / MagnetCrane
private object OnEntityEnter(TriggerHurtNotChild triggerHurtNotChild, BasePlayer player) {
if (triggerHurtNotChild == null || triggerHurtNotChild.SourceEntity == null || player == null) return null;
var sourceEntity = triggerHurtNotChild.SourceEntity;
if (vehiclesCache.ContainsKey(sourceEntity)) {
var baseVehicle = sourceEntity as BaseVehicle;
if (baseVehicle != null && player.userID.IsSteamId()) {
if (baseVehicle is TrainEngine) {
var transform = triggerHurtNotChild.transform;
MoveToPosition(player, transform.position + (UnityEngine.Random.value >= 0.5f ? -transform.right : transform.right) * 2.5f);
return False;
}
Vector3 pos;
if (GetDismountPosition(baseVehicle, player, out pos)) {
MoveToPosition(player, pos);
}
}
//triggerHurtNotChild.enabled = false;
return False;
}
return null;
}
// HotAirBalloon
private object OnEntityEnter(TriggerHurt triggerHurt, BasePlayer player) {
if (triggerHurt == null || player == null) return null;
var sourceEntity = triggerHurt.gameObject.ToBaseEntity();
if (sourceEntity == null) return null;
if (vehiclesCache.ContainsKey(sourceEntity)) {
if (player.userID.IsSteamId()) {
MoveToPosition(player, sourceEntity.CenterPoint() + Vector3.down);
}
//triggerHurt.enabled = false;
return False;
}
return null;
}
#endregion Damage
#region Destroy
private void OnEntityDeath(BaseCombatEntity entity, HitInfo info) => CheckEntity(entity, true);
private void OnEntityKill(BaseCombatEntity entity) => CheckEntity(entity);
#endregion Destroy
#endregion Oxide Hooks
#region Methods
#region Message
private void SendCantUseMessage(BasePlayer friend, Vehicle vehicle) {
var baseVehicleS = GetBaseVehicleS(vehicle.vehicleType);
if (baseVehicleS != null) {
var player = RustCore.FindPlayerById(vehicle.playerID);
var playerName = player?.displayName ?? ServerMgr.Instance.persistance.GetPlayerName(vehicle.playerID) ?? "Unknown";
Print(friend, Lang("CantUse", friend.UserIDString, baseVehicleS.displayName, $"<color=#{(player != null && player.IsConnected ? "69D214" : "FF6347")}>{playerName}</color>"));
}
}
#endregion Message
#region CheckEntity
private void CheckEntity(BaseCombatEntity entity, bool isCrash = false) {
if (entity == null) return;
Vehicle vehicle;
if (!vehiclesCache.TryGetValue(entity, out vehicle)) return;
vehiclesCache.Remove(entity);
vehicle.OnDeath();
var baseVehicleS = GetBaseVehicleS(vehicle.vehicleType);
RefundVehicleItems(vehicle, entity, isCrash : isCrash, baseVehicleS : baseVehicleS);
if (isCrash && baseVehicleS.removeLicenseOnceCrash) {
RemoveVehicleLicense(vehicle.playerID, vehicle.vehicleType);
}
}
#endregion CheckEntity
#region CheckVehicles
private void CheckVehicles() {
var currentTimestamp = TimeEx.currentTimestamp;
foreach (var entry in vehiclesCache.ToArray()) {
if (entry.Key == null || entry.Key.IsDestroyed) continue;
if (VehicleIsActive(entry.Key, entry.Value, currentTimestamp)) continue;
if (VehicleAnyMounted(entry.Key)) continue;
entry.Key.Kill(BaseNetworkable.DestroyMode.Gib);
}
}
private bool VehicleIsActive(BaseEntity entity, Vehicle vehicle, double currentTimestamp) {
var baseVehicleS = GetBaseVehicleS(vehicle.vehicleType);
if (baseVehicleS.wipeTime <= 0) return true;
if (baseVehicleS.excludeCupboard && entity.GetBuildingPrivilege() != null) return true;
return currentTimestamp - vehicle.lastDismount < baseVehicleS.wipeTime;
}
#endregion CheckVehicles
#region Refund
private static bool CanRefundFuel(BaseVehicleS baseVehicleS, bool isCrash, bool isUnload) {
if (isUnload) return true;
var fuelVehicleS = baseVehicleS as IFuelVehicle;
return fuelVehicleS != null && (isCrash ? fuelVehicleS.refundFuelOnCrash : fuelVehicleS.refundFuelOnKill);
}
private static bool CanRefundInventory(BaseVehicleS baseVehicleS, bool isCrash, bool isUnload) {
if (isUnload) return true;
var inventoryVehicleS = baseVehicleS as IInventoryVehicle;
return inventoryVehicleS != null && (isCrash ? inventoryVehicleS.refundInventoryOnCrash : inventoryVehicleS.refundInventoryOnKill);
}
private static void ModularCarRefundState(BaseVehicleS baseVehicleS, bool isCrash, bool isUnload, out bool refundFuel, out bool refundInventory, out bool refundEngine, out bool refundModule) {
if (isUnload) {
refundFuel = refundInventory = refundEngine = refundModule = true;
return;
}
var modularVehicleS = baseVehicleS as ModularVehicleS;
if (modularVehicleS == null) {
refundFuel = refundInventory = refundEngine = refundModule = false;
return;
}
refundFuel = isCrash ? modularVehicleS.refundFuelOnCrash : modularVehicleS.refundFuelOnKill;
refundInventory = isCrash ? modularVehicleS.refundInventoryOnCrash : modularVehicleS.refundInventoryOnKill;
refundEngine = isCrash ? modularVehicleS.refundEngineOnCrash : modularVehicleS.refundEngineOnKill;
refundModule = isCrash ? modularVehicleS.refundModuleOnCrash : modularVehicleS.refundModuleOnKill;
}
private void RefundVehicleItems(Vehicle vehicle, BaseEntity entity, BaseVehicleS baseVehicleS = null, bool isCrash = false, bool isUnload = false) {
if (entity == null) entity = vehicle.entity;
if (entity == null) return;
if (baseVehicleS == null) baseVehicleS = GetBaseVehicleS(vehicle.vehicleType);
if (baseVehicleS == null) return;
NormalVehicleType normalVehicleType;
var collect = Pool.GetList<Item>();
if (Enum.TryParse(vehicle.vehicleType, out normalVehicleType)) {
ItemContainer inventory = null;
EntityFuelSystem fuelSystem = null;
switch (normalVehicleType) {
case NormalVehicleType.Sedan : case NormalVehicleType.Chinook : return;
case NormalVehicleType.MiniCopter : case NormalVehicleType.TransportHelicopter : {
if (CanRefundFuel(baseVehicleS, isCrash, isUnload)) {
fuelSystem = (entity as MiniCopter)?.GetFuelSystem();
}
}
break;
case NormalVehicleType.HotAirBalloon : {
var hotAirBalloon = entity as HotAirBalloon;
if (CanRefundFuel(baseVehicleS, isCrash, isUnload)) {
fuelSystem = hotAirBalloon?.fuelSystem;
}
if (CanRefundInventory(baseVehicleS, isCrash, isUnload)) {
inventory = (hotAirBalloon?.storageUnitInstance.Get(true) as StorageContainer)?.inventory;
}
}
break;
case NormalVehicleType.RHIB : case NormalVehicleType.Rowboat : {
var motorRowboat = entity as MotorRowboat;
if (CanRefundFuel(baseVehicleS, isCrash, isUnload)) {
fuelSystem = motorRowboat?.GetFuelSystem();
}
if (CanRefundInventory(baseVehicleS, isCrash, isUnload)) {
inventory = (motorRowboat?.storageUnitInstance.Get(true) as StorageContainer)?.inventory;
}
}
break;
case NormalVehicleType.RidableHorse : {
if (CanRefundInventory(baseVehicleS, isCrash, isUnload)) {
inventory = (entity as RidableHorse)?.inventory;
}
}
break;
case NormalVehicleType.WorkCart : {
if (CanRefundFuel(baseVehicleS, isCrash, isUnload)) {
fuelSystem = (entity as TrainEngine)?.GetFuelSystem();
}
}
break;
case NormalVehicleType.MagnetCrane : {
if (CanRefundFuel(baseVehicleS, isCrash, isUnload)) {
fuelSystem = (entity as BaseCrane)?.GetFuelSystem();
}
}
break;
case NormalVehicleType.SubmarineSolo : case NormalVehicleType.SubmarineDuo : {
var baseSubmarine = entity as BaseSubmarine;
if (CanRefundFuel(baseVehicleS, isCrash, isUnload)) {
fuelSystem = baseSubmarine?.GetFuelSystem();
}
if (CanRefundInventory(baseVehicleS, isCrash, isUnload)) {
inventory = baseSubmarine?.GetTorpedoContainer()?.inventory;
}
}
break;
case NormalVehicleType.Snowmobile : case NormalVehicleType.TomahaSnowmobile : {
var snowmobile = entity as Snowmobile;
if (CanRefundFuel(baseVehicleS, isCrash, isUnload)) {
fuelSystem = snowmobile?.GetFuelSystem();
}
if (CanRefundInventory(baseVehicleS, isCrash, isUnload)) {
inventory = snowmobile?.GetItemContainer()?.inventory;
}
}
break;
default : return;
}
var fuelContainer = fuelSystem?.GetFuelContainer()?.inventory;
if (fuelContainer != null) {
collect.AddRange(fuelContainer.itemList);
}
if (inventory != null) {
collect.AddRange(inventory.itemList);
}
}
else {
var modularCar = entity as ModularCar;
if (modularCar == null) return;
bool refundFuel, refundInventory, refundEngine, refundModule;
ModularCarRefundState(baseVehicleS, isCrash, isUnload, out refundFuel, out refundInventory, out refundEngine, out refundModule);
foreach (var moduleEntity in modularCar.AttachedModuleEntities) {
if (refundEngine) {
var moduleEngine = moduleEntity as VehicleModuleEngine;
if (moduleEngine != null) {
var engineContainer = moduleEngine.GetContainer()?.inventory;
if (engineContainer != null) collect.AddRange(engineContainer.itemList);
continue;
}
}
if (refundInventory) {
var moduleStorage = moduleEntity as VehicleModuleStorage;
if (moduleStorage != null && !(moduleEntity is VehicleModuleEngine)) {
var storageContainer = moduleStorage.GetContainer()?.inventory;
if (storageContainer != null) collect.AddRange(storageContainer.itemList);
}
}
}
if (refundFuel) {
var fuelContainer = modularCar.GetFuelSystem()?.GetFuelContainer()?.inventory;
if (fuelContainer != null) collect.AddRange(fuelContainer.itemList);
}
if (refundModule) {
var moduleContainer = modularCar.Inventory?.ModuleContainer;
if (moduleContainer != null) collect.AddRange(moduleContainer.itemList);
}
//var chassisContainer = modularCar.Inventory?.ChassisContainer;
//if (chassisContainer != null)
//{
// collect.AddRange(chassisContainer.itemList);
//}
}
if (collect.Count > 0) {
var player = RustCore.FindPlayerById(vehicle.playerID);
if (player == null) {
DropItemContainer(entity, vehicle.playerID, collect);
}
else {
for (var i = collect.Count - 1; i >= 0; i--) {
var item = collect[i];
player.GiveItem(item);
}
if (player.IsConnected) {
Print(player, Lang("RefundedVehicleItems", player.UserIDString, baseVehicleS.displayName));
}
}
}
Pool.FreeList(ref collect);
}
private static void DropItemContainer(BaseEntity entity, ulong playerID, List<Item> collect) {
var droppedItemContainer = GameManager.server.CreateEntity(PREFAB_ITEM_DROP, entity.GetDropPosition(), entity.transform.rotation) as DroppedItemContainer;
droppedItemContainer.inventory = new ItemContainer();
droppedItemContainer.inventory.ServerInitialize(null, Mathf.Min(collect.Count, droppedItemContainer.maxItemCount));
droppedItemContainer.inventory.GiveUID();
droppedItemContainer.inventory.entityOwner = droppedItemContainer;
droppedItemContainer.inventory.SetFlag(ItemContainer.Flag.NoItemInput, true);
for (var i = collect.Count - 1; i >= 0; i--) {
var item = collect[i];
if (!item.MoveToContainer(droppedItemContainer.inventory)) {
item.DropAndTossUpwards(droppedItemContainer.transform.position);
}
}
droppedItemContainer.OwnerID = playerID;
droppedItemContainer.Spawn();
}
#endregion Refund
#region GiveFuel
private static void TryGiveFuel(BaseEntity entity, string vehicleType, IFuelVehicle iFuelVehicle) {
if (iFuelVehicle == null || iFuelVehicle.spawnFuelAmount <= 0) return;
ItemContainer fuelContainer;
NormalVehicleType normalVehicleType;
if (Enum.TryParse(vehicleType, out normalVehicleType)) {
EntityFuelSystem fuelSystem = null;
switch (normalVehicleType) {
case NormalVehicleType.Sedan : case NormalVehicleType.Chinook : case NormalVehicleType.RidableHorse : return;
case NormalVehicleType.MiniCopter : case NormalVehicleType.TransportHelicopter : fuelSystem = (entity as MiniCopter)?.GetFuelSystem();
break;
case NormalVehicleType.HotAirBalloon : fuelSystem = (entity as HotAirBalloon)?.fuelSystem;
break;
case NormalVehicleType.RHIB : case NormalVehicleType.Rowboat : fuelSystem = (entity as MotorRowboat)?.GetFuelSystem();
break;
case NormalVehicleType.WorkCart : fuelSystem = (entity as TrainEngine)?.GetFuelSystem();
break;
case NormalVehicleType.MagnetCrane : fuelSystem = (entity as BaseCrane)?.GetFuelSystem();
break;
case NormalVehicleType.SubmarineSolo : case NormalVehicleType.SubmarineDuo : fuelSystem = (entity as BaseSubmarine)?.GetFuelSystem();
break;
case NormalVehicleType.Snowmobile : case NormalVehicleType.TomahaSnowmobile : fuelSystem = (entity as Snowmobile)?.GetFuelSystem();
break;
default : return;
}
fuelContainer = fuelSystem?.GetFuelContainer()?.inventory;
}
else {
fuelContainer = (entity as ModularCar)?.GetFuelSystem()?.GetFuelContainer()?.inventory;
}
if (fuelContainer == null /*|| fuelContainer.FindItemByItemID(ITEMID_FUEL) != null*/
) return;
var fuel = ItemManager.CreateByItemID(ITEMID_FUEL, iFuelVehicle.spawnFuelAmount);
if (!fuel.MoveToContainer(fuelContainer)) {
fuel.Remove();
}
}
#endregion GiveFuel
#region VehicleModules
private void AttacheVehicleModules(ModularCar modularCar, ModularVehicleS modularVehicleS, string vehicleType) {
foreach (var moduleItem in modularVehicleS.CreateModuleItems()) {
if (!modularCar.TryAddModule(moduleItem)) {
PrintError($"Module item '{moduleItem.info.shortname}' in '{vehicleType}' cannot be attached to the vehicle");
moduleItem.Remove();
}
}
}
private void AddItemsToVehicleEngine(ModularCar modularCar, ModularVehicleS modularVehicleS, string vehicleType) {
if (modularCar == null || modularCar.IsDestroyed) return;
foreach (var moduleEntity in modularCar.AttachedModuleEntities) {
var vehicleModuleEngine = moduleEntity as VehicleModuleEngine;
if (vehicleModuleEngine != null) {
var engineInventory = vehicleModuleEngine.GetContainer()?.inventory;
if (engineInventory != null) {
foreach (var engineItem in modularVehicleS.CreateEngineItems()) {
bool moved = false;
for (int i = 0; i < engineInventory.capacity; i++) {
if (engineItem.MoveToContainer(engineInventory, i, false)) {
moved = true;
break;
}
}
if (!moved) {
PrintError($"Engine item '{engineItem.info.shortname}' in '{vehicleType}' cannot be move to the vehicle engine inventory");
engineItem.Remove();
engineItem.DoRemove();
}
}
}
}
}
}
#endregion VehicleModules
#region DropInventory
private static bool CanDropInventory(BaseVehicleS baseVehicleS) {
var inventoryVehicle = baseVehicleS as IInventoryVehicle;
return inventoryVehicle != null && inventoryVehicle.dropInventoryOnRecall;
}
private void DropVehicleInventoryItems(BasePlayer player, string vehicleType, BaseEntity entity, BaseVehicleS baseVehicleS) {
DroppedItemContainer droppedItemContainer = null;
NormalVehicleType normalVehicleType;
if (Enum.TryParse(vehicleType, out normalVehicleType)) {
ItemContainer itemContainer = null;
switch (normalVehicleType) {
case NormalVehicleType.Sedan : case NormalVehicleType.MiniCopter : case NormalVehicleType.TransportHelicopter : case NormalVehicleType.Chinook : case NormalVehicleType.WorkCart : case NormalVehicleType.MagnetCrane : return;
case NormalVehicleType.RHIB : case NormalVehicleType.Rowboat : itemContainer = ((entity as MotorRowboat)?.storageUnitInstance.Get(true) as StorageContainer)?.inventory;
break;
case NormalVehicleType.HotAirBalloon : itemContainer = ((entity as HotAirBalloon)?.storageUnitInstance.Get(true) as StorageContainer)?.inventory;
break;
case NormalVehicleType.RidableHorse : itemContainer = (entity as RidableHorse)?.inventory;
break;
case NormalVehicleType.SubmarineSolo : case NormalVehicleType.SubmarineDuo : itemContainer = (entity as BaseSubmarine)?.GetTorpedoContainer()?.inventory;
break;
case NormalVehicleType.Snowmobile : case NormalVehicleType.TomahaSnowmobile : itemContainer = (entity as Snowmobile)?.GetItemContainer()?.inventory;
break;
}
if (itemContainer != null) {
droppedItemContainer = itemContainer.Drop(PREFAB_ITEM_DROP, entity.GetDropPosition(), entity.transform.rotation);
}
}
else {
var modularCar = entity as ModularCar;
if (modularCar == null) return;
foreach (var moduleEntity in modularCar.AttachedModuleEntities) {
if (moduleEntity is VehicleModuleEngine) continue;
var moduleStorage = moduleEntity as VehicleModuleStorage;
if (moduleStorage != null) {
droppedItemContainer = moduleStorage.GetContainer()?.inventory?.Drop(PREFAB_ITEM_DROP, entity.GetDropPosition(), entity.transform.rotation);
}
}
}
if (droppedItemContainer != null) {
Print(player, Lang("VehicleInventoryDropped", player.UserIDString, baseVehicleS.displayName));
}
}
#endregion DropInventory
#region TryPay
private bool TryPay(BasePlayer player, Dictionary<string, PriceInfo> prices, out string missingResources) {
if (permission.UserHasPermission(player.UserIDString, PERMISSION_BYPASS_COST)) {
missingResources = null;
return true;
}
if (!CanPay(player, prices, out missingResources)) {
return false;
}
var collect = Pool.GetList<Item>();
foreach (var entry in prices) {
if (entry.Value.amount <= 0) continue;
var itemDefinition = ItemManager.FindItemDefinition(entry.Key);
if (itemDefinition != null) {
player.inventory.Take(collect, itemDefinition.itemid, entry.Value.amount);
player.Command("note.inv", itemDefinition.itemid, -entry.Value.amount);
continue;
}
switch (entry.Key.ToLower()) {
case "economics" : Economics?.Call("Withdraw", player.userID, (double)entry.Value.amount);
continue;
case "serverrewards" : ServerRewards?.Call("TakePoints", player.userID, entry.Value.amount);
continue;
}
}
foreach (var item in collect) {
item.Remove();
}
Pool.FreeList(ref collect);
missingResources = null;
return true;
}
private readonly Hash<string, int> missingDictionary = new Hash<string, int>();
private bool CanPay(BasePlayer player, Dictionary<string, PriceInfo> prices, out string missingResources) {
missingDictionary.Clear();
var language = RustTranslationAPI != null ? lang.GetLanguage(player.UserIDString) : null;
foreach (var entry in prices) {
if (entry.Value.amount <= 0) continue;
int missingAmount;
var itemDefinition = ItemManager.FindItemDefinition(entry.Key);
if (itemDefinition != null) missingAmount = entry.Value.amount - player.inventory.GetAmount(itemDefinition.itemid);
else missingAmount = CheckBalance(entry.Key, entry.Value.amount, player.userID);
if (missingAmount <= 0) continue;
var displayName = GetItemDisplayName(language, entry.Key, entry.Value.displayName);
missingDictionary[displayName] += missingAmount;
}
if (missingDictionary.Count > 0) {
StringBuilder stringBuilder = Pool.Get<StringBuilder>();
foreach (var entry in missingDictionary) {
stringBuilder.AppendLine($"* {Lang("PriceFormat", player.UserIDString, entry.Key, entry.Value)}");
}
missingResources = stringBuilder.ToString();
stringBuilder.Clear();
Pool.Free(ref stringBuilder);
return false;
}
missingResources = null;
return true;
}
private int CheckBalance(string key, int price, ulong playerID) {
switch (key.ToLower()) {
case "economics" : var balance = Economics?.Call("Balance", playerID);
if (balance is double) {
var n = price - (double)balance;
return n <= 0 ? 0 : (int)Math.Ceiling(n);
}
return price;
case "serverrewards" : var points = ServerRewards?.Call("CheckPoints", playerID);
if (points is int) {
var n = price - (int)points;
return n <= 0 ? 0 : n;
}
return price;
default : PrintError($"Unknown Currency Type '{key}'");
return price;
}
}
#endregion TryPay
#region AreFriends
private bool AreFriends(ulong playerID, ulong friendID) {
if (playerID == friendID) return true;
if (configData.globalS.useTeams && SameTeam(playerID, friendID)) return true;
if (configData.globalS.useFriends && HasFriend(playerID, friendID)) return true;
if (configData.globalS.useClans && SameClan(playerID, friendID)) return true;
return false;
}
private static bool SameTeam(ulong playerID, ulong friendID) {
if (!RelationshipManager.TeamsEnabled()) return false;
var playerTeam = RelationshipManager.ServerInstance.FindPlayersTeam(playerID);
if (playerTeam == null) return false;
var friendTeam = RelationshipManager.ServerInstance.FindPlayersTeam(friendID);
if (friendTeam == null) return false;
return playerTeam == friendTeam;
}
private bool HasFriend(ulong playerID, ulong friendID) {
if (Friends == null) return false;
return (bool)Friends.Call("HasFriend", playerID, friendID);
}
private bool SameClan(ulong playerID, ulong friendID) {
if (Clans == null) return false;
//Clans
var isMember = Clans.Call("IsClanMember", playerID.ToString(), friendID.ToString());
if (isMember != null) return (bool)isMember;
//Rust:IO Clans
var playerClan = Clans.Call("GetClanOf", playerID);
if (playerClan == null) return false;
var friendClan = Clans.Call("GetClanOf", friendID);
if (friendClan == null) return false;
return (string)playerClan == (string)friendClan;
}
#endregion AreFriends
#region IsPlayerBlocked
private bool IsPlayerBlocked(BasePlayer player) {
if (NoEscape == null) return false;
if (configData.globalS.useRaidBlocker && IsRaidBlocked(player.UserIDString)) {
Print(player, Lang("RaidBlocked", player.UserIDString));
return true;
}
if (configData.globalS.useCombatBlocker && IsCombatBlocked(player.UserIDString)) {
Print(player, Lang("CombatBlocked", player.UserIDString));
return true;
}
return false;
}
private bool IsRaidBlocked(string playerID) => (bool)NoEscape.Call("IsRaidBlocked", playerID);
private bool IsCombatBlocked(string playerID) => (bool)NoEscape.Call("IsCombatBlocked", playerID);
#endregion IsPlayerBlocked
#region GetBaseVehicleS
private BaseVehicleS GetBaseVehicleS(string vehicleName) {
BaseVehicleS baseVehicleS;
return allBaseVehicleSettings.TryGetValue(vehicleName, out baseVehicleS) ? baseVehicleS : null;
}
private BaseVehicleS GetBaseVehicleS(NormalVehicleType normalVehicleType) {
switch (normalVehicleType) {
case NormalVehicleType.Rowboat : return configData.normalVehicleS.rowboatS;
case NormalVehicleType.RHIB : return configData.normalVehicleS.rhibS;
case NormalVehicleType.Sedan : return configData.normalVehicleS.sedanS;
case NormalVehicleType.HotAirBalloon : return configData.normalVehicleS.hotAirBalloonS;
case NormalVehicleType.MiniCopter : return configData.normalVehicleS.miniCopterS;
case NormalVehicleType.TransportHelicopter : return configData.normalVehicleS.transportHelicopterS;
case NormalVehicleType.Chinook : return configData.normalVehicleS.chinookS;
case NormalVehicleType.RidableHorse : return configData.normalVehicleS.ridableHorseS;
case NormalVehicleType.WorkCart : return configData.normalVehicleS.workCartS;
case NormalVehicleType.MagnetCrane : return configData.normalVehicleS.magnetCraneS;
case NormalVehicleType.SubmarineSolo : return configData.normalVehicleS.submarineSoloS;
case NormalVehicleType.SubmarineDuo : return configData.normalVehicleS.submarineDuoS;
case NormalVehicleType.Snowmobile : return configData.normalVehicleS.snowmobileS;
case NormalVehicleType.TomahaSnowmobile : return configData.normalVehicleS.tomahaSnowmobileS;
default : return null;
}
}
#endregion GetBaseVehicleS
#region HasVehiclePermission
private bool CanViewVehicleInfo(BasePlayer player, string vehicleType, BaseVehicleS baseVehicleS) {
if (baseVehicleS.purchasable && baseVehicleS.commands.Count > 0) {
return HasVehiclePermission(player, vehicleType, baseVehicleS);
}
return false;
}
private bool HasVehiclePermission(BasePlayer player, string vehicleType, BaseVehicleS baseVehicleS = null) {
if (baseVehicleS == null) baseVehicleS = GetBaseVehicleS(vehicleType);
if (!baseVehicleS.usePermission || string.IsNullOrEmpty(baseVehicleS.permission)) return true;
return permission.UserHasPermission(player.UserIDString, PERMISSION_ALL) || permission.UserHasPermission(player.UserIDString, baseVehicleS.permission);
}
#endregion HasVehiclePermission
#region GetCooldown
private double GetSpawnCooldown(BasePlayer player, BaseVehicleS baseVehicleS) {
double cooldown = baseVehicleS.spawnCooldown;
foreach (var entry in baseVehicleS.cooldownPermissions) {
if (cooldown > entry.Value.spawnCooldown && permission.UserHasPermission(player.UserIDString, entry.Key)) {
cooldown = entry.Value.spawnCooldown;
}
}
return cooldown;
}
private double GetRecallCooldown(BasePlayer player, BaseVehicleS baseVehicleS) {
double cooldown = baseVehicleS.recallCooldown;
foreach (var entry in baseVehicleS.cooldownPermissions) {
if (cooldown > entry.Value.recallCooldown && permission.UserHasPermission(player.UserIDString, entry.Key)) {
cooldown = entry.Value.recallCooldown;
}
}
return cooldown;
}
#endregion GetCooldown
#region ClaimVehicle
private bool TryClaimVehicle(BasePlayer player, BaseEntity entity, NormalVehicleType normalVehicleType) {
return TryClaimVehicle(player, entity, normalVehicleType.ToString());
}
private bool TryClaimVehicle(BasePlayer player, BaseEntity entity, string vehicleType) {
Vehicle vehicle;
if (!st
// ... [Code preview truncated due to length. Full source in attached file] ...