Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 198 additions & 0 deletions S1API/Vehicles/LandVehicle.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
#if (IL2CPPMELON)
using S1Vehicles = Il2CppScheduleOne.Vehicles;
using Il2Cpp;
using Il2CppFishNet;
using Il2CppFishNet.Connection;
#elif (MONOMELON || MONOBEPINEX || IL2CPPBEPINEX)
using S1Vehicles = ScheduleOne.Vehicles;
using FishNet;
using FishNet.Connection;
#endif
using System;
using System.Reflection;
using UnityEngine;
using S1API.Logging;

namespace S1API.Vehicles
{
/// <summary>
/// Represents a land vehicle in the game.
/// </summary>
public class LandVehicle
{
// Public members intended to be used by modders
#region Public Members
/// <summary>
/// Creates a new LandVehicle instance.
/// </summary>
public LandVehicle(string vehicleCode)
{
var vehiclePrefab = S1Vehicles.VehicleManager.Instance.GetVehiclePrefab(vehicleCode);
if (vehiclePrefab == null)
{
_logger.Error($"SpawnVehicle: '{vehicleCode}' is not a valid vehicle code!");
return;
}

var component = UnityEngine.Object.Instantiate<GameObject>(vehiclePrefab.gameObject)
.GetComponent<S1Vehicles.LandVehicle>();

component.SetGUID(GUIDManager.GenerateUniqueGUID());
S1Vehicles.VehicleManager.Instance.AllVehicles.Add(component);

S1LandVehicle = component;
SetConnection();
}

/// <summary>
/// Vehicle price.
/// </summary>
public float VehiclePrice
{
get => S1LandVehicle.VehiclePrice;
set => VehiclePriceField?.SetValue(S1LandVehicle, value);
}

/// <summary>
/// Vehicle's top speed.
/// </summary>
public float TopSpeed
{
get => S1LandVehicle.TopSpeed;
set => S1LandVehicle.TopSpeed = value;
}

/// <summary>
/// If the vehicle is owned by the player.
/// </summary>
public bool IsPlayerOwned
{
get => S1LandVehicle.IsPlayerOwned;
set => SetIsPlayerOwned(value);
}

/// <summary>
/// Vehicle's color.
/// </summary>
public VehicleColor Color
{
get => (VehicleColor)S1LandVehicle.OwnedColor;
set => SetColor(value);
}

/// <summary>
/// Spawns the vehicle in the game world.
/// </summary>
/// <param name="position">Position in the world</param>
/// <param name="rotation">Rotation of the vehicle</param>
public void Spawn(Vector3 position, Quaternion rotation)
{
if (!InstanceFinder.IsServer)
{
_logger.Warning("Spawn can only be called on the server!");
return;
}

if (S1LandVehicle == null)
throw new Exception("Unable to spawn vehicle, S1LandVehicle is null!");

S1LandVehicle.transform.position = position;
S1LandVehicle.transform.rotation = rotation;
S1Vehicles.VehicleManager.Instance.Spawn(S1LandVehicle.gameObject);
}

#endregion

// Internal members used by S1API
#region Internal Members

/// <summary>
/// INTERNAL: The stored reference to the land vehicle in-game (see <see cref="S1Vehicles.LandVehicle"/>).
/// </summary>
internal S1Vehicles.LandVehicle S1LandVehicle = null!;

/// <summary>
/// INTERNAL: Creates a LandVehicle instance from an in-game land vehicle instance.
/// </summary>
/// <param name="landVehicle">The in-game land vehicle instance.</param>
internal LandVehicle(S1Vehicles.LandVehicle landVehicle)
{
S1LandVehicle = landVehicle;
SetConnection();
}

#endregion

// Private members used by LandVehicle class
#region Private Members

/// <summary>
/// Logger for the LandVehicle class.
/// </summary>
private static readonly Log _logger = new Log("S1API.LandVehicle");

/// <summary>
/// The stored reference to protected vehiclePrice field in the land vehicle in-game.
/// </summary>
private static readonly FieldInfo? VehiclePriceField =
typeof(S1Vehicles.LandVehicle).GetField("vehiclePrice", BindingFlags.NonPublic);

/// <summary>
/// Connection to the player that owns the vehicle.
/// </summary>
private NetworkConnection? _conn;

/// <summary>
/// Sets the connection to the player that owns the vehicle.
/// </summary>
private void SetConnection()
{
var nm = InstanceFinder.NetworkManager;
if (nm.IsClientOnly)
{
var tempConn = InstanceFinder.ClientManager.Connection;
if (tempConn != null && tempConn.IsValid)
_conn = tempConn;
}
else if (nm.IsServerOnly || (nm.IsServer && !nm.IsClient))
{
var owner = S1LandVehicle.Owner;
if (owner != null && owner.IsValid)
_conn = owner;
}
}

/// <summary>
/// Helper method to set the vehicle as player owned.
/// </summary>
/// <param name="isPlayerOwned">If true, sets vehicle as player owned</param>
private void SetIsPlayerOwned(bool isPlayerOwned)
{
S1LandVehicle.SetIsPlayerOwned(_conn, isPlayerOwned);
// make sure to add/remove the vehicle from the player owned vehicles list
if (isPlayerOwned)
S1Vehicles.VehicleManager.Instance.PlayerOwnedVehicles.Add(S1LandVehicle);
else
S1Vehicles.VehicleManager.Instance.PlayerOwnedVehicles.Remove(S1LandVehicle);
}

/// <summary>
/// Helper method to set the vehicle color.
/// </summary>
/// <param name="color">Vehicle's color</param>
private void SetColor(VehicleColor color)
{
var setOwnedColorMethod =
typeof(S1Vehicles.LandVehicle).GetMethod("SetOwnedColor",
BindingFlags.Instance | BindingFlags.NonPublic);
if (setOwnedColorMethod == null)
{
_logger.Error("SetOwnedColor method not found!");
return;
}

setOwnedColorMethod.Invoke(S1LandVehicle, [_conn, (S1Vehicles.Modification.EVehicleColor)color]);
}
#endregion
}
}
26 changes: 26 additions & 0 deletions S1API/Vehicles/VehicleColor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
namespace S1API.Vehicles
{
/// <summary>
/// Represents available colors for vehicles.
/// </summary>
public enum VehicleColor
{
Black,
DarkGrey,
LightGrey,
White,
Yellow,
Orange,
Red,
DullRed,
Pink,
Purple,
Navy,
DarkBlue,
LightBlue,
Cyan,
LightGreen,
DarkGreen,
Custom
}
}
Loading