Иконка ресурса

FREE SpawnModularCar : 5.2.2 5.2.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Rust;
using Rust.Modular;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using System.Text;
namespace Oxide.Plugins {
    [Info("Spawn Modular Car", "WhiteThunder", "5.2.2")]
    [Description("Allows players to spawn modular cars.")]
    internal class SpawnModularCar : CovalencePlugin {
#region Fields
        [PluginReference]
        private Plugin VehicleDeployedLocks;
        private static SpawnModularCar _pluginInstance;
        private static Configuration _pluginConfig;
        private PluginData _pluginData;
        private CommonPresets _commonPresets;
        private const string DefaultPresetName = "default";
        private const int PresetMaxLength = 30;
        private const string PermissionSpawnSockets2 = "spawnmodularcar.spawn.2";
        private const string PermissionSpawnSockets3 = "spawnmodularcar.spawn.3";
        private const string PermissionSpawnSockets4 = "spawnmodularcar.spawn.4";
        private const string PermissionEnginePartsTier1 = "spawnmodularcar.engineparts.tier1";
        private const string PermissionEnginePartsTier2 = "spawnmodularcar.engineparts.tier2";
        private const string PermissionEnginePartsTier3 = "spawnmodularcar.engineparts.tier3";
        private const string PermissionFix = "spawnmodularcar.fix";
        private const string PermissionFetch = "spawnmodularcar.fetch";
        private const string PermissionDespawn = "spawnmodularcar.despawn";
        private const string PermissionAutoFuel = "spawnmodularcar.autofuel";
        private const string PermissionAutoCodeLock = "spawnmodularcar.autocodelock";
        private const string PermissionAutoKeyLock = "spawnmodularcar.autokeylock";
        private const string PermissionAutoStartEngine = "spawnmodularcar.autostartengine";
        private const string PermissionAutoFillTankers = "spawnmodularcar.autofilltankers";
        private const string PermissionGiveCar = "spawnmodularcar.givecar";
        private const string PermissionPresets = "spawnmodularcar.presets";
        private const string PermissionPresetLoad = "spawnmodularcar.presets.load";
        private const string PermissionCommonPresets = "spawnmodularcar.presets.common";
        private const string PermissionManageCommonPresets = "spawnmodularcar.presets.common.manage";
        private const string PrefabSockets2 = "assets/content/vehicles/modularcar/2module_car_spawned.entity.prefab";
        private const string PrefabSockets3 = "assets/content/vehicles/modularcar/3module_car_spawned.entity.prefab";
        private const string PrefabSockets4 = "assets/content/vehicles/modularcar/4module_car_spawned.entity.prefab";
        private const string ItemDropPrefab = "assets/prefabs/misc/item drop/item_drop.prefab";
        private const string RepairEffectPrefab = "assets/bundled/prefabs/fx/build/promote_toptier.prefab";
        private const string TankerFilledEffectPrefab = "assets/prefabs/food/water jug/effects/water-jug-fill-container.prefab";
        // These layers are used to preventing spawning inside walls or players.private const int BoxcastLayers = Layers.Mask.Default
        + Layers.Mask.Deployed + Layers.Mask.Player_Server + Layers.Mask.AI + Layers.Mask.Vehicle_Detailed + Layers.Mask.Vehicle_World + Layers.Mask.World + Layers.Mask.Construction + Layers.Mask.Tree;
        // These layers are used to find a surface to spawn on.private const int RaycastLayers = Layers.Mask.Default
        + Layers.Mask.Terrain + Layers.World + Layers.Mask.Construction;
        private static readonly Vector3 ShortCarExtents = new Vector3(1, 1.1f, 1.5f);
        private static readonly Vector3 MediumCarExtents = new Vector3(1, 1.1f, 2.3f);
        private static readonly Vector3 LongCarExtents = new Vector3(1, 1.1f, 3);
        private static readonly Vector3 ShortCarFrontLeft = new Vector3(ShortCarExtents.x, 0, ShortCarExtents.z);
        private static readonly Vector3 ShortCarFrontRight = new Vector3(-ShortCarExtents.x, 0, ShortCarExtents.z);
        private static readonly Vector3 ShortCarBackLeft = new Vector3(ShortCarExtents.x, 0, -ShortCarExtents.z);
        private static readonly Vector3 ShortCarBackRight = new Vector3(-ShortCarExtents.x, 0, -ShortCarExtents.z);
        private static readonly Vector3 MediumCarFrontLeft = new Vector3(MediumCarExtents.x, 0, MediumCarExtents.z);
        private static readonly Vector3 MediumCarFrontRight = new Vector3(-MediumCarExtents.x, 0, MediumCarExtents.z);
        private static readonly Vector3 MediumCarBackLeft = new Vector3(MediumCarExtents.x, 0, -MediumCarExtents.z);
        private static readonly Vector3 MediumCarBackRight = new Vector3(-MediumCarExtents.x, 0, -MediumCarExtents.z);
        private static readonly Vector3 LongCarFrontLeft = new Vector3(LongCarExtents.x, 0, LongCarExtents.z);
        private static readonly Vector3 LongCarFrontRight = new Vector3(-LongCarExtents.x, 0, LongCarExtents.z);
        private static readonly Vector3 LongCarBackLeft = new Vector3(LongCarExtents.x, 0, -LongCarExtents.z);
        private static readonly Vector3 LongCarBackRight = new Vector3(-LongCarExtents.x, 0, -LongCarExtents.z);
        private static readonly float ForwardRaycastDistance = 1.5f + ShortCarExtents.x;
        private const float DownwardRaycastDistance = 4;
        private readonly RaycastHit[] _raycastBuffer = new RaycastHit[1];
        private readonly Dictionary<string, PlayerConfig> _playerConfigsMap = new Dictionary<string, PlayerConfig>();
#endregion
#region Hooks
        private void Init() {
            _pluginInstance = this;
            _pluginData = PluginData.LoadData();
            _commonPresets = CommonPresets.LoadData(_pluginData);
            MigrateConfig();
            permission.RegisterPermission(PermissionSpawnSockets2, this);
            permission.RegisterPermission(PermissionSpawnSockets3, this);
            permission.RegisterPermission(PermissionSpawnSockets4, this);
            permission.RegisterPermission(PermissionEnginePartsTier1, this);
            permission.RegisterPermission(PermissionEnginePartsTier2, this);
            permission.RegisterPermission(PermissionEnginePartsTier3, this);
            permission.RegisterPermission(PermissionFix, this);
            permission.RegisterPermission(PermissionFetch, this);
            permission.RegisterPermission(PermissionDespawn, this);
            permission.RegisterPermission(PermissionAutoFuel, this);
            permission.RegisterPermission(PermissionAutoCodeLock, this);
            permission.RegisterPermission(PermissionAutoKeyLock, this);
            permission.RegisterPermission(PermissionAutoStartEngine, this);
            permission.RegisterPermission(PermissionAutoFillTankers, this);
            permission.RegisterPermission(PermissionGiveCar, this);
            permission.RegisterPermission(PermissionPresets, this);
            permission.RegisterPermission(PermissionPresetLoad, this);
            permission.RegisterPermission(PermissionCommonPresets, this);
            permission.RegisterPermission(PermissionManageCommonPresets, this);
        }
        private void Unload() {
            _pluginInstance = null;
            _pluginConfig = null;
        }
        private void OnNewSave(string filename) {
            _pluginData.PlayerCars.Clear();
            _pluginData.Cooldowns.ClearAll();
            _pluginData.SaveData();
        }
        private void OnEntityKill(ModularCar car) {
            if (!IsPlayerCar(car)) return;
            string userId = _pluginData.PlayerCars.FirstOrDefault(x => x.Value == car.net.ID.Value).Key;
            BasePlayer player = BasePlayer.Find(userId);
            if (player != null) ChatMessage(player, "Generic.Info.CarDestroyed");
            _pluginData.UnregisterCar(userId);
        }
        private void OnEngineStarted(ModularCar car, BasePlayer player) {
            if (car == null || car.OwnerID == 0 || !_pluginData.PlayerCars.ContainsValue(car.net.ID.Value) || !permission.UserHasPermission(car.OwnerID.ToString(), PermissionAutoStartEngine)) return;
            if (car.engineController.IsStarting) {
                car.CancelInvoke(car.engineController.FinishStartingEngine);
                car.engineController.FinishStartingEngine();
            }
        }
#endregion
#region API
        private static class ApiParser {
            public static string CodeLockField = "CodeLock";
            public static string KeyLockField = "KeyLock";
            public static string EnginePartsTierField = "EnginePartsTier";
            public static string FreshWaterAmountField = "FreshWaterAmount";
            public static string FuelAmountField = "FuelAmount";
            public static string ModulesField = "Modules";
            public static bool TryParseOptions(Dictionary<string, object> options, out PresetCarOptions presetOptions) {
                var codeLock = BoolOption(options, CodeLockField);
                var keyLock = BoolOption(options, KeyLockField);
                var enginePartsTier = IntOption(options, EnginePartsTierField);
                var freshWaterAmount = IntOption(options, FreshWaterAmountField);
                var fuelAmount = IntOption(options, FuelAmountField);
                var moduleIDs = ParseModulesOption(options);
                presetOptions = null;
                if (moduleIDs == null) {
                    _pluginInstance.LogError($"[API] '{ApiParser.ModulesField}' field is missing or unrecognizable.");
                    return false;
                }
                if (moduleIDs.Length < 2 || moduleIDs.Length > 4) {
                    _pluginInstance.LogError($"[API] Requested a car with {moduleIDs.Length} sockets, but only 2-4 sockets is supported.");
                    return false;
                }
                presetOptions = new PresetCarOptions {
                    CodeLock = codeLock, KeyLock = keyLock, EnginePartsTier = enginePartsTier, FreshWaterAmount = freshWaterAmount, FuelAmount = fuelAmount, NormalizedModuleIDs = moduleIDs
                }
                ;
                return true;
            }
            private static bool BoolOption(Dictionary<string, object> options, string name) {
                object value;
                return options.TryGetValue(name, out value) && value is bool ? (bool)value : false;
            }
            private static int IntOption(Dictionary<string, object> options, string name) {
                object value;
                return options.TryGetValue(name, out value) && value is int ? (int)value : 0;
            }
            public static int[] ParseModulesOption(Dictionary<string, object> options) {
                if (!options.ContainsKey(ModulesField)) return null;
                var moduleArray = options[ModulesField] as object[];
                if (moduleArray == null) return null;
                return _pluginInstance.ValidateModules(moduleArray);
            }
        }
        private ModularCar API_SpawnPreset(Dictionary<string, object> options, BasePlayer player, Vector3 position, Quaternion rotation) {
            PresetCarOptions presetOptions;
            if (!ApiParser.TryParseOptions(options, out presetOptions)) return null;
            if (SpawnWasBlocked(player)) return null;
            if (position == Vector3.zero && player != null) DetermineCarPositionAndRotation(player, presetOptions.Length, out position, out rotation);
            return SpawnCar(presetOptions, position, rotation, player, shouldTrackCar : false);
        }
        private ModularCar API_SpawnNamedPreset(string presetName, BasePlayer player, Vector3 position, Quaternion rotation) {
            var presetOptions = _pluginConfig.FindPreset(presetName)?.Options;
            if (presetOptions == null) {
                LogError($"[API] Server preset '{presetName}' not found.");
                return null;
            }
            if (presetOptions.Length < 2 || presetOptions.Length > 4) {
                LogError($"[API] Requested a car with {presetOptions.Length} sockets, but only 2-4 sockets is supported.");
                return null;
            }
            if (SpawnWasBlocked(player)) return null;
            if (position == Vector3.zero && player != null) DetermineCarPositionAndRotation(player, presetOptions.Length, out position, out rotation);
            return SpawnCar(presetOptions, position, rotation, player, shouldTrackCar : false);
        }
        private ModularCar API_SpawnPresetCar(BasePlayer player, Dictionary<string, object> options, Action<ModularCar> onReady = null) {
            PresetCarOptions presetOptions;
            if (!ApiParser.TryParseOptions(options, out presetOptions)) return null;
            if (SpawnWasBlocked(player)) return null;
            Vector3 spawnPosition;
            Quaternion rotation;
            if (!TryGetIdealCarPositionAndRotation(player, presetOptions.Length, out spawnPosition, out rotation)) {
                spawnPosition = GetFixedCarPosition(player);
                rotation = GetRelativeCarRotation(player);
            }
            var car = SpawnCar(presetOptions, spawnPosition, rotation, player, shouldTrackCar : false);
            if (car != null) {
                // Note: Consumers no longer need to use this callback since this plugin now forces synchronous module registration.onReady?.Invoke(car);
            }
            return car;
        }
#endregion
#region Commands
        [Command("givecar")]
        private void SpawnCarServerCommand(IPlayer player, string cmd, string[] args) {
            if (!player.IsServer && !VerifyPermissionAny(player, PermissionGiveCar)) return;
            if (args.Length < 2) {
                ReplyToPlayer(player, "Command.Give.Error.Syntax");
                return;
            }
            var playerNameOrIdArg = args[0];
            var presetNameArg = args[1];
            var targetPlayer = BasePlayer.Find(playerNameOrIdArg);
            if (targetPlayer == null) {
                ReplyToPlayer(player, "Command.Give.Error.PlayerNotFound", playerNameOrIdArg);
                return;
            }
            var preset = _pluginConfig.FindPreset(presetNameArg);
            if (preset == null) {
                ReplyToPlayer(player, "Generic.Error.PresetNotFound", presetNameArg);
                return;
            }
            var carOptions = preset.Options;
            if (carOptions.Length < 2) {
                ReplyToPlayer(player, "Command.Give.Error.PresetTooFewModules", preset.Name, carOptions.Length);
                return;
            }
            if (carOptions.Length > 4) {
                ReplyToPlayer(player, "Command.Give.Error.PresetTooManyModules", preset.Name, carOptions.Length);
                return;
            }
            Vector3 spawnPosition;
            Quaternion rotation;
            if (!TryGetIdealCarPositionAndRotation(targetPlayer, preset.Options.Length, out spawnPosition, out rotation)) {
                spawnPosition = GetFixedCarPosition(targetPlayer);
                rotation = GetRelativeCarRotation(targetPlayer);
            }
            var car = SpawnCar(carOptions, spawnPosition, rotation, targetPlayer, shouldTrackCar : false);
            if (car != null) {
                ReplyToPlayer(player, "Command.Give.Success", targetPlayer.displayName, preset.Name);
            }
        }
        [Command("mycar")]
        private void MyCarCommand(IPlayer player, string cmd, string[] args) {
            if (player.IsServer) return;
            var basePlayer = player.Object as BasePlayer;
            if (!basePlayer.CanInteract()) return;
            if (args.Length == 0) {
                SubCommand_SpawnCar(player, args);
                return;
            }
            switch (args[0].ToLower()) {
                case "help" : SubCommand_Help(player, args.Skip(1).ToArray());
                return;
                case "list" : SubCommand_ListPresets(player, args.Skip(1).ToArray());
                return;
                case "save" : SubCommand_SavePreset(player, args.Skip(1).ToArray());
                return;
                case "update" : SubCommand_UpdatePreset(player, args.Skip(1).ToArray());
                return;
                case "load" : SubCommand_LoadPreset(player, args.Skip(1).ToArray());
                return;
                case "rename" : SubCommand_RenamePreset(player, args.Skip(1).ToArray());
                return;
                case "delete" : SubCommand_DeletePreset(player, args.Skip(1).ToArray());
                return;
                case "fix" : SubCommand_FixCar(player, args.Skip(1).ToArray());
                return;
                case "fetch" : SubCommand_FetchCar(player, args.Skip(1).ToArray());
                return;
                case "destroy" : SubCommand_DestroyCar(player, args.Skip(1).ToArray());
                return;
                case "autocodelock" : SubCommand_ToggleAutoCodeLock(player, args.Skip(1).ToArray());
                return;
                case "autokeylock" : SubCommand_ToggleAutoKeyLock(player, args.Skip(1).ToArray());
                return;
                case "autofilltankers" : SubCommand_ToggleAutoFillTankers(player, args.Skip(1).ToArray());
                return;
                case "common" : SubCommand_CommonPreset(player, args.Skip(1).ToArray());
                return;
                default : SubCommand_SpawnCar(player, args);
                return;
            }
        }
        private void SubCommand_CommonPreset(IPlayer player, string[] args) {
            if (args.Length == 0) {
                ReplyToPlayer(player, "Command.Common.Error.Syntax");
                return;
            }
            switch (args[0].ToLower()) {
                case "list" : SubCommand_Common_ListPresets(player, args.Skip(1).ToArray());
                return;
                case "load" : SubCommand_Common_LoadPreset(player, args.Skip(1).ToArray());
                return;
                case "save" : SubCommand_Common_SavePreset(player, args.Skip(1).ToArray());
                return;
                case "update" : SubCommand_Common_UpdatePreset(player, args.Skip(1).ToArray());
                return;
                case "rename" : SubCommand_Common_RenamePreset(player, args.Skip(1).ToArray());
                return;
                case "delete" : SubCommand_Common_DeletePreset(player, args.Skip(1).ToArray());
                return;
                default : SubCommand_Common_SpawnCar(player, args);
                return;
            }
        }
        private void SubCommand_Help(IPlayer player, string[] args) {
            ushort maxAllowedSockets = GetPlayerMaxAllowedCarSockets(player.Id);
            if (maxAllowedSockets == 0) {
                ReplyToPlayer(player, "Generic.Error.NoPermission");
                return;
            }
            var canUsePresets = permission.UserHasPermission(player.Id, PermissionPresets);
            var canLoadPresets = permission.UserHasPermission(player.Id, PermissionPresetLoad);
            var sb = new StringBuilder();
            sb.AppendLine(GetMessage(player, "Command.Help"));
            if (canUsePresets) sb.AppendLine(GetMessage(player, "Command.Help.Spawn.Basic.PresetsAllowed"));
            else sb.AppendLine(GetMessage(player, "Command.Help.Spawn.Basic"));
            sb.AppendLine(GetMessage(player, "Command.Help.Spawn.Sockets"));
            if (permission.UserHasPermission(player.Id, PermissionFix)) sb.AppendLine(GetMessage(player, "Command.Help.Fix"));
            if (permission.UserHasPermission(player.Id, PermissionFetch)) sb.AppendLine(GetMessage(player, "Command.Help.Fetch"));
            if (permission.UserHasPermission(player.Id, PermissionDespawn)) sb.AppendLine(GetMessage(player, "Command.Help.Destroy"));
            if (canUsePresets) {
                sb.AppendLine(GetMessage(player, "Command.Help.Section.PersonalPresets"));
                sb.AppendLine(GetMessage(player, "Command.Help.ListPresets"));
                sb.AppendLine(GetMessage(player, "Command.Help.Spawn.Preset"));
                if (canLoadPresets) sb.AppendLine(GetMessage(player, "Command.Help.LoadPreset"));
                sb.AppendLine(GetMessage(player, "Command.Help.SavePreset"));
                sb.AppendLine(GetMessage(player, "Command.Help.UpdatePreset"));
                sb.AppendLine(GetMessage(player, "Command.Help.RenamePreset"));
                sb.AppendLine(GetMessage(player, "Command.Help.DeletePreset"));
            }
            if (permission.UserHasPermission(player.Id, PermissionCommonPresets)) {
                sb.AppendLine(GetMessage(player, "Command.Help.Section.CommonPresets"));
                sb.AppendLine(GetMessage(player, "Command.Help.Common.ListPresets"));
                sb.AppendLine(GetMessage(player, "Command.Help.Common.Spawn"));
                if (canLoadPresets) sb.AppendLine(GetMessage(player, "Command.Help.Common.LoadPreset"));
                if (permission.UserHasPermission(player.Id, PermissionManageCommonPresets)) {
                    sb.AppendLine(GetMessage(player, "Command.Help.Common.SavePreset"));
                    sb.AppendLine(GetMessage(player, "Command.Help.Common.UpdatePreset"));
                    sb.AppendLine(GetMessage(player, "Command.Help.Common.RenamePreset"));
                    sb.AppendLine(GetMessage(player, "Command.Help.Common.DeletePreset"));
                }
            }
            var canCodeLock = VehicleDeployedLocks != null && permission.UserHasPermission(player.Id, PermissionAutoCodeLock);
            var canKeyLock = permission.UserHasPermission(player.Id, PermissionAutoKeyLock);
            var canFillTankers = permission.UserHasPermission(player.Id, PermissionAutoFillTankers);
            if (canCodeLock || canKeyLock || canFillTankers) sb.AppendLine(GetMessage(player, "Command.Help.Section.PersonalSettings"));
            if (canCodeLock) sb.AppendLine(GetMessage(player, "Command.Help.ToggleAutoCodeLock", BooleanToLocalizedString(player, GetPlayerConfig(player).Settings.AutoCodeLock)));
            if (canKeyLock) sb.AppendLine(GetMessage(player, "Command.Help.ToggleAutoKeyLock", BooleanToLocalizedString(player, GetPlayerConfig(player).Settings.AutoKeyLock)));
            if (canFillTankers) sb.AppendLine(GetMessage(player, "Command.Help.ToggleAutoFillTankers", BooleanToLocalizedString(player, GetPlayerConfig(player).Settings.AutoFillTankers)));
            if (permission.UserHasPermission(player.Id, PermissionGiveCar)) {
                sb.AppendLine("Command.Help.Section.OtherCommands");
                sb.AppendLine(GetMessage(player, "Command.Help.Give"));
            }
            player.Reply(sb.ToString());
        }
        private void SubCommand_SpawnCar(IPlayer player, string[] args) {
            ushort maxAllowedSockets = GetPlayerMaxAllowedCarSockets(player.Id);
            if (maxAllowedSockets == 0) {
                ReplyToPlayer(player, "Generic.Error.NoPermission");
                return;
            }
            if (!VerifyHasNoCar(player) || !VerifyOffCooldown(player, CooldownType.Spawn) || !VerifyLocationNotRestricted(player) || !_pluginConfig.CanSpawnBuildingBlocked && !VerifyNotBuildingBlocked(player)) return;
            // Key binds automatically pass the "True" argument.var wasPassedArgument = args.Length > 0 && args[0] != "True";
            if (wasPassedArgument) {
                int desiredSockets;
                if (int.TryParse(args[0], out desiredSockets)) {
                    if (desiredSockets < 2 || desiredSockets > 4) {
                        ReplyToPlayer(player, "Command.Spawn.Error.SocketSyntax");
                        return;
                    }
                    if (desiredSockets > maxAllowedSockets) {
                        ReplyToPlayer(player, "Generic.Error.NoPermission");
                        return;
                    }
                    SpawnRandomCarForPlayer(player, desiredSockets);
                    return;
                }
                if (!VerifyPermissionAny(player, PermissionPresets)) return;
                var presetNameArg = args[0];
                SimplePreset preset;
                if (!VerifyOnlyOneMatchingPreset(player, GetPlayerConfig(player), presetNameArg, out preset)) return;
                SpawnPresetCarForPlayer(player, preset);
            }
            else {
                if (permission.UserHasPermission(player.Id, PermissionPresets)) {
                    var preset = GetPlayerConfig(player).FindPreset(DefaultPresetName);
                    if (preset != null) {
                        SpawnPresetCarForPlayer(player, preset);
                        return;
                    }
                }
                SpawnRandomCarForPlayer(player, maxAllowedSockets);
            }
        }
        private void SubCommand_Common_SpawnCar(IPlayer player, string[] args) {
            ushort maxAllowedSockets = GetPlayerMaxAllowedCarSockets(player.Id);
            if (maxAllowedSockets == 0) {
                ReplyToPlayer(player, "Generic.Error.NoPermission");
                return;
            }
            if (!VerifyPermissionAny(player, PermissionCommonPresets) || !VerifyHasNoCar(player) || !VerifyOffCooldown(player, CooldownType.Spawn) || !VerifyLocationNotRestricted(player) || !_pluginConfig.CanSpawnBuildingBlocked && !VerifyNotBuildingBlocked(player)) return;
            var presetNameArg = args[0];
            SimplePreset preset;
            if (!VerifyOnlyOneMatchingPreset(player, _commonPresets, presetNameArg, out preset)) return;
            SpawnPresetCarForPlayer(player, preset);
        }
        private void SubCommand_FixCar(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionFix)) return;
            ModularCar car;
            if (!VerifyHasCar(player, out car) || !VerifyOffCooldown(player, CooldownType.Fix) || FixMyCarWasBlocked(player.Object as BasePlayer, car)) return;
            if (car.IsDead()) ReviveCar(car);
            FixCar(car, GetPlayerAllowedFuel(player.Id), GetPlayerEnginePartsTier(player.Id));
            MaybeFillTankerModules(car, GetPlayerAllowedFreshWater(player.Id));
            _pluginData.StartCooldown(player.Id, CooldownType.Fix);
            MaybePlayCarRepairEffects(car);
            ReplyToPlayer(player, "Command.Fix.Success");
        }
        private void SubCommand_FetchCar(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionFetch)) return;
            var basePlayer = player.Object as BasePlayer;
            ModularCar car;
            Vector3 fetchPosition;
            Quaternion fetchRotation;
            if (!VerifyHasCar(player, out car) || !_pluginConfig.CanFetchOccupied && !VerifyCarNotOccupied(player, car) || !VerifyOffCooldown(player, CooldownType.Fetch) || !VerifyLocationNotRestricted(player) || !_pluginConfig.CanFetchBuildingBlocked && !VerifyNotBuildingBlocked(player) || !VerifySufficientSpace(player, car.TotalSockets, out fetchPosition, out fetchRotation) || FetchMyCarWasBlocked(basePlayer, car)) return;
            // This is a hacky way to determine that the car is on a lift.if (car.rigidBody.isKinematic && !TryReleaseCarFromLift(car))
            {
                var messages = new List<string> {
                    GetMessage(player, "Command.Fetch.Error.StuckOnLift")
                }
                ;
                if (permission.UserHasPermission(player.Id, PermissionDespawn)) messages.Add(GetMessage(player, "Command.Fetch.Error.StuckOnLift.Help"));
                player.Reply(string.Join(" ", messages));
                return;
            }
            if (_pluginConfig.DismountPlayersOnFetch) DismountAllPlayersFromCar(car);
            // Temporarily clear max angular velocity to prevent the car from unexpectedly spinning when teleporting really far.var maxAngularVelocity = car.rigidBody.maxAngularVelocity;
            car.rigidBody.maxAngularVelocity = 0;
            car.transform.SetPositionAndRotation(fetchPosition, fetchRotation);
            car.SetVelocity(Vector3.zero);
            car.SetAngularVelocity(Vector3.zero);
            car.UpdateNetworkGroup();
            car.SendNetworkUpdateImmediate();
            timer.Once(1f, () => {
                if (car != null) car.rigidBody.maxAngularVelocity = maxAngularVelocity;
            }
            );
            _pluginData.StartCooldown(player.Id, CooldownType.Fetch);
            ReplyToPlayer(player, "Command.Fetch.Success");
        }
        private void SubCommand_DestroyCar(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionDespawn)) return;
            var basePlayer = player.Object as BasePlayer;
            ModularCar car;
            if (!VerifyHasCar(player, out car) || !_pluginConfig.CanDespawnOccupied && !VerifyCarNotOccupied(player, car) || DestroyMyCarWasBlocked(basePlayer, car)) return;
            var extractedEngineParts = ExtractEnginePartsAboveTierAndDeleteRest(car, GetPlayerEnginePartsTier(player.Id));
            car.Kill();
            if (extractedEngineParts.Count > 0) {
                GiveItemsToPlayerOrDrop(basePlayer, extractedEngineParts);
                ReplyToPlayer(player, "Generic.Info.PartsRecovered");
            }
        }
        private void SubCommand_ListPresets(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionPresets)) return;
            PlayerConfig config = GetPlayerConfig(player);
            if (config.Presets.Count == 0) {
                ReplyToPlayer(player, "Generic.Error.NoPresets");
                return;
            }
            var presetList = config.Presets.Select(p => p).ToList();
            presetList.Sort(SortPresetNames);
            var sb = new StringBuilder();
            sb.AppendLine(GetMessage(player, "Command.List"));
            foreach (var preset in presetList) sb.AppendLine(GetMessage(player, "Command.List.Item", preset.Name, preset.NumSockets));
            player.Reply(sb.ToString());
        }
        private void SubCommand_Common_ListPresets(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionCommonPresets)) return;
            if (_commonPresets.Presets.Count == 0) {
                ReplyToPlayer(player, "Generic.Error.NoCommonPresets");
                return;
            }
            ushort maxAllowedSockets = GetPlayerMaxAllowedCarSockets(player.Id);
            var presetList = _commonPresets.Presets.Where(p => p.NumSockets <= maxAllowedSockets).ToList();
            presetList.Sort(SortPresetNames);
            var sb = new StringBuilder();
            sb.AppendLine(GetMessage(player, "Command.Common.List"));
            foreach (var preset in presetList) sb.AppendLine(GetMessage(player, "Command.List.Item", preset.Name, preset.NumSockets));
            player.Reply(sb.ToString());
        }
        private void SubCommand_SavePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionPresets)) return;
            ModularCar car;
            if (!VerifyHasCar(player, out car)) return;
            var presetNameArg = args.Length == 0 ? DefaultPresetName : args[0];
            var presetManager = GetPlayerConfig(player);
            if (!VerifyNoMatchingPreset(player, presetManager, presetNameArg)) return;
            if (presetManager.Presets.Count >= _pluginConfig.MaxPresetsPerPlayer) {
                ReplyToPlayer(player, "Command.SavePreset.Error.TooManyPresets", _pluginConfig.MaxPresetsPerPlayer);
                return;
            }
            SavePreset(player, presetManager, presetNameArg, car);
        }
        private void SubCommand_Common_SavePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionManageCommonPresets)) return;
            if (args.Length == 0) {
                ReplyToPlayer(player, "Command.Common.SavePreset.Error.Syntax");
                return;
            }
            var presetNameArg = args[0];
            ModularCar car;
            if (!VerifyHasCar(player, out car) || !VerifyNoMatchingPreset(player, _commonPresets, presetNameArg)) return;
            SavePreset(player, _commonPresets, presetNameArg, car);
        }
        private void SavePreset(IPlayer player, SimplePresetManager presetManager, string presetNameArg, ModularCar car) {
            if (presetNameArg.Length > PresetMaxLength) {
                ReplyToPlayer(player, "Generic.Error.PresetNameLength", PresetMaxLength);
                return;
            }
            presetManager.SavePreset(SimplePreset.FromCar(car, presetNameArg));
            ReplyToPlayer(player, "Command.SavePreset.Success", presetNameArg);
        }
        private void SubCommand_UpdatePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionPresets)) return;
            var presetNameArg = args.Length == 0 ? DefaultPresetName : args[0];
            UpdatePreset(player, GetPlayerConfig(player), presetNameArg);
        }
        private void SubCommand_Common_UpdatePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionManageCommonPresets)) return;
            if (args.Length == 0) {
                ReplyToPlayer(player, "Command.Common.UpdatePreset.Error.Syntax");
                return;
            }
            UpdatePreset(player, _commonPresets, args[0]);
        }
        private void UpdatePreset(IPlayer player, SimplePresetManager presetManager, string presetNameArg) {
            ModularCar car;
            if (!VerifyHasCar(player, out car)) return;
            SimplePreset preset;
            if (!VerifyHasPreset(player, presetManager, presetNameArg, out preset)) return;
            presetManager.UpdatePreset(SimplePreset.FromCar(car, preset.Name));
            ReplyToPlayer(player, "Command.UpdatePreset.Success", preset.Name);
        }
        private void SubCommand_LoadPreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionPresetLoad)) return;
            var presetNameArg = args.Length == 0 ? DefaultPresetName : args[0];
            LoadPreset(player, GetPlayerConfig(player.Id), presetNameArg);
        }
        private void SubCommand_Common_LoadPreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionPresetLoad) || !VerifyPermissionAny(player, PermissionCommonPresets)) return;
            if (args.Length == 0) {
                ReplyToPlayer(player, "Command.Common.LoadPreset.Error.Syntax");
                return;
            }
            var presetNameArg = args[0];
            LoadPreset(player, _commonPresets, presetNameArg);
        }
        private void LoadPreset(IPlayer player, SimplePresetManager presetManager, string presetNameArg) {
            var basePlayer = player.Object as BasePlayer;
            ModularCar car;
            if (!VerifyHasCar(player, out car) || !VerifyCarNotOccupied(player, car) || !VerifyOffCooldown(player, CooldownType.Load) || LoadMyCarPresetWasBlocked(basePlayer, car)) return;
            SimplePreset preset;
            if (!VerifyOnlyOneMatchingPreset(player, presetManager, presetNameArg, out preset)) return;
            var presetNumSockets = preset.NumSockets;
            if (presetNumSockets > GetPlayerMaxAllowedCarSockets(player.Id)) {
                ReplyToPlayer(player, "Generic.Error.NoPermissionToPresetSocketCount", preset.Name, preset.NumSockets);
                return;
            }
            if (presetNumSockets != car.TotalSockets) {
                ReplyToPlayer(player, "Command.LoadPreset.Error.SocketCount", preset.Name, presetNumSockets, car.TotalSockets);
                return;
            }
            if (car.IsDead()) ReviveCar(car);
            var wasEngineOn = car.IsOn();
            var enginePartsTier = GetPlayerEnginePartsTier(player.Id);
            var extractedEngineParts = ExtractEnginePartsAboveTierAndDeleteRest(car, enginePartsTier);
            UpdateCarModules(car, preset.ModuleIDs);
            _pluginData.StartCooldown(player.Id, CooldownType.Load);
            NextTick(() => {
                var wereExtraParts = false;
                if (extractedEngineParts.Count > 0) {
                    var remainingEngineParts = AddEngineItemsAndReturnRemaining(car, extractedEngineParts);
                    if (remainingEngineParts.Count > 0) {
                        wereExtraParts = true;
                        GiveItemsToPlayerOrDrop(basePlayer, remainingEngineParts);
                    }
                }
                FixCar(car, GetPlayerAllowedFuel(player.Id), enginePartsTier);
                // Restart the engine if it turned off during the brief moment it had no engine or no parts.if (wasEngineOn && !car.IsOn() && car.engineController.CanRunEngine())
                car.engineController.FinishStartingEngine();
                MaybeFillTankerModules(car, GetPlayerAllowedFreshWater(player.Id));
                if (car.CarLock.HasALock && !car.CarLock.CanHaveALock()) {
                    car.RemoveLock();
                }
                MaybePlayCarRepairEffects(car);
                var chatMessages = new List<string>() {
                    GetMessage(player, "Command.LoadPreset.Success", preset.Name)
                }
                ;
                if (wereExtraParts) chatMessages.Add(GetMessage(player, "Generic.Info.PartsRecovered"));
                player.Reply(string.Join(" ", chatMessages));
            }
            );
        }
        private void SubCommand_RenamePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionPresets)) return;
            if (args.Length < 2) {
                ReplyToPlayer(player, "Command.RenamePreset.Error.Syntax");
                return;
            }
            RenamePreset(player, GetPlayerConfig(player), args[0], args[1]);
        }
        private void SubCommand_Common_RenamePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionManageCommonPresets)) return;
            if (args.Length < 2) {
                ReplyToPlayer(player, "Command.Common.RenamePreset.Error.Syntax");
                return;
            }
            RenamePreset(player, _commonPresets, args[0], args[1]);
        }
        private void RenamePreset(IPlayer player, SimplePresetManager presetManager, string oldName, string newName) {
            SimplePreset preset;
            if (!VerifyHasPreset(player, presetManager, oldName, out preset)) return;
            // Cache actual old preset name since matching is case-insensitive.var actualOldPresetName = preset.Name;
            SimplePreset existingPresetWithNewName = presetManager.FindPreset(newName);
            if (newName.Length > PresetMaxLength) {
                ReplyToPlayer(player, "Generic.Error.PresetNameLength", PresetMaxLength);
                return;
            }
            // Allow renaming if just changing case.if (existingPresetWithNewName != null && preset != existingPresetWithNewName)
            {
                ReplyToPlayer(player, "Generic.Error.PresetAlreadyTaken", existingPresetWithNewName.Name);
                return;
            }
            presetManager.RenamePreset(preset, newName);
            ReplyToPlayer(player, "Command.RenamePreset.Success", actualOldPresetName, newName);
        }
        private void SubCommand_DeletePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionPresets)) return;
            var presetNameArg = args.Length == 0 ? DefaultPresetName : args[0];
            DeletePreset(player, GetPlayerConfig(player), presetNameArg);
        }
        private void SubCommand_Common_DeletePreset(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionManageCommonPresets)) return;
            if (args.Length == 0) {
                ReplyToPlayer(player, "Command.Common.DeletePreset.Error.Syntax");
                return;
            }
            DeletePreset(player, _commonPresets, args[0]);
        }
        private void DeletePreset(IPlayer player, SimplePresetManager presetManager, string presetNameArg) {
            SimplePreset preset;
            if (!VerifyHasPreset(player, presetManager, presetNameArg, out preset)) return;
            presetManager.DeletePreset(preset);
            ReplyToPlayer(player, "Command.DeletePreset.Success", preset.Name);
        }
        private void SubCommand_ToggleAutoCodeLock(IPlayer player, string[] args) {
            if (VehicleDeployedLocks == null || !VerifyPermissionAny(player, PermissionAutoCodeLock)) return;
            var config = GetPlayerConfig(player);
            config.Settings.AutoCodeLock = !config.Settings.AutoCodeLock;
            config.SaveData();
            ReplyToPlayer(player, "Command.ToggleAutoCodeLock.Success", BooleanToLocalizedString(player, config.Settings.AutoCodeLock));
        }
        private void SubCommand_ToggleAutoKeyLock(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionAutoKeyLock)) return;
            var config = GetPlayerConfig(player);
            config.Settings.AutoKeyLock = !config.Settings.AutoKeyLock;
            config.SaveData();
            ReplyToPlayer(player, "Command.ToggleAutoKeyLock.Success", BooleanToLocalizedString(player, config.Settings.AutoKeyLock));
        }
        private void SubCommand_ToggleAutoFillTankers(IPlayer player, string[] args) {
            if (!VerifyPermissionAny(player, PermissionAutoFillTankers)) return;
            var config = GetPlayerConfig(player);
            config.Settings.AutoFillTankers = !config.Settings.AutoFillTankers;
            config.SaveData();
            ReplyToPlayer(player, "Command.ToggleAutoFillTankers.Success", BooleanToLocalizedString(player, config.Settings.AutoFillTankers));
        }
#endregion
#region Helper Methods - Command Checks
        private static bool SpawnWasBlocked(BasePlayer player) {
            object hookResult = Interface.CallHook("CanSpawnModularCar", player);
            return hookResult is bool && (bool)hookResult == false;
        }
        private static bool SpawnMyCarWasBlocked(BasePlayer player) {
            if (SpawnWasBlocked(player)) return true;
            object hookResult = Interface.CallHook("CanSpawnMyCar", player);
            return hookResult is bool && (bool)hookResult == false;
        }
        private static bool FetchMyCarWasBlocked(BasePlayer player, ModularCar car) {
            object hookResult = Interface.CallHook("CanFetchMyCar", player, car);
            return hookResult is bool && (bool)hookResult == false;
        }
        private static bool FixMyCarWasBlocked(BasePlayer player, ModularCar car) {
            object hookResult = Interface.CallHook("CanFixMyCar", player, car);
            return hookResult is bool && (bool)hookResult == false;
        }
        private static bool LoadMyCarPresetWasBlocked(BasePlayer player, ModularCar car) {
            object hookResult = Interface.CallHook("CanLoadMyCarPreset", player, car);
            return hookResult is bool && (bool)hookResult == false;
        }
        private static bool DestroyMyCarWasBlocked(BasePlayer player, ModularCar car) {
            object hookResult = Interface.CallHook("CanDestroyMyCar", player, car);
            return hookResult is bool && (bool)hookResult == false;
        }
        private bool VerifyPermissionAny(IPlayer player, params string[] permissionNames) {
            foreach (var perm in permissionNames) {
                if (!permission.UserHasPermission(player.Id, perm)) {
                    ReplyToPlayer(player, "Generic.Error.NoPermission");
                    return false;
                }
            }
            return true;
        }
        private bool VerifyLocationNotRestricted(IPlayer player) {
            if ((player.Object as BasePlayer).GetComponentInParent<CargoShip>() != null) {
                ReplyToPlayer(player, "Generic.Error.LocationRestricted");
                return false;
            }
            return true;
        }
        private bool VerifyNotBuildingBlocked(IPlayer player) {
            if ((player.Object as BasePlayer).IsBuildingBlocked()) {
                ReplyToPlayer(player, "Generic.Error.BuildingBlocked");
                return false;
            }
            return true;
        }
        private bool VerifySufficientSpace(IPlayer player, int numSockets, out Vector3 determinedPosition, out Quaternion determinedRotation) {
            var basePlayer = player.Object as BasePlayer;
            if (!TryGetIdealCarPositionAndRotation(basePlayer, numSockets, out determinedPosition, out determinedRotation) || !HasSufficientSpace(basePlayer, numSockets, determinedPosition, determinedRotation)) {
                ReplyToPlayer(player, "Generic.Error.InsufficientSpace");
                return false;
            }
            return true;
        }
        private bool VerifyHasPreset(IPlayer player, SimplePresetManager presetManager, string presetName, out SimplePreset preset) {
            preset = presetManager.FindPreset(presetName);
            if (preset == null) {
                ReplyToPlayer(player, "Generic.Error.PresetNotFound", presetName);
                return false;
            }
            return true;
        }
        private bool VerifyNoMatchingPreset(IPlayer player, SimplePresetManager presetManager, string presetName) {
            var existingPreset = presetManager.FindPreset(presetName);
            if (existingPreset != null) {
                ReplyToPlayer(player, "Command.SavePreset.Error.PresetAlreadyExists", existingPreset.Name);
                return false;
            }
            return true;
        }
        private bool VerifyHasCar(IPlayer player, out ModularCar car) {
            car = FindPlayerCar(player);
            if (car == null) {
                ReplyToPlayer(player, "Generic.Error.CarNotFound");
                return false;
            }
            return true;
        }
        private bool VerifyHasNoCar(IPlayer player) {
            if (FindPlayerCar(player) == null) return true;
            var messages = new List<string> {
                GetMessage(player, "Command.Spawn.Error.CarAlreadyExists")
            }
            ;
            if (permission.UserHasPermission(player.Id, PermissionFetch)) messages.Add(GetMessage(player, "Command.Spawn.Error.CarAlreadyExists.Help"));
            player.Reply(string.Join(" ", messages));
            return false;
        }
        private bool VerifyCarNotOccupied(IPlayer player, ModularCar car) {
            // Players can either be mounted in seats, or standing on flatbed modules.if (car.AnyMounted()
     
// ... [Code preview truncated due to length. Full source in attached file] ...

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху