C#:
using Oxide.Plugins.BiplaneExtensionMethods;
using System.Collections.Generic;
using Oxide.Game.Rust.Cui;
using System.Collections;
using System.Reflection;
using Newtonsoft.Json;
using Rust.Modular;
using UnityEngine;
using Oxide.Core;
using Oxide.Core.Plugins;
using System;
namespace Oxide.Plugins {
[Info("Biplane", "Adem", "1.0.9")]
class Biplane : RustPlugin {
#region Variables
const bool en = true;
bool unload = false;
private static Biplane ins;
HashSet<BiplaneComponent> biplanes = new HashSet<BiplaneComponent>();
List<SellerData> sellers = new List<SellerData>();
HashSet<MonumentInfo> monuments = new HashSet<MonumentInfo>();
Coroutine spawnCorountine;
Coroutine saveCoroutine;
#endregion Variables
#region Hooks
void OnServerInitialized() {
ins = this;
UpdateConfig();
foreach (BiplaneSetting biplaneSetting in _config.biplanePresets.Values) {
if (biplaneSetting.permission != "") permission.RegisterPermission(biplaneSetting.permission, this);
}
if (!_config.samSite && !_config.samSiteMonuments) Unsubscribe("OnSamSiteTargetScan");
LoadDefaultMessages();
permission.RegisterPermission(_config.itemPermission, this);
foreach (MonumentInfo monumentInfo in TerrainMeta.Path.Monuments.Where(x => _config.spawnSetting.monumentSpawnSettings.ContainsKey(x.name))) monuments.Add(monumentInfo);
if (_config.spawnSetting.monumentSpawnSettings.Any(x => x.Value.enableSpawn) || _config.spawnSetting.customSpawnPointsConfig.enableSpawn) spawnCorountine = ServerMgr.Instance.StartCoroutine(SpawnCorountine());
SpawnSellersAtMonuments();
LoadData();
foreach (ModularCar modularCar in ModularCar.allCarsList) {
if (!modularCar.IsExists() || modularCar.NumAttachedModules > 1) continue;
SaveBiplaneData saveBiplaneData = saveBiplanes.FirstOrDefault(x => x.biplaneId == modularCar.net.ID.Value);
if (saveBiplaneData == null) continue;
BaseVehicleModule baseVehicleModule;
modularCar.TryGetModuleAt(0, out baseVehicleModule);
if (modularCar.NumAttachedModules == 0 || (modularCar.NumAttachedModules == 1 && baseVehicleModule != null && baseVehicleModule.name == "assets/content/vehicles/modularcar/module_entities/1module_engine.prefab")) LoadBiplane(modularCar, saveBiplaneData);
}
timer.In(1f, () => saveCoroutine = ServerMgr.Instance.StartCoroutine(SaveCorountine()));
}
void Unload() {
if (saveCoroutine != null) ServerMgr.Instance.StopCoroutine(saveCoroutine);
unload = true;
if (spawnCorountine != null) ServerMgr.Instance.StopCoroutine(spawnCorountine);
foreach (SellerData sellerData in sellers) sellerData.Destroy();
foreach (BasePlayer player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, "BiplaneSellerPanel");
CuiHelper.DestroyUi(player, "FuelText");
}
saveBiplanes.Clear();
foreach (BiplaneComponent biplane in biplanes) {
SaveBiplane(biplane);
UnityEngine.Object.DestroyImmediate(biplane, true);
}
SaveData();
ins = null;
}
object OnEntityTakeDamage(DecorWing entity, HitInfo info) {
if (entity == null || info == null) return null;
if (entity.ShortPrefabName.Contains("kayak") || entity.ShortPrefabName.Contains("boogieboard")) {
BiplaneComponent biplaneComponent = biplanes.FirstOrDefault(x => x.subEntities.Contains(entity));
if (biplaneComponent == null) return null;
biplaneComponent.modularCar.Hurt(info);
return true;
}
return null;
}
object CanMountEntity(BasePlayer player, BaseMountable entity) {
if (player == null || entity == null || !player.userID.IsSteamId()) return null;
BiplaneComponent biplaneComponent = biplanes.FirstOrDefault(x => x != null && (x.fakeSeat != null && x.fakeSeat == entity) || (x.pilotSeat != null && x.pilotSeat == entity));
if (biplaneComponent != null) {
if (biplaneComponent.biplaneSetting.permission != "" && !permission.UserHasPermission(player.UserIDString, biplaneComponent.biplaneSetting.permission)) {
PrintToChat(player, GetMessage("NoPermission", player.UserIDString, ins._config.prefics));
return true;
}
else if (biplaneComponent.modularCar.CarLock != null && !biplaneComponent.modularCar.CarLock.PlayerCanUseThis(player, ModularCarCodeLock.LockType.Door)) {
PrintToChat(player, GetMessage("Lock", player.UserIDString, ins._config.prefics));
return true;
}
else if (biplaneComponent.fakeSeat == entity) {
biplaneComponent.MountPlayer(player);
return true;
}
}
return null;
}
void OnEntityBuilt(Planner plan, GameObject go) {
if (plan == null || go == null) return;
Item item = plan.GetItem();
if (item == null) return;
var pair = _config.itemsPresets.FirstOrDefault(x => x.Value.shortname == item.info.shortname && x.Value.skin == item.skin);
if (pair.Value == null || pair.Key == null) return;
BaseEntity entity = go.GetComponent<BaseEntity>();
if (entity == null) return;
CreateBiplane(entity.transform.position, entity.transform.rotation, _config.biplanePresets.FirstOrDefault(x => x.Value.customItemShortname == pair.Key).Key, true, false);
NextTick(() => entity.Kill());
}
object OnNpcConversationStart(VehicleVendor vehicleVendor, BasePlayer player, ConversationData conversationData) {
if (vehicleVendor != null) {
SellerData sellerData = sellers.FirstOrDefault(x => x.seller == vehicleVendor);
if (sellerData != null) {
CreateGui(player, sellerData.sellerPrefab, sellers.IndexOf(sellerData));
return true;
}
}
return null;
}
void OnEntityMounted(BaseMountable entity, BasePlayer player) {
if (entity == null) return;
BiplaneComponent biplaneComponent = biplanes.FirstOrDefault(x => x != null && x.pilotSeat != null && x.pilotSeat.net.ID == entity.net.ID);
if (biplaneComponent != null) biplaneComponent.UnSleep();
}
void OnEntityDismounted(BaseMountable entity, BasePlayer player) {
if (entity == null) return;
BiplaneComponent biplaneComponent = biplanes.FirstOrDefault(x => x != null && x.pilotSeat != null && x.pilotSeat == entity);
if (biplaneComponent != null) CuiHelper.DestroyUi(player, "FuelText");
}
object OnEngineStart(BaseVehicle vehicle, BasePlayer driver) {
if (vehicle == null || driver == null) return null;
BiplaneComponent biplaneComponent = biplanes.FirstOrDefault(x => x.modularCar.net.ID == vehicle.net.ID);
if (biplaneComponent == null) return null;
if (biplaneComponent.modularCar.CarLock != null && !biplaneComponent.modularCar.CarLock.PlayerCanUseThis(driver, ModularCarCodeLock.LockType.Door)) {
PrintToChat(driver, GetMessage("Lock", driver.UserIDString, ins._config.prefics));
return true;
}
return null;
}
object CanLootEntity(BasePlayer player, StorageContainer container) {
if (player == null || container == null) return null;
BiplaneComponent biplaneComponent = null;
if (container.ShortPrefabName == "rhib_storage") biplaneComponent = biplanes.FirstOrDefault(x => x.container.net.ID == container.net.ID);
else if (container.ShortPrefabName == "modular_car_v8_engine_storage" || container.ShortPrefabName == "modular_car_fuel_storage") biplaneComponent = container.GetComponentInParent<BiplaneComponent>();
if (biplaneComponent == null) return null;
if (biplaneComponent.biplaneSetting.permission != "" && !permission.UserHasPermission(player.UserIDString, biplaneComponent.biplaneSetting.permission)) {
PrintToChat(player, GetMessage("NoPermission", player.UserIDString, ins._config.prefics));
return true;
}
if (biplaneComponent.modularCar.CarLock != null && !biplaneComponent.modularCar.CarLock.PlayerCanUseThis(player, ModularCarCodeLock.LockType.Door)) {
PrintToChat(player, GetMessage("Lock", player.UserIDString, ins._config.prefics));
return true;
}
return null;
}
object CanPickupEntity(BasePlayer player, BaseEntity entity) {
if (entity.PrefabName.Contains("kayak") && entity is Kayak == false) {
BiplaneComponent biplaneComponent = entity.GetComponentInParent<BiplaneComponent>();
if (biplaneComponent == null) return null;
if (biplaneComponent.biplaneSetting.customItemShortname != "") {
if (!ins._config.allowIpckUp) return false;
if (biplaneComponent.biplaneSetting.permission != "" && !permission.UserHasPermission(player.UserIDString, biplaneComponent.biplaneSetting.permission)) {
PrintToChat(player, GetMessage("NoPermission", player.UserIDString, ins._config.prefics));
return false;
}
if (biplaneComponent.modularCar.CarLock != null && !biplaneComponent.modularCar.CarLock.PlayerCanUseThis(player, ModularCarCodeLock.LockType.Door)) {
PrintToChat(player, GetMessage("Lock", player.UserIDString, ins._config.prefics));
return false;
}
else if (biplaneComponent.modularCar.GetFuelSystem().GetFuelAmount() > 0 || biplaneComponent.container.inventory.itemList.Count > 0) {
PrintToChat(player, GetMessage("EmptyСontainers", player.UserIDString, ins._config.prefics));
return false;
}
foreach (BaseVehicleModule module in biplaneComponent.modularCar.AttachedModuleEntities) {
VehicleModuleEngine engineModule = module as VehicleModuleEngine;
if (engineModule == null) continue;
Rust.Modular.EngineStorage engineStorage = engineModule.GetContainer() as Rust.Modular.EngineStorage;
if (engineStorage == null) continue;
if (engineStorage.inventory.itemList.Count > 0) {
PrintToChat(player, GetMessage("EmptyСontainers", player.UserIDString, ins._config.prefics));
return false;
}
}
MoveItem(player, CreateItem(_config.itemsPresets[biplaneComponent.biplaneSetting.customItemShortname]));
biplaneComponent.modularCar.Kill();
}
return false;
}
return null;
}
void OnLicensedVehicleSpawned(BaseEntity entity, BasePlayer player, string vehicleType) {
if (vehicleType != null && _config.biplanePresets.ContainsKey(vehicleType) && entity != null && entity.ShortPrefabName.Contains("3module.entity")) {
BiplaneComponent biplaneComponent = entity.gameObject.AddComponent<BiplaneComponent>();
biplaneComponent.Init(vehicleType, false);
biplanes.Add(biplaneComponent);
}
}
#endregion Hooks
#region Commands
[ChatCommand("biplanemonument")]
private void ChatNewBiplaneMonument(BasePlayer player) {
if (!player.IsAdmin) return;
MonumentInfo monumentInfo = TerrainMeta.Path.Monuments.FirstOrDefault(x => Vector3.Distance(player.transform.position, x.transform.position) < x.Bounds.size.x);
if (monumentInfo == null) {
PrintToChat(player, "Monument not found!");
return;
}
if (_config.spawnSetting.monumentSpawnSettings.ContainsKey(monumentInfo.name)) {
PrintToChat(player, "The monument has already been added");
return;
}
_config.spawnSetting.monumentSpawnSettings.Add(monumentInfo.name, new MonumentConfig());
SaveConfig();
}
[ChatCommand("biplanemonumentpoint")]
private void ChatNewBiplanePoint(BasePlayer player) {
if (!player.IsAdmin) return;
MonumentConfig monumentConfig;
LocationConfig locationConfig;
DefineMonumentAndPlayerLocation(player, out monumentConfig, out locationConfig);
if (monumentConfig == null || locationConfig == null) return;
monumentConfig.points.Add(locationConfig);
PrintToChat(player, "The biplane spawn point has been successfully added to the location");
SaveConfig();
}
[ChatCommand("biplaneseller")]
private void ChatNewBiplaneSeller(BasePlayer player) {
if (!player.IsAdmin) return;
MonumentConfig monumentConfig;
LocationConfig locationConfig;
DefineMonumentAndPlayerLocation(player, out monumentConfig, out locationConfig);
if (monumentConfig == null || locationConfig == null) return;
monumentConfig.sellerLocation = locationConfig;
PrintToChat(player, "The seller's spawn point has been successfully added to the location");
SaveConfig();
}
[ChatCommand("biplanesellerpoint")]
private void ChatNewBiplaneSellerPoint(BasePlayer player) {
if (!player.IsAdmin) return;
MonumentConfig monumentConfig;
LocationConfig locationConfig;
DefineMonumentAndPlayerLocation(player, out monumentConfig, out locationConfig);
if (monumentConfig == null || locationConfig == null) return;
monumentConfig.sellerBiplaneLocation = locationConfig;
PrintToChat(player, "The seller's biplane spawn point has been successfully added to the location");
SaveConfig();
}
[ChatCommand("givebiplane")]
void BiplaneGiveCommandk(BasePlayer player, string command, string[] arg) {
if (player == null || arg == null || arg.Length == 0) return;
if (!_config.itemsPresets.ContainsKey(arg[0])) return;
if (!permission.UserHasPermission(player.UserIDString, _config.itemPermission)) {
PrintToChat(player, "You do not have permission to use this command!");
return;
}
MoveItem(player, CreateItem(_config.itemsPresets[arg[0]]));
PrintToChat(player, GetMessage("GetBiplane", player.UserIDString, ins._config.prefics));
}
[ConsoleCommand("givebiplane")]
void GiveCustomItemCommand(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
BasePlayer target = null;
bool rcon = player == null;
if (arg.Args == null || arg.Args.Length == 0) return;
if (player != null) {
if (!permission.UserHasPermission(player.UserIDString, _config.itemPermission) && !rcon) {
PrintToConsole(player, "You do not have permission to use this command!");
return;
}
if (arg.Args.Length == 1 && !rcon) target = player;
else target = BasePlayer.FindByID(Convert.ToUInt64(arg.Args[1]));
}
else if (arg.Args.Length >= 2) target = BasePlayer.FindByID(Convert.ToUInt64(arg.Args[1]));
if (target == null) {
if (rcon) Puts("Player not found");
else PrintToConsole(player, "Player not found");
return;
}
MoveItem(target, CreateItem(_config.itemsPresets[arg.Args[0]]));
PrintToChat(target, GetMessage("GetBiplane", target.UserIDString, ins._config.prefics));
if (rcon) Puts($"A biplane was given to {target.displayName}");
else PrintToConsole(player, $"A biplane was given to {target.displayName}");
}
[ChatCommand("biplanecustomspawnpoint")]
private void ChatNewCustomSpawnPoint(BasePlayer player) {
if (!player.IsAdmin) return;
_config.spawnSetting.customSpawnPointsConfig.points.Add(new LocationConfig {
position = player.transform.position.ToString(), rotation = player.viewAngles.y.ToString()
}
);
PrintToChat(player, "Custom spawn point successfully added");
SaveConfig();
}
#endregion Commands
#region Methods
void UpdateConfig() {
if (_config.version != Version.ToString()) {
VersionNumber versionNumber;
var versionArray = _config.version.Split('.');
versionNumber.Major = Convert.ToInt32(versionArray[0]);
versionNumber.Minor = Convert.ToInt32(versionArray[1]);
versionNumber.Patch = Convert.ToInt32(versionArray[2]);
if (versionNumber.Patch == 0) {
PrintError("Delete the configuration file!");
NextTick(() => Server.Command($"o.unload {Name}"));
return;
}
if (versionNumber.Patch == 1) {
if (!_config.itemsPresets.ContainsKey("biplaneitem_airfield")) _config.itemsPresets.Add("biplaneitem_airfield", new NamedItem {
shortname = "box.wooden.large", skin = 2776561072, name = "Biplane Airfield"
}
);
if (!_config.itemsPresets.ContainsKey("biplaneitem_bomber")) _config.itemsPresets.Add("biplaneitem_bomber", new NamedItem {
shortname = "box.wooden.large", skin = 2776561506, name = "Biplane Airfield"
}
);
if (!_config.itemsPresets.ContainsKey("biplaneitem_stormtrooper")) _config.itemsPresets.Add("biplaneitem_stormtrooper", new NamedItem {
shortname = "box.wooden.large", skin = 2776561787, name = "Biplane Airfield"
}
);
foreach (var pair in _config.biplanePresets) {
if (pair.Key == "biplane_airfield") {
pair.Value.customItemShortname = "biplaneitem_airfield";
}
else if (pair.Key == "biplane_bomber") {
pair.Value.customItemShortname = "biplaneitem_bomber";
}
else if (pair.Key == "biplane_stormtrooper") {
pair.Value.customItemShortname = "biplaneitem_stormtrooper";
}
else if (pair.Key == "biplane_default") {
pair.Value.bombs = false;
pair.Value.rockets = false;
}
pair.Value.permission = "";
}
}
if (versionNumber.Patch <= 2) {
_config.marker = new MarkerConfig {
enable = true, text = "Biplane seller"
}
;
}
if (versionNumber.Patch <= 3) {
_config.allowIpckUp = true;
_config.spawnSetting.customSpawnPointsConfig = new CustomSpawnPointsConfig {
enableSpawn = false, presets = new Dictionary<string, float> {
["biplane_airfield"]
= 100
}
, points = new List<LocationConfig>()
}
;
}
if (versionNumber.Patch <= 4) {
foreach (string key in _config.biplanePresets.Keys) {
BiplaneSetting biplaneSetting = _config.biplanePresets[key];
biplaneSetting.biplaneControlSetting = new BiplaneControlSetting {
turningADSpeed = 1, turningMouseSpeed = 1,
}
;
}
}
_config.version = Version.ToString();
SaveConfig();
}
}
IEnumerator SpawnCorountine() {
while (true) {
yield return CoroutineEx.waitForSeconds(UnityEngine.Random.Range(_config.spawnSetting.minRespawnTime, _config.spawnSetting.maxRespawnTime));
SpawnBipaneAtMonuments();
SpawnBipaneAtCustomPosition();
}
}
IEnumerator SaveCorountine() {
while (true) {
saveBiplanes.Clear();
foreach (BiplaneComponent biplane in biplanes) SaveBiplane(biplane);
SaveData();
yield return CoroutineEx.waitForSeconds(3600);
}
}
void DefineMonumentAndPlayerLocation(BasePlayer player, out MonumentConfig monumentConfig, out LocationConfig locationConfig) {
MonumentInfo monumentInfo = TerrainMeta.Path.Monuments.FirstOrDefault(x => _config.spawnSetting.monumentSpawnSettings.ContainsKey(x.name) && Vector3.Distance(player.transform.position, x.transform.position) < x.Bounds.size.x);
if (monumentInfo == null) {
PrintToChat(player, "The monument was not found in the config.To add it, use the <addbiplanemonument> command ");
monumentConfig = null;
locationConfig = null;
return;
}
MonumentConfig newMonumentConfig = _config.spawnSetting.monumentSpawnSettings[monumentInfo.name];
LocationConfig newLocationConfig = new LocationConfig {
position = monumentInfo.transform.InverseTransformPoint(player.transform.position).ToString(), rotation = (player.viewAngles - monumentInfo.transform.rotation.eulerAngles).y.ToString()
}
;
monumentConfig = newMonumentConfig;
locationConfig = newLocationConfig;
}
void SpawnSellersAtMonuments() {
foreach (MonumentInfo monumentInfo in monuments) {
MonumentConfig monumentConfig = _config.spawnSetting.monumentSpawnSettings[monumentInfo.name];
if (!monumentConfig.enableSeller || monumentConfig.sellerLocation == null) continue;
Vector3 position = monumentInfo.transform.TransformPoint(monumentConfig.sellerLocation.position.ToVector3());
VehicleVendor seller = GameManager.server.CreateEntity("assets/prefabs/npc/bandit/shopkeepers/bandit_conversationalist.prefab", position, monumentInfo.transform.rotation * Quaternion.Euler(new Vector3(0, float.Parse(monumentConfig.sellerLocation.rotation), 0))) as VehicleVendor;
seller.enableSaving = false;
seller.Spawn();
if (!_config.marker.enable) sellers.Add(new SellerData(seller, monumentConfig.sellerName, monumentInfo.transform, monumentInfo.name, null));
else sellers.Add(new SellerData(seller, monumentConfig.sellerName, monumentInfo.transform, monumentInfo.name, CreateMapMarker(position)));
}
}
void SpawnBipaneAtMonuments() {
foreach (MonumentInfo monumentInfo in monuments) {
MonumentConfig monumentConfig = _config.spawnSetting.monumentSpawnSettings[monumentInfo.name];
if (monumentConfig.points.Count == 0 || monumentConfig.presets.Count == 0 || !monumentConfig.presets.Values.Any(x => x > 0)) continue;
LocationConfig locationConfig = monumentConfig.points.GetRandom();
string biplanePreset = "";
while (String.IsNullOrEmpty(biplanePreset)) {
foreach (var pair in monumentConfig.presets) {
if (UnityEngine.Random.Range(0f, 100f) <= pair.Value) {
biplanePreset = pair.Key;
break;
}
}
}
Vector3 position = monumentInfo.transform.TransformPoint(locationConfig.position.ToVector3());
if (biplanes.Any(x => Vector3.Distance(x.transform.position, position) < 10f)) continue;
CreateBiplane(position, monumentInfo.transform.rotation * Quaternion.Euler(new Vector3(0, float.Parse(locationConfig.rotation), 0)), biplanePreset);
}
}
void SpawnBipaneAtCustomPosition() {
if (!_config.spawnSetting.customSpawnPointsConfig.enableSpawn) return;
foreach (LocationConfig locationConfig in _config.spawnSetting.customSpawnPointsConfig.points) {
string biplanePreset = "";
while (String.IsNullOrEmpty(biplanePreset)) {
foreach (var pair in _config.spawnSetting.customSpawnPointsConfig.presets) {
if (UnityEngine.Random.Range(0f, 100f) <= pair.Value) {
biplanePreset = pair.Key;
break;
}
}
}
if (biplanes.Any(x => Vector3.Distance(x.transform.position, locationConfig.position.ToVector3()) < 10f)) continue;
CreateBiplane(locationConfig.position.ToVector3(), Quaternion.Euler(0, Convert.ToSingle(locationConfig.rotation), 0), biplanePreset);
}
}
void CreateBiplane(Vector3 position, Quaternion rotation, string presetName, bool firstSpawn = true, bool addModule = true) {
ModularCar car = GameManager.server.CreateEntity("assets/content/vehicles/modularcar/3module_car_spawned.entity.prefab", position, rotation) as ModularCar;
BiplaneComponent biplaneComponent = car.gameObject.AddComponent<BiplaneComponent>();
car.spawnSettings.useSpawnSettings = false;
car.Spawn();
biplaneComponent.Init(presetName, firstSpawn, addModule);
biplanes.Add(biplaneComponent);
}
void SaveBiplane(BiplaneComponent biplaneComponent) {
if (biplaneComponent == null || !biplaneComponent.modularCar.IsExists()) return;
SaveBiplaneData saveBiplaneData = new SaveBiplaneData(biplaneComponent.modularCar.net.ID.Value, biplaneComponent.presetName, 0);
foreach (Item item in biplaneComponent.container.inventory.itemList) {
if (item == null) continue;
SaveItemData saveItemData = new SaveItemData(item.info.shortname, item.name, item.amount, item.skin, item.condition);
BaseProjectile projectile = item.GetHeldEntity() as BaseProjectile;
if (projectile != null) {
saveItemData.projectileData = new ProjectileData(projectile.primaryMagazine.ammoType.shortname, projectile.primaryMagazine.contents);
foreach (Item modItem in item.contents.itemList) saveItemData.projectileData.mods.Add(modItem.info.shortname);
}
saveBiplaneData.items.Add(saveItemData);
}
saveBiplanes.Add(saveBiplaneData);
}
void LoadBiplane(ModularCar modularCar, SaveBiplaneData saveBiplaneData) {
BiplaneComponent biplaneComponent = modularCar.gameObject.AddComponent<BiplaneComponent>();
if (saveBiplaneData.keyIndex != 0) {
//modularCar.carLock.AddALock();
//modularCar.carLock.LockID = saveBiplaneData.keyIndex;
}
biplaneComponent.Init(saveBiplaneData.biplanePrefab, false);
biplanes.Add(biplaneComponent);
if (saveBiplaneData.items.Count > 0) timer.In(1f, () => {
foreach (SaveItemData saveItemData in saveBiplaneData.items) {
Item newItem = ItemManager.CreateByName(saveItemData.shortname, saveItemData.amount, saveItemData.skin);
newItem.condition = saveItemData.condition;
if (saveItemData.customName != null) newItem.name = saveItemData.customName;
if (!newItem.MoveToContainer(biplaneComponent.container.inventory)) {
newItem.Remove();
continue;
}
if (saveItemData.projectileData != null) {
BaseProjectile projectile = newItem.GetHeldEntity() as BaseProjectile;
if (projectile != null) {
if (saveItemData.projectileData.ammoShortname != "") projectile.primaryMagazine.ammoType = ItemManager.FindItemDefinition(saveItemData.projectileData.ammoShortname);
projectile.primaryMagazine.contents = saveItemData.projectileData.ammoAmount;
foreach (string shortname in saveItemData.projectileData.mods) {
ItemDefinition itemDefinition = ItemManager.FindItemDefinition(shortname);
if (itemDefinition != null) newItem.contents.AddItem(itemDefinition, 1);
}
}
}
}
}
);
}
VendingMachineMapMarker CreateMapMarker(Vector3 position) {
VendingMachineMapMarker vendingMarker = GameManager.server.CreateEntity("assets/prefabs/deployable/vendingmachine/vending_mapmarker.prefab", position) as VendingMachineMapMarker;
vendingMarker.enableSaving = false;
vendingMarker.Spawn();
vendingMarker.markerShopName = _config.marker.text;
return vendingMarker;
}
private static void CopySerializableFields<T>(T src, T dst) {
FieldInfo[] srcFields = typeof(T).GetFields(BindingFlags.Public | BindingFlags.Instance);
foreach (FieldInfo field in srcFields) {
object value = field.GetValue(src);
field.SetValue(dst, value);
}
}
#endregion Methods
#region Classes
class BiplaneComponent : FacepunchBehaviour {
internal Coroutine controlCorountine;
internal string presetName;
internal BiplaneSetting biplaneSetting;
internal StorageContainer container;
internal ModularCar modularCar;
internal BaseMountable fakeSeat;
internal List<BaseEntity> subEntities = new List<BaseEntity>();
List<BaseEntity> rotors = new List<BaseEntity>();
Rigidbody rigidbody;
internal BaseMountable pilotSeat;
List<BaseEntity> rockets = new List<BaseEntity>();
bool active = true;
internal bool grounded = true;
bool engineOn = false;
int lastFuelAmount = 0;
float weaonDelay = 1f;
bool leftRocket = true;
internal void Init(string presetName, bool firstSpawn = true, bool addModule = true) {
this.presetName = presetName;
biplaneSetting = ins._config.biplanePresets[presetName];
modularCar = GetComponent<ModularCar>();
modularCar.spawnSettings.useSpawnSettings = false;
modularCar.Inventory.ModuleContainer.capacity = 1;
modularCar.Inventory.ModuleContainer.SetOnlyAllowedItem(ItemManager.FindItemDefinition("vehicle.1mod.engine"));
foreach (BaseVehicle.MountPointInfo mountPointInfo in modularCar.mountPoints) mountPointInfo.mountable.Kill();
modularCar.mountPoints.Clear();
rigidbody = modularCar.rigidBody;
rigidbody.drag = 0.1f;
Invoke(() => Buid(firstSpawn, addModule), 0.1f);
}
void Buid(bool firstSpawn, bool addModule) {
if (firstSpawn) {
Item moduleItem = ItemManager.CreateByName("vehicle.1mod.engine");
modularCar.TryAddModule(moduleItem, 0);
if (addModule) Invoke(EngineBuild, 0.25f);
}
SpawnSubEntity();
SpawnSeat();
SpawnRotor();
}
void EngineBuild() {
if (biplaneSetting.fuelAmount > 0) {
StorageContainer fuelContainer = GetFuelContainer(modularCar);
if (fuelContainer != null) {
fuelContainer.inventory.AddItem(fuelContainer.allowedItem, biplaneSetting.fuelAmount);
fuelContainer.isLootable = false;
UpdateFuelSystem(modularCar);
// Call to update the fuel system after adding fuel
}
}
if (biplaneSetting.engineComponents) {
foreach (BaseVehicleModule module in modularCar.AttachedModuleEntities) {
VehicleModuleEngine engineModule = module as VehicleModuleEngine;
if (engineModule == null) continue;
Rust.Modular.EngineStorage engineStorage = engineModule.GetContainer() as Rust.Modular.EngineStorage;
if (engineStorage == null) continue;
ItemContainer inventory = engineStorage.inventory;
for (var i = 0; i < inventory.capacity; i++) {
ItemModEngineItem output;
if (!engineStorage.allEngineItems.TryGetItem(biplaneSetting.engineComponentsLvl, engineStorage.slotTypes[i], out output)) continue;
ItemDefinition component = output.GetComponent<ItemDefinition>();
Item item = ItemManager.Create(component);
if (item == null) continue;
item.conditionNormalized = 100;
item.MoveToContainer(engineStorage.inventory, i, allowStack : false);
}
engineModule.RefreshPerformanceStats(engineStorage);
return;
}
}
}
StorageContainer GetFuelContainer(BaseModularVehicle vehicle) {
// Accessing the fuel container through available modules and properties
foreach (BaseVehicleModule module in vehicle.AttachedModuleEntities) {
if (module is VehicleModuleEngine engineModule) {
// Check if the engine module has any child entities that are StorageContainer
foreach (BaseEntity child in engineModule.children) {
if (child is StorageContainer container && container.allowedItem != null && container.allowedItem.shortname == "lowgradefuel") {
return container;
}
}
}
}
return null;
}
void UpdateFuelSystem(BaseModularVehicle vehicle) {
// This method triggers the fuel system to recognize the new fuel level
IFuelSystem fuelSystem = vehicle.GetFuelSystem();
if (fuelSystem != null) {
// This is a hypothetical method.Replace with the actual method to update the fuel system if available
// fuelSystem.UpdateFuelLevel();
// or fuelSystem.Refresh(); or similar
// Ensure to call the right method that updates or refreshes the fuel system
}
}
void SpawnRotor() {
foreach (BaseEntity rotor in rotors) if (rotor != null && !rotor.IsDestroyed) rotor.Kill();
rotors.Clear();
if (rotors.Count == 0) {
foreach (RotorData rotorData in ins.rotorPositions) {
BaseEntity entity = GameManager.server.CreateEntity("assets/prefabs/weapons/sword big/longsword.entity.prefab", Vector3.zero, Quaternion.identity, false);
entity.enableSaving = false;
entity.SetParent(modularCar);
entity.transform.localPosition = rotorData.position;
entity.transform.localEulerAngles = rotorData.rotation;
entity.SetFlag(BaseEntity.Flags.Reserved8, true);
entity.Spawn();
rotors.Add(entity);
if (rotorData.hide) entity.limitNetworking = true;
}
}
else {
for (int i = 0; i < ins.rotorPositions.Count; i++) {
if (i >= rotors.Count) return;
BaseEntity rotor = rotors[i];
if (!rotor.IsExists()) continue;
if (ins.rotorPositions[i].hide) rotor.limitNetworking = true;
else rotor.limitNetworking = false;
}
}
}
void SpawnSubEntity() {
foreach (SubEntityData subEntityData in ins.subEntityDatas) {
if (subEntityData.type == 4 && !biplaneSetting.rockets) continue;
BaseEntity entity = GameManager.server.CreateEntity(subEntityData.name, Vector3.zero, Quaternion.identity, false);
entity.enableSaving = false;
if (subEntityData.type == 0) {
DecorWing newEntity = entity.gameObject.AddComponent<DecorWing>();
CopySerializableFields(entity, newEntity);
UnityEngine.Object.DestroyImmediate(entity, true);
newEntity.gameObject.AwakeFromInstantiate();
newEntity.enableSaving = false;
newEntity.SetParent(modularCar);
newEntity.transform.localPosition = subEntityData.position;
newEntity.transform.localEulerAngles = subEntityData.rotation;
newEntity.Spawn();
newEntity.InitializeHealth(200, 200);
newEntity.SetFlag(BaseEntity.Flags.Reserved7, true);
newEntity.SetFlag(BaseEntity.Flags.On, true);
newEntity.SetFlag(BaseEntity.Flags.Busy, true);
Rigidbody entityRigidbody = newEntity.GetComponent<Rigidbody>();
if (entityRigidbody != null) Destroy(entityRigidbody);
subEntities.Add(newEntity);
}
else if (subEntityData.type == 1) {
Kayak kayak = entity as Kayak;
BaseVehicle newEntity = entity.gameObject.AddComponent<BaseVehicle>();
CopySerializableFields(kayak, newEntity);
UnityEngine.Object.DestroyImmediate(entity, true);
newEntity.gameObject.AwakeFromInstantiate();
newEntity.enableSaving = false;
newEntity.SetParent(modularCar);
newEntity.transform.localPosition = subEntityData.position;
newEntity.transform.localEulerAngles = subEntityData.rotation;
Rigidbody entityRigidbody = newEntity.GetComponent<Rigidbody>();
if (entityRigidbody != null) Destroy(entityRigidbody);
newEntity.isMobile = false;
newEntity.Spawn();
subEntities.Add(newEntity);
newEntity.SetFlag(BaseEntity.Flags.On, true);
foreach (var a in newEntity.mountPoints) {
a.mountable.SetParent(modularCar);
modularCar.mountPoints.Add(a);
a.mountable.transform.localPosition = new Vector3(a.mountable.transform.localPosition.x, a.mountable.transform.localPosition.y + 0.68f, a.mountable.transform.localPosition.z);
a.mountable.allowHeadLook = false;
newEntity.SetFlag(BaseEntity.Flags.Reserved8, true);
if (fakeSeat == null) fakeSeat = a.mountable;
else a.isDriver = false;
}
}
else {
entity.SetParent(modularCar);
entity.transform.localPosition = subEntityData.position;
entity.transform.localEulerAngles = subEntityData.rotation;
if (subEntityData.type == 2 || subEntityData.type >= 4) entity.SetFlag(BaseEntity.Flags.Reserved8, true);
entity.Spawn();
Rigidbody entityRigidbody = entity.GetComponent<Rigidbody>();
if (entityRigidbody != null) Destroy(entityRigidbody);
subEntities.Add(entity);
if (subEntityData.type == 4) rockets.Add(entity);
if (subEntityData.type == 3) {
container = entity as StorageContainer;
container.inventory.capacity = biplaneSetting.countSlots;
}
}
}
}
void SpawnSeat() {
BaseMountable seat = GameManager.server.CreateEntity("assets/prefabs/vehicle/seats/miniheliseat.prefab") as BaseMountable;
seat.enableSaving = false;
seat.SetParent(modularCar, true, false);
seat.transform.localPosition = new Vector3(0f, 0.45f, 0.324f);
seat.transform.localEulerAngles = Vector3.zero;
seat.Spawn();
modularCar.mountPoints.Add(new BaseVehicle.MountPointInfo {
pos = seat.transform.position, rot = seat.transform.eulerAngles, isDriver = true, mountable = seat, prefab = null
}
);
pilotSeat = seat;
}
internal void MountPlayer(BasePlayer player) {
if (pilotSeat._mounted == null) pilotSeat.MountPlayer(player);
}
internal void UnSleep() {
if (controlCorountine == null) controlCorountine = ServerMgr.Instance.StartCoroutine(ControlCorountine());
}
IEnumerator ControlCorountine() {
lastFuelAmount = 0;
while (!grounded || pilotSeat._mounted != null) {
bool checkGroung = modularCar.wheelFR.wheelCollider.isGrounded || modularCar.wheelFL.wheelCollider.isGrounded || modularCar.wheelRR.wheelCollider.isGrounded || modularCar.wheelRL.wheelCollider.isGrounded || Vector3.Angle(modularCar.transform.forward, rigidbody.velocity) > 90;
if (checkGroung != grounded) {
grounded = checkGroung;
if (grounded) {
rigidbody.maxAngularVelocity = 0.7f;
modularCar.carSettings.maxSteerAngle = 35f;
}
else {
rigidbody.maxAngularVelocity = 0.3f;
modularCar.carSettings.maxSteerAngle = 0;
}
}
bool checkEngine = modularCar.engineController.IsOn;
if (checkEngine != engineOn) {
engineOn = checkEngine;
if (!engineOn) SpawnRotor();
}
if (engineOn) {
foreach (BaseEntity rotor in rotors) {
if (UnityEngine.Random.Range(0, 2) < 1) {
rotor.limitNetworking = true;
rotor.limitNetworking = false;
}
}
}
BasePlayer player = pilotSeat._mounted;
if (player != null) {
UpdateGui(player);
float leftRight = player.serverInput.MouseDelta().x;
if (leftRight > 10) leftRight = 10;
if (leftRight < -10) leftRight = -10;
if (ins._config.invertX) leftRight = -leftRight;
float upDown = player.serverInput.MouseDelta().y;
if (upDown > 10) upDown = 10;
if (upDown < -10) upDown = -10;
if (ins._config.invertY) upDown = -upDown;
float speedScale = 1.25f * rigidbody.velocity.magnitude / biplaneSetting.maxVelosity;
if (speedScale > 1) speedScale = 1;
if (grounded) {
if (upDown < 0 || rigidbody.velocity.magnitude < 10) upDown = 0;
rigidbody.AddForce(Vector3.up * rigidbody.velocity.magnitude * 1000);
}
if (player.serverInput.IsDown(BUTTON.FORWARD) && (rigidbody.velocity.magnitude < biplaneSetting.maxVelosity) && engineOn) rigidbody.AddForce(modularCar.transform.forward.normalized * biplaneSetting.force);
if (upDown != 0) rigidbody.AddTorque(modularCar.transform.right * upDown * -4000 * speedScale * biplaneSetting.biplaneControlSetting.turningMouseSpeed);
if (!grounded) {
rigidbody.AddTorque(modularCar.transform.up * leftRight * 4000 * speedScale * biplaneSetting.biplaneControlSetting.turningMouseSpeed);
if (player.serverInput.IsDown(BUTTON.LEFT)) rigidbody.AddTorque(modularCar.transform.forward * 4000 * speedScale * biplaneSetting.biplaneControlSetting.turningADSpeed);
if (player.serverInput.IsDown(BUTTON.RIGHT)) rigidbody.AddTorque(modularCar.transform.forward * -4000 * speedScale * biplaneSetting.biplaneControlSetting.turningADSpeed);
}
}
Vector2 vector2 = new Vector2(rigidbody.velocity.x, rigidbody.velocity.z);
if (!gro
// ... [Code preview truncated due to length. Full source in attached file] ...