C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
// Reference: 0Harmony
//None of this code is to be used in any paid projects/plugins
using Facepunch.Utility;
using Oxide.Core;
using ProtoBuf;
using Rust.Modular;
using System;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using Oxide.Core.Database;
using Rust;
using Oxide.Core.Plugins;
using System.Linq;
using Oxide.Game.Rust.Cui;
using HarmonyLib;
namespace Oxide.Plugins {
[Info("OpenNexus", "bmgjet", "1.0.0")]
[Description("Nexus system created by bmgjet")]
public class OpenNexus : RustPlugin {
private string thisserverip = "";
//Over-ride auto detected ip
private string thisserverport = "";
//Over-ride auto detected port
//Permissions
private readonly string permbypass = "OpenNexus.bypass";
//bypass the single server at a time limit
private readonly string permadmin = "OpenNexus.admin";
//Allows to use admin commands
//MySQL
Core.MySql.Libraries.MySql sqlLibrary = Interface.Oxide.GetLibrary<Core.MySql.Libraries.MySql>();
Core.Database.Connection sqlConnection;
//Memory
public List<IslandData> FoundIslands = new List<IslandData>();
public List<Vector3> HeliPads = new List<Vector3>();
private Dictionary<ulong, int> SeatPlayers = new Dictionary<ulong, int>();
private List<BaseNetworkable> unloadable = new List<BaseNetworkable>();
private List<ulong> ProcessingPlayers = new List<ulong>();
private List<ulong> MovePlayers = new List<ulong>();
private List<BasePlayer> JoinedViaNexus = new List<BasePlayer>();
private List<ModuleData> CarModules = new List<ModuleData>();
private List<CargoShip> ActiveCargoShips = new List<CargoShip>();
public static OpenNexus plugin;
private Climate climate;
//Plugin Hooks
[PluginReference]
private Plugin Backpacks, Economics, ZLevelsRemastered, ServerRewards;
private Harmony _harmony;
//Harmony Instance TFC:Changed to Harmony
#region Configuration
public ServerSettings _ServerSettings;
public class ServerSettings {
public string MapName = plugin.Config["MapName"].ToString();
public float ServerDelay = float.Parse(plugin.Config["ServerDelay"].ToString());
public string MySQLHost = plugin.Config["MySQLHost"].ToString();
public int MySQLPort = int.Parse(plugin.Config["MySQLPort"].ToString());
public string MySQLDB = plugin.Config["MySQLDB"].ToString();
public string MySQLUsername = plugin.Config["MySQLUsername"].ToString();
public string MySQLPassword = plugin.Config["MySQLPassword"].ToString();
public int ExtendFerryDistance = int.Parse(plugin.Config["ExtendFerryDistance"].ToString());
public bool AutoDistance = bool.Parse(plugin.Config["AutoDistance"].ToString());
public bool SyncTimeWeather = bool.Parse(plugin.Config["SyncTimeWeather"].ToString());
public int SyncTimeWeaterEvery = int.Parse(plugin.Config["SyncTimeWeaterEvery"].ToString());
public bool UseCompression = bool.Parse(plugin.Config["UseCompression"].ToString());
public bool ShowDebugMsg = bool.Parse(plugin.Config["ShowDebugMsg"].ToString());
public float MoveSpeed = float.Parse(plugin.Config["MoveSpeed"].ToString());
public float TurnSpeed = float.Parse(plugin.Config["TurnSpeed"].ToString());
public float WaitTime = float.Parse(plugin.Config["WaitTime"].ToString());
public float EjectDelay = float.Parse(plugin.Config["EjectDelay"].ToString());
public int TransfereTime = int.Parse(plugin.Config["TransfereTime"].ToString());
public int TransfereSyncTime = int.Parse(plugin.Config["TransfereSyncTime"].ToString());
public int ProgressDelay = int.Parse(plugin.Config["ProgressDelay"].ToString());
public int RedirectDelay = int.Parse(plugin.Config["RedirectDelay"].ToString());
public int CargoDistance = int.Parse(plugin.Config["CargoDistance"].ToString());
public bool StatusMsg = bool.Parse(plugin.Config["StatusMsg"].ToString());
public int MSGDistance = int.Parse(plugin.Config["MSGDistance"].ToString());
public int FontSize = int.Parse(plugin.Config["FontSize"].ToString());
public string FontColour = plugin.Config["FontColour"].ToString();
public int FontFadeIn = int.Parse(plugin.Config["FontFadeIn"].ToString());
public string AnchorMin = plugin.Config["AnchorMin"].ToString();
public string AnchorMax = plugin.Config["AnchorMax"].ToString();
public string FailedMSG = plugin.Config["FailedMSG"].ToString();
public string WaitingMSG = plugin.Config["WaitingMSG"].ToString();
public string CastoffMSG = plugin.Config["CastoffMSG"].ToString();
public string ArriveMSG = plugin.Config["ArriveMSG"].ToString();
public bool BackPacks = bool.Parse(plugin.Config["BackPacks"].ToString());
public bool Economics = bool.Parse(plugin.Config["Economics"].ToString());
public bool ZLevelsRemastered = bool.Parse(plugin.Config["ZLevelsRemastered"].ToString());
public bool ServerRewards = bool.Parse(plugin.Config["ServerRewards"].ToString());
public bool BluePrints = bool.Parse(plugin.Config["BluePrints"].ToString());
public bool Modifiers = bool.Parse(plugin.Config["Modifiers"].ToString());
public bool Parented = bool.Parse(plugin.Config["Parented"].ToString());
}
protected override void LoadDefaultConfig() {
Puts("Creating a new configuration file");
Config["MapName"] = "";
Config["ServerDelay"] = 1;
Config["MySQLHost"] = "localhost";
Config["MySQLPort"] = 3306;
Config["MySQLDB"] = "opennexus";
Config["MySQLUsername"] = "OpenNexus";
Config["MySQLPassword"] = "1234";
Config["ExtendFerryDistance"] = 0;
Config["AutoDistance"] = true;
Config["SyncTimeWeather"] = true;
Config["SyncTimeWeaterEvery"] = 300;
Config["UseCompression"] = true;
Config["ShowDebugMsg"] = false;
Config["MoveSpeed"] = 5;
Config["TurnSpeed"] = 0.6f;
Config["WaitTime"] = 60;
Config["EjectDelay"] = 60;
Config["TransfereTime"] = 60;
Config["TransfereSyncTime"] = 60;
Config["ProgressDelay"] = 60;
Config["RedirectDelay"] = 5;
Config["CargoDistance"] = 1000;
Config["StatusMsg"] = true;
Config["MSGDistance"] = 60;
Config["FontSize"] = 32;
Config["FontColour"] = "0.1 0.4 0.1 0.7";
Config["FontFadeIn"] = 3;
Config["AnchorMin"] = "0.100 0.800";
Config["AnchorMax"] = "0.900 0.900";
Config["FailedMSG"] = "Other Servers Failed To Reach Transfere Point In Time";
Config["WaitingMSG"] = "Waiting For Other Server";
Config["CastoffMSG"] = "Ferry Casting Off In <$T> Seconds";
Config["ArriveMSG"] = "You Have Arrived At The Next Server";
Config["BackPacks"] = true;
Config["Economics"] = true;
Config["ZLevelsRemastered"] = true;
Config["ServerRewards"] = true;
Config["BluePrints"] = true;
Config["Modifiers"] = true;
Config["Parented"] = true;
}
#endregion
#region Harmony
[HarmonyPatch(typeof(World), "GetServerBrowserMapName")]
//Called on ServerInformation
internal class World_GetServerBrowserMapName {
[HarmonyPrefix]
static bool Prefix(ref string __result) {
if (string.IsNullOrEmpty(plugin._ServerSettings.MapName)) //Check if startup arg set
{
return true;
//Not set so run normally
}
__result = plugin._ServerSettings.MapName;
//Override result of orignal method
return false;
//Block orignal method
}
}
#endregion
#region Commands
//Chat command to paste where admin is a transfered packet
//Command /OpenNexus.Paste $PacketID
[ChatCommand("OpenNexus.Paste")]
private void cmdPaste(BasePlayer player, string command, string[] args) {
if (!HasPermission(player, permadmin)) {
player.ChatMessage("You dont have OpenNexus.admin Perm!");
return;
}
if (args.Length != 1) {
player.ChatMessage("You must provide packet id!");
return;
}
int packetid = int.Parse(args[0]);
player.ChatMessage("Pasting Packet " + args[0]);
//Do Read Of Packet
MySQLRead("", null, packetid, player);
}
//Clears all the MySQL tables and sets back to default.[ConsoleCommand("OpenNexus.resettables")]
private void cmdReset(ConsoleSystem.Arg arg) {
//Resets database tables
if (!arg.IsAdmin) {
Puts("You dont have OpenNexus.admin Perm!");
return;
}
string sqlQuery = "DROP TABLE IF EXISTS players, packets, sync;";
Sql deleteCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery);
sqlLibrary.ExecuteNonQuery(deleteCommand, sqlConnection);
if (bool.Parse(Config["ShowDebugMsg"].ToString())) Puts("cmdReset Dropped all tables");
timer.Once(_ServerSettings.ServerDelay, () => {
CreatesTables();
//Reset players data
timer.Once(_ServerSettings.ServerDelay, () => {
foreach (BasePlayer bp in BasePlayer.activePlayerList) {
if (bp.IsConnected && !bp.IsNpc) {
NextTick(() => {
UpdatePlayers(thisserverip + ":" + thisserverport, thisserverip + ":" + thisserverport, "Playing", bp.UserIDString);
}
);
}
}
}
);
}
);
}
//Reloads the config with out having to restart, Not all changes will take effect
[ConsoleCommand("OpenNexus.reloadconfig")]
private void cmdReload(ConsoleSystem.Arg arg) {
if (!arg.IsAdmin) {
Puts("You dont have OpenNexus.admin Perm!");
return;
}
ServerSettings oldconfig = _ServerSettings;
_ServerSettings = Config.ReadObject<ServerSettings>();
if (oldconfig != _ServerSettings) {
Puts("Loaded changes, Not all settings will take effect with out a restart of plugin.");
Puts("You can restart plugin with /oxide.reload OpenNexus");
}
}
//toggle debug information
[ChatCommand("OpenNexus.debug")]
private void cmddebug(BasePlayer player, string command, string[] args) {
if (!HasPermission(player, permadmin)) {
player.ChatMessage("You dont have OpenNexus.admin Perm!");
return;
}
if (_ServerSettings.ShowDebugMsg) {
_ServerSettings.ShowDebugMsg = false;
player.ChatMessage("Debug messages disabled.");
}
else {
_ServerSettings.ShowDebugMsg = true;
player.ChatMessage("Debug messages enabled.");
}
Config.Save();
}
#endregion
#region MySQL
//Read data from mysql database
private void MySQLRead(string Target, OpenNexusFerry OpenFerry, int findid = 0, BasePlayer player = null) {
string sqlQuery;
Sql selectCommand;
//If passed as admin command to read given packet
if (player != null) {
sqlQuery = "SELECT `id`, `spawned`,`data` FROM packets WHERE `id` = @0;";
selectCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, findid);
}
else {
//Read last transfered packet waiting for us
sqlQuery = "SELECT `id`, `spawned`,`data` FROM packets WHERE `target`= @0 AND `sender` = @1 ORDER BY id DESC LIMIT 10;";
selectCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, Target, OpenFerry.ServerIP + ":" + OpenFerry.ServerPort);
}
sqlLibrary.Query(selectCommand, sqlConnection, list => {
if (list == null) {
return;
}
foreach (Dictionary<string, object> entry in list) {
//Packet has already been spawned on server before so dont re-transfere
if (entry["spawned"].ToString() == "1" && findid == 0) {
continue;
}
//Process Packet
int id;
bool success = int.TryParse(entry["id"].ToString(), out id);
if (!success) {
continue;
}
string data = "";
if (_ServerSettings.UseCompression) {
data = Encoding.UTF8.GetString(Compression.Uncompress(Convert.FromBase64String(entry["data"].ToString())));
}
//compressed
else {
data = entry["data"].ToString();
}
//Admin command
if (player != null) {
ReadPacket(data, player, id);
return;
}
//Process mysql packet
ReadPacket(data, OpenFerry, id);
//Kill stray bots that might of followed players
List<BasePlayer> Bots = new List<BasePlayer>();
List<BasePlayer> KillBots = new List<BasePlayer>();
Vis.Entities<BasePlayer>(OpenFerry.transform.position + (OpenFerry.transform.rotation * Vector3.forward * 6), 14f, KillBots);
foreach (BasePlayer bp in KillBots) {
if (!Bots.Contains(bp) && !bp.IsNpc) {
Bots.Add(bp);
}
}
Vis.Entities<BasePlayer>(OpenFerry.transform.position + (OpenFerry.transform.rotation * Vector3.forward * -12), 14f, KillBots);
foreach (BasePlayer bp in KillBots) {
if (!Bots.Contains(bp) && !bp.IsNpc) {
Bots.Add(bp);
}
}
foreach (BasePlayer bot in Bots) {
if (!IsSteamId(bot.UserIDString)) {
bot.Kill();
}
}
if (_ServerSettings.ShowDebugMsg) plugin.Puts("Read " + String.Format("{0:0.##}", (double)(entry["data"].ToString().Length / 1024f)) + " Kb");
return;
}
return;
}
);
}
//Write data to mysql database
private void MySQLWrite(string target = "", string sender = "", string data = "", int id = 0, int spawned = 0) {
if (id != 0) {
//If ID is given then update this as being spawned
string sqlQuery = "UPDATE packets SET `spawned` = @1 WHERE `id` = @0;";
Sql updateCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, id, spawned);
sqlLibrary.Update(updateCommand, sqlConnection, rowsAffected => {
if (rowsAffected > 0) {
if (_ServerSettings.ShowDebugMsg) {
Puts("MySQLWrite Record Updated");
}
return;
}
else {
if (_ServerSettings.ShowDebugMsg) {
Puts("MySQLWrite Record Update Failed!");
}
return;
}
}
);
return;
}
//No ID given so create new
if (target != "" && sender != "" && data != "") {
string sqlQuery = "INSERT INTO packets (`spawned`, `timestamp`, `target`,`sender`,`data`) VALUES (@0, @1, @2, @3, @4);";
Sql insertCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, spawned, DateTime.Now.ToString("t"), target, sender, data);
sqlLibrary.Insert(insertCommand, sqlConnection, rowsAffected => {
if (rowsAffected > 0) {
if (_ServerSettings.ShowDebugMsg) {
Puts("MySQLWrite New record inserted with ID: {0}", sqlConnection.LastInsertRowId);
}
return;
}
else {
if (_ServerSettings.ShowDebugMsg) {
Puts("MySQLWrite Failed to insert!");
}
return;
}
}
);
}
}
//Maintains table of each ferrys status
private void UpdateSync(string fromaddress, string target, string state) {
//try Update
string sqlQuery = "UPDATE sync SET `state` = @0, `climate` = @3 WHERE `sender` = @1 AND `target` = @2;";
Sql updateCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, state, fromaddress, target, plugin.getclimate());
;
sqlLibrary.Update(updateCommand, sqlConnection, rowsAffected => {
if (rowsAffected > 0) {
if (_ServerSettings.ShowDebugMsg) {
Puts("UpdateSync Record Updated");
}
return;
}
//Update failed so do insert
sqlQuery = "INSERT INTO sync (`state`, `sender`, `target`, `climate`) VALUES (@0, @1, @2, @3);";
Sql insertCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, state, fromaddress, target, plugin.getclimate());
sqlLibrary.Insert(insertCommand, sqlConnection, rowsAffectedwrite => {
if (rowsAffectedwrite > 0) {
if (_ServerSettings.ShowDebugMsg) {
Puts("UpdateSync New Record inserted with ID: {0}", sqlConnection.LastInsertRowId);
}
}
}
);
}
);
}
//Checks the state of players
private void ReadPlayers(string Target, ulong steamid, Network.Connection connection) {
string sqlQuery = "SELECT `state`, `target`, `sender` FROM players WHERE `steamid` = @0;";
Sql selectCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, steamid.ToString());
sqlLibrary.Query(selectCommand, sqlConnection, list => {
if (list == null) {
//creates new player data
if (_ServerSettings.ShowDebugMsg) {
Puts("ReadPlayers No Player Data For " + steamid.ToString() + " Creating It");
}
UpdatePlayers(Target, Target, "Playing", steamid.ToString());
return;
}
foreach (Dictionary<string, object> entry in list) {
//Redirect player to last server they were in.if (entry["target"].ToString() != thisserverip + ":" + thisserverport && entry["state"].ToString() != "Moving" && entry["state"].ToString() != "Ready" && connection != null)
{
if (BasePlayer.FindByID(connection.ownerid).IPlayer.HasPermission(permbypass)) {
return;
}
string[] server = entry["target"].ToString().Split(':');
if (_ServerSettings.ShowDebugMsg) Puts("ReadPlayers Redirecting " + steamid);
ConsoleNetwork.SendClientCommand(connection, "nexus.redirect", new object[] {
server[0], server[1], ""
}
);
return;
}
//Waits for player moving
if (entry["state"].ToString() == "Moving") {
if (_ServerSettings.ShowDebugMsg) {
Puts("ReadPlayers Waiting for server to set player as ready " + steamid);
}
return;
}
//Sets flag to move player
if (entry["state"].ToString() == "Ready") {
if (_ServerSettings.ShowDebugMsg) {
Puts("ReadPlayers Player Ready to move " + steamid);
}
MovePlayers.Add(ulong.Parse(steamid.ToString()));
//Sets flag back to playing
UpdatePlayers(Target, Target, "Playing", steamid.ToString());
return;
}
return;
}
//Creates new player data
if (_ServerSettings.ShowDebugMsg) {
Puts("No Player Data For " + steamid + " Creating It");
}
UpdatePlayers(Target, Target, "Playing", steamid.ToString());
}
);
}
//Updates players table
private void UpdatePlayers(string fromaddress, string target, string state, string steamid) {
//trys to update
string sqlQuery = "UPDATE players SET `state` = @0, `target` = @1, `sender` = @2 WHERE `steamid` = @3;";
Sql updateCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, state, target, fromaddress, steamid);
sqlLibrary.Update(updateCommand, sqlConnection, rowsAffected => {
if (rowsAffected > 0) {
if (_ServerSettings.ShowDebugMsg) {
Puts("UpdatePlayers Record Updated");
}
return;
}
//Failed to update so create new
sqlQuery = "INSERT INTO players (`state`, `target`, `sender`,`steamid`) VALUES (@0, @1, @2, @3);";
Sql insertCommand = Oxide.Core.Database.Sql.Builder.Append(sqlQuery, state, target, fromaddress, steamid);
sqlLibrary.Insert(insertCommand, sqlConnection, rowsAffectedInsert => {
if (rowsAffectedInsert > 0) {
if (_ServerSettings.ShowDebugMsg) {
Puts("UpdatePlayers New Record inserted with ID: {0}", sqlConnection.LastInsertRowId);
}
}
}
);
}
);
}
//Connect to mysql database
private void ConnectToMysql(string host, int port, string database, string username, string password) {
sqlConnection = sqlLibrary.OpenDb(host, port, database, username, password, this);
// Failed message
if (sqlConnection == null || sqlConnection.Con == null) {
Puts("Couldn't open the MySQL Database: {0} ", sqlConnection.Con.State.ToString());
}
else {
Puts("MySQL server connected: " + host);
CreatesTables();
}
}
private void CreatesTables() {
//Setup tables if they dont exsist
sqlLibrary.Insert(Core.Database.Sql.Builder.Append("CREATE TABLE IF NOT EXISTS `packets` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT, `spawned` int(1) NOT NULL,`timestamp` varchar(64) NOT NULL,`target` varchar(21),`sender` varchar(21),`data` mediumtext, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;"), sqlConnection);
sqlLibrary.Insert(Core.Database.Sql.Builder.Append("CREATE TABLE IF NOT EXISTS `sync` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`sender` varchar(21),`target` varchar(21),`state` varchar(21),`climate` text, PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;"), sqlConnection);
sqlLibrary.Insert(Core.Database.Sql.Builder.Append("CREATE TABLE IF NOT EXISTS `players` (`id` int(11) unsigned NOT NULL AUTO_INCREMENT,`sender` varchar(21),`target` varchar(21),`state` varchar(21),`steamid` varchar(21), PRIMARY KEY (`id`)) DEFAULT CHARSET=utf8;"), sqlConnection);
}
#endregion
#region Oxidehooks
private void Init() {
//Set up permissions
permission.RegisterPermission(permadmin, this);
permission.RegisterPermission(permbypass, this);
plugin = this;
_ServerSettings = new ServerSettings();
//Patch in harmony
_harmony = new HarmonyLib.Harmony(Name + "PATCH");
//_harmony = HarmonyLoader.TryLoadMod(Name + "PATCH");
Type[] patchType = {
AccessTools.Inner(typeof(OpenNexus), "World_GetServerBrowserMapName"),
}
;
// foreach (var t in patchType) { new PatchProcessor(_harmony, t, HarmonyMethod.Merge(t.GetHarmonyMethods())).Patch(); }
}
private void OnServerInitialized(bool initial) {
//Connect to database
ConnectToMysql(_ServerSettings.MySQLHost, _ServerSettings.MySQLPort, _ServerSettings.MySQLDB, _ServerSettings.MySQLUsername, _ServerSettings.MySQLPassword);
//Get Weather data
climate = SingletonComponent<Climate>.Instance;
//Sync weather repeat timer
if (_ServerSettings.SyncTimeWeather) {
timer.Every(_ServerSettings.SyncTimeWeaterEvery, () => setclimate());
}
//Determing if need wait for first startup
if (initial) {
Fstartup();
}
else {
Startup();
}
}
private void OnEntitySpawned(BaseEntity baseEntity) {
//Keep track of cargo ship so they dont collide
if (baseEntity is CargoShip) {
ActiveCargoShips.Add(baseEntity as CargoShip);
}
}
//Remove cargoship from list when its leaving
private void OnCargoShipEgress(CargoShip cs) {
if (ActiveCargoShips.Contains(cs)) {
ActiveCargoShips.Remove(cs);
}
}
private void OnWorldPrefabSpawned(GameObject gameObject, string str) {
//Remove Uncoded NexusFerry / NexusIsland / FerryTerminal
BaseEntity component = gameObject.GetComponent<BaseEntity>();
if (component != null) {
if ((component.prefabID == 2508295857 || component.prefabID == 1924784290 || component.prefabID == 2795004596) && component.OwnerID == 0) {
component.Kill();
}
}
}
private void OnPlayerSetInfo(Network.Connection connection, string name, string value) {
//Limits player to 1 server at a time.if (ProcessingPlayers.Contains(connection.ownerid)) return;
ProcessingPlayers.Add(connection.ownerid);
timer.Once(10f, () => ProcessingPlayers.Remove(connection.ownerid));
if (_ServerSettings.ShowDebugMsg) Puts("Checking if " + connection.ownerid.ToString() + " is already on any OpenNexus servers");
ReadPlayers(thisserverip + ":" + thisserverport, connection.ownerid, connection);
}
private void OnPlayerSleepEnded(BasePlayer player) {
//Mount players that were mounted.if (SeatPlayers.ContainsKey(player.userID))
{
MountPlayer(player, SeatPlayers[player.userID]);
SeatPlayers.Remove(player.userID);
}
if (JoinedViaNexus.Contains(player)) {
DirectMessage(player, _ServerSettings.ArriveMSG);
JoinedViaNexus.Remove(player);
}
//Remove transfere protection
player.SetFlag(BaseEntity.Flags.Protected, false);
}
private object CanHelicopterTarget(PatrolHelicopterAI heli, BasePlayer player) {
return FerryProtection(player);
}
private object CanHelicopterStrafeTarget(PatrolHelicopterAI heli, BasePlayer player) {
return FerryProtection(player);
}
object OnEntityTakeDamage(BaseCombatEntity entity, HitInfo info) {
return FerryProtection(entity);
}
private void Unload() {
//Remove plugin created stuff.foreach (BaseNetworkable basenetworkable in unloadable)
{
//Ferry Terminal
if (basenetworkable.prefabID == 1924784290) {
basenetworkable.Kill();
}
//Destroy island
else if (basenetworkable.prefabID == 2795004596) {
basenetworkable.Kill();
}
//Distroy ferry
else if (basenetworkable.prefabID == 2508295857) {
//Eject any entitys on the ferry so they dont drop in water
OpenNexusFerry Ferry = basenetworkable as OpenNexusFerry;
if (Ferry != null) {
//Dissconnect database
if (sqlConnection != null && sqlConnection.Con != null) {
sqlLibrary.CloseDb(sqlConnection);
}
//Updates ferry contents list and ejects it to dock.Ferry.UpdateDockedEntitys();
EjectEntitys(Ferry.GetFerryContents(), Ferry.DockedEntitys, Ferry.EjectionZone.position);
//Destroys Transform objects
UnityEngine.Object.Destroy(Ferry.Arrival.gameObject);
UnityEngine.Object.Destroy(Ferry.CastingOff.gameObject);
UnityEngine.Object.Destroy(Ferry.Departure.gameObject);
UnityEngine.Object.Destroy(Ferry.Docked.gameObject);
UnityEngine.Object.Destroy(Ferry.Docking.gameObject);
UnityEngine.Object.Destroy(Ferry.EjectionZone.gameObject);
Ferry.Kill();
}
}
}
//Remove CUI messaghes
foreach (BasePlayer player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, "FerryInfo");
}
_harmony.UnpatchAll(Name + "PATCH");
//Unpatch harmony
plugin = null;
}
#endregion
#region Startup
private void Fstartup() {
//Waits for fully loaded before running
timer.Once(10f, () => {
//Still starting so run a timer again in 10 sec to check.try { if (Rust.Application.isLoading) { Fstartup(); return; } } catch { }
//Starup script now.Startup();
}
);
}
//Set IP and port of ferry from prefab name
private void SetFerryIPs(OpenNexusFerry OpenFerry, string[] FerrySettings) {
foreach (string setting in FerrySettings) {
string[] tempsetting = setting.Split(':');
foreach (string finalsetting in tempsetting) {
string settingparsed = finalsetting.ToLower().Replace(":", "");
if (settingparsed.Contains("server=")) {
OpenFerry.ServerIP = settingparsed.Replace("server=", "");
}
else if (settingparsed.Contains("port=")) {
OpenFerry.ServerPort = settingparsed.Replace("port=", "");
}
}
}
}
private void Startup() {
//Check avaliable plugins that are supported
if (Backpacks == null) {
Puts("Backpacks plugin supported https://github.com/LaserHydra/Backpacks");
}
if (Economics == null) {
Puts("Economics supported https://umod.org/plugins/economics");
}
if (ZLevelsRemastered == null) {
Puts("ZLevels Remastered supported https://umod.org/plugins/zlevels-remastered");
}
if (ServerRewards == null) {
Puts("ServerRewards supported https://umod.org/plugins/server-rewards");
}
//Find this servers IP and Port if not manually set
if (thisserverip == "") thisserverip = covalence.Server.Address.ToString();
if (thisserverport == "") thisserverport = covalence.Server.Port.ToString();
Quaternion rotation;
Vector3 position;
//Scan map prefabs
foreach (PrefabData prefabdata in World.Serialization.world.prefabs) {
switch(prefabdata.id) {
case 14651698 : //Heli pad
if (prefabdata.category.ToLower().Contains("opennexus")) {
HeliPads.Add(prefabdata.position);
}
break;
case 1427415412 : //Search Lights
if (prefabdata.category.ToLower().Contains("opennexus")) {
}
break;
case 1924784290 : //Dock terminal
if (prefabdata.category.ToLower().Contains("opennexus")) {
NexusDockTerminal terminal = GameManager.server.CreateEntity(StringPool.Get(1924784290), prefabdata.position, prefabdata.rotation) as NexusDockTerminal;
if (terminal == null) continue;
NextFrame(() => {
terminal.CancelInvoke("UpdateFerrySchedule");
}
);
}
break;
case 2508295857 : //Nexus ferry
//Read settings from prefab name
string[] FerrySettings = prefabdata.category.Replace(@"\", "").Split(',');
if (FerrySettings == null || FerrySettings.Length < 3) {
Debug.LogError("OpenNexus ferry not setup properly");
continue;
}
//Create rotation/position data
rotation = Quaternion.Euler(new Vector3(prefabdata.rotation.x, prefabdata.rotation.y, prefabdata.rotation.z));
position = new Vector3(prefabdata.position.x, prefabdata.position.y, prefabdata.position.z);
//Create New Ferry
NexusFerry ferry = GameManager.server.CreateEntity(StringPool.Get(2508295857), position, rotation) as NexusFerry;
if (ferry == null) continue;
//Attach open nexus code
OpenNexusFerry OpenFerry = ferry.gameObject.AddComponent<OpenNexusFerry>();
if (OpenFerry == null) continue;
unloadable.Add(OpenFerry);
//Setup with setting in dock prefab name
SetFerryIPs(OpenFerry, FerrySettings);
//Finish creating OpenNexus Ferrys
OpenFerry.prefabID = ferry.prefabID;
OpenFerry.syncPosition = true;
OpenFerry.globalBroadcast = true;
UnityEngine.Object.DestroyImmediate(ferry);
OpenFerry.enableSaving = false;
OpenFerry.Spawn();
break;
case 2795004596 : //NexusIslands
//Create rotation/position data
rotation = Quaternion.Euler(new Vector3(prefabdata.rotation.x, prefabdata.rotation.y, prefabdata.rotation.z));
position = new Vector3(prefabdata.position.x, prefabdata.position.y, prefabdata.position.z);
NexusIsland island = GameManager.server.CreateEntity(StringPool.Get(2795004596), position, rotation) as NexusIsland;
if (island == null) continue;
OpenNexusIsland openNexusIsland = island.gameObject.AddComponent<OpenNexusIsland>();
unloadable.Add(openNexusIsland);
openNexusIsland.prefabID = island.prefabID;
openNexusIsland.syncPosition = true;
openNexusIsland.globalBroadcast = true;
UnityEngine.Object.DestroyImmediate(island);
openNexusIsland.enableSaving = false;
openNexusIsland.Spawn();
IslandData id = new IslandData();
id.Island = openNexusIsland;
id.location = position;
id.rotation = rotation;
FoundIslands.Add(id);
Puts("Found Island @ " + position.ToString());
break;
}
}
//Remove dead Ferry turrets at junk collection (happens on reboots might shoot though low ground maps)
List<NPCAutoTurret> Z = new List<NPCAutoTurret>();
Vis.Entities<NPCAutoTurret>(Vector3.zero, 25f, Z);
foreach (NPCAutoTurret ss in Z) {
ss.Kill();
}
}
#endregion
#region functions
private Vector3 StringToVector3(string sVector) {
if (sVector.StartsWith("(") && sVector.EndsWith(")")) {
sVector = sVector.Substring(1, sVector.Length - 2);
}
string[] sArray = sVector.Split(',');
Vector3 result = new Vector3(float.Parse(sArray[0]), float.Parse(sArray[1]), float.Parse(sArray[2]));
return result;
}
private Quaternion StringToQuaternion(string sVector) {
if (sVector.StartsWith("(") && sVector.EndsWith(")")) {
sVector = sVector.Substring(1, sVector.Length - 2);
}
string[] sArray = sVector.Split(',');
Quaternion result = new Quaternion(float.Parse(sArray[0]), float.Parse(sArray[1]), float.Parse(sArray[2]), float.Parse(sArray[3]));
return result;
}
private void StartSleeping(BasePlayer player) {
if (!player.IsSleeping()) {
Interface.CallHook("OnPlayerSleep", player);
player.SetPlayerFlag(BasePlayer.PlayerFlags.Sleeping, true);
player.sleepStartTime = Time.time;
BasePlayer.sleepingPlayerList.Add(player);
player.CancelInvoke("InventoryUpdate");
player.CancelInvoke("TeamUpdate");
player.SendNetworkUpdateImmediate();
}
}
private bool HasPermission(BasePlayer player, string perm) => permission.UserHasPermission(player.UserIDString, perm);
private bool IsSteamId(string id) {
ulong userId;
if (!ulong.TryParse(id, out userId)) {
return false;
}
return userId > 76561197960265728L;
}
private void DestroyMeshCollider(BaseEntity ent) {
foreach (var mesh in ent.GetComponentsInChildren<MeshCollider>()) {
UnityEngine.Object.DestroyImmediate(mesh);
}
}
private void DestroyGroundComp(BaseEntity ent) {
foreach (var groundmissing in ent.GetComponentsInChildren<DestroyOnGroundMissing>().ToArray()) {
UnityEngine.Object.DestroyImmediate(groundmissing);
}
foreach (var groundwatch in ent.GetComponentsInChildren<GroundWatch>().ToArray()) {
UnityEngine.Object.DestroyImmediate(groundwatch);
}
}
private object FerryProtection(BaseEntity be) {
BaseEntity Ferry = be.GetParentEntity();
if (Ferry != null && Ferry is OpenNexusFerry) {
return false;
}
return null;
}
private void MessageScreen(string msg, Vector3 pos, float radius, int delay = 8) {
if (_ServerSettings.StatusMsg == false) {
return;
}
foreach (BasePlayer player in BasePlayer.activePlayerList) {
if (player.Distance(pos) < _ServerSettings.MSGDistance) {
if (!player.IsSleeping()) {
DirectMessage(player, msg, delay);
}
}
}
List<BasePlayer> PlayersInRange = new List<BasePlayer>();
//Scans area for players
Vis.Entities<BasePlayer>(pos, radius, PlayersInRange);
//Shows CUI to each player in range
if (PlayersInRange.Count != 0) {
foreach (BasePlayer player in PlayersInRange.ToArray()) {
if (!player.IsSleeping()) {
DirectMessage(player, msg, delay);
}
}
}
}
private void DirectMessage(BasePlayer player, string msg, int delay = 8) {
CuiHelper.DestroyUi(player, "FerryInfo");
var elements = new CuiElementContainer();
elements.Add(new CuiLabel {
Text = {
Text = msg, FontSize = _ServerSettings.FontSize, Align = TextAnchor.MiddleCenter, FadeIn = _ServerSettings.FontFadeIn, Color = _ServerSettings.FontColour
}
, RectTransform = {
AnchorMin = _ServerSettings.AnchorMin, AnchorMax = _ServerSettings.AnchorMax
}
}
, "Overlay", "FerryInfo");
CuiHelper.AddUi(player, elements);
//Destroys message after delay
timer.Once(delay, () => {
CuiHelper.DestroyUi(player, "FerryInfo");
}
);
}
private void AddLock(BaseEntity ent, string data) {
//Recreates codelocks
string[] codedata = data.Split(new string[] {
"<CodeLock>"
}
, System.StringSplitOptions.RemoveEmptyEntries);
string[] wlp = codedata[4].Split(new string[] {
"<player>"
}
, System.StringSplitOptions.RemoveEmptyEntries);
CodeLock alock = GameManager.server.CreateEntity("assets/prefabs/locks/keypad/lock.code.prefab") as CodeLock;
alock.Spawn();
foreach (string wl in wlp) {
alock.whitelistPlayers.Add(ulong.Parse(wl));
}
try {
alock.OwnerID = alock.whitelistPlayers[0];
}
catch {
}
alock.code = codedata[2];
alock.SetParent(ent, ent.GetSlotAnchorName(BaseEntity.Slot.Lock));
alock.transform.localPosition = StringToVector3(codedata[0]);
alock.transform.localRotation = StringToQuaternion(codedata[1]);
ent.SetSlot(BaseEntity.Slot.Lock, alock);
alock.SetFlag(BaseEntity.Flags.Locked, bool.Parse(codedata[3]));
alock.enableSaving = true;
alock.SendNetworkUpdateImmediate(true);
}
private void MountPlayer(BasePlayer player, int seatnum) {
//Try mount seat given in setting
List<BaseVehicle> bv = new List<BaseVehicle>();
Vis.Entities<BaseVehicle>(player.transform.position, 1f, bv);
try {
foreach (BaseVehicle seat in bv) {
if (!seat.GetMountPoint(seatnum).mountable.HasValidDismountPosition(player)) {
player.Teleport(player.transform.position += new Vector3(0, 3, 0));
return;
}
seat.GetMountPoint(seatnum).mountable.MountPlayer(player);
return;
}
}
catch {
}
//Fall back to find nearest seat and mount
List<BaseMountable> Seats = new List<BaseMountable>();
Vis.Entities<BaseMountable>(player.transform.position, 0.5f, Seats);
BaseMountable closest_seat = null;
foreach (BaseMountable seat in Seats) {
if (seat.HasFlag(BaseEntity.Flags.Busy)) continue;
if (closest_seat == null) closest_seat = seat;
if (Vector3.Distance(player.transform.position, seat.transform.position) <= Vector3.Distance(player.transform.position, closest_seat.transform.position)) closest_seat = seat;
}
//Trys to mount seat
if (closest_seat != null) {
BaseMountable seat = closest_seat.GetComponent<BaseMountable>();
if (seat == null || !seat.HasValidDismountPosition(player)) {
player.Teleport(player.transform.position += new Vector3(0, 3, 0));
return;
}
seat.MountPlayer(player);
closest_seat.SendNetworkUpdateImmediate();
player.SendNetworkUpdateImmediate();
}
}
private bool TryFindEjectionPosition(out Vector3 position, Vector3 spawnpos, float radius = 1f) {
//try 100 times or drop on center
Vector3 position2;
Vector3 position3;
for (int i = 0; i < 100; i++) {
position2 = new Vector3(Core.Random.Range(spawnpos.x - 8f, spawnpos.x + 8f), spawnpos.y + 2.5f, Core.Random.Range(spawnpos.z - 8f, spawnpos.z + 8f));
if (!TransformUtil.GetGroundInfo(position2, out position2, out position3, 10, 413204481, null)) {
position = spawnpos + new Vector3(0, 5, 0);
return false;
}
if (GamePhysics.CheckSphere(position2, radius, Layers.Mask.Construction | Layers.Server.Deployed | Layers.World | Layers.Server.Players | Layers.Mask.Vehicle_World | Layers.Server.VehiclesSimple | Layers.Server.NPCs, QueryTriggerInteraction.Ignore)) {
continue;
}
position = position2;
return true;
}
position = spawnpos + new Vector3(0, 5, 0);
return false;
}
private void EjectEntitys(List<BaseNetworkable> currentcontents, List<BaseNetworkable> Do
// ... [Code preview truncated due to length. Full source in attached file] ...