C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using UnityEngine;
using Oxide.Plugins.TrainHomesExtensionMethods;
using Facepunch;
using System.Reflection;
using Newtonsoft.Json;
using Oxide.Core;
using System.Threading.Tasks;
using Oxide.Core.Plugins;
using Network;
using System.Collections;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Libraries;
namespace Oxide.Plugins {
[Info("TrainHomes", "jtedal", "1.1.0")]
class TrainHomes : RustPlugin {
private const bool En = false;
#region Config
private PluginConfig _config;
protected override void LoadDefaultConfig() {
Puts("Creating a default config...");
_config = PluginConfig.DefaultConfig();
_config.PluginVersion = Version;
SaveConfig();
Puts("Creation of the default config completed!");
}
protected override void LoadConfig() {
base.LoadConfig();
_config = Config.ReadObject<PluginConfig>();
if (_config.PluginVersion < Version) {
UpdateConfigValues();
}
}
private void UpdateConfigValues() {
Puts("Config update detected! Updating config values...");
if (_config.PluginVersion < new VersionNumber(1, 0, 1)) {
_config.PermissionsForAmountWagons = new Dictionary<string, int>() {
["trainhomes.amount1"]
= 1, ["trainhomes.amount10"] = 10
}
;
}
if (_config.PluginVersion < new VersionNumber(1, 0, 5)) {
_config.CheckTopology = false;
}
if (_config.PluginVersion < new VersionNumber(1, 0, 7)) {
_config.Log = true;
}
_config.PluginVersion = Version;
Puts("Config update completed!");
SaveConfig();
}
protected override void SaveConfig() => Config.WriteObject(_config);
public class NotifyConfig {
[JsonProperty(En ? "Prefix" : "Префикс сообщений")]
public string prefix {
get;
set;
}
[JsonProperty(En ? "Chat Message setting" : "Настройки сообщений в чате")]
public ChatConfig chatConfig {
get;
set;
}
[JsonProperty(En ? "Facepunch Game Tips setting" : "Настройка сообщений Facepunch Game Tip")]
public GameTipConfig gameTipConfig {
get;
set;
}
[JsonProperty(En ? "GUI Announcements setting (only for GUIAnnouncements plugin)" : "Настройка GUI Announcements (только для тех, кто использует плагин GUI Announcements)")]
public GUIAnnouncementsConfig guiAnnouncementsConfig {
get;
set;
}
[JsonProperty(En ? "Notify setting (only for Notify plugin)" : "Настройка Notify (только для тех, кто использует плагин Notify)")]
public NotifyPluginConfig notifyPluginConfig {
get;
set;
}
[JsonProperty(En ? "Discord setting (only for DiscordMessages plugin)" : "Настройка оповещений в Discord (только для тех, кто использует плагин Discord Messages)")]
public DiscordMessagesConfig discordMessagesConfig {
get;
set;
}
}
public class ChatConfig {
[JsonProperty(En ? "Use chat notifications? [true/false]" : "Использовать ли чат? [true/false]")]
public bool isEnabled {
get;
set;
}
}
public class GameTipConfig {
[JsonProperty(En ? "Use Facepunch Game Tips (notification bar above hotbar)? [true/false]" : "Использовать ли Facepunch Game Tip (оповещения над слотами быстрого доступа игрока)? [true/false]")]
public bool isEnabled {
get;
set;
}
[JsonProperty(En ? "Style (0 - Blue Normal, 1 - Red Normal, 2 - Blue Long, 3 - Blue Short, 4 - Server Event)" : "Стиль (0 - Blue Normal, 1 - Red Normal, 2 - Blue Long, 3 - Blue Short, 4 - Server Event)")]
public int style {
get;
set;
}
}
public class GUIAnnouncementsConfig {
[JsonProperty(En ? "Do you use GUI Announcements integration? [true/false]" : "Использовать ли GUI Announcements? [true/false]")]
public bool isEnabled {
get;
set;
}
[JsonProperty(En ? "Banner color" : "Цвет баннера")]
public string bannerColor {
get;
set;
}
[JsonProperty(En ? "Text color" : "Цвет текста")]
public string textColor {
get;
set;
}
[JsonProperty(En ? "Adjust Vertical Position" : "Отступ от верхнего края")]
public float apiAdjustVPosition {
get;
set;
}
}
public class NotifyPluginConfig {
[JsonProperty(En ? "Do you use Notify integration? [true/false]" : "Использовать ли Notify? [true/false]")]
public bool isEnabled {
get;
set;
}
[JsonProperty(En ? "Type" : "Тип")]
public string type {
get;
set;
}
}
public class DiscordMessagesConfig {
[JsonProperty(En ? "Do you use DiscordMessages? [true/false]" : "Использовать ли DiscordMessages? [true/false]")]
public bool isEnabled {
get;
set;
}
[JsonProperty("Webhook URL")]
public string webhookUrl {
get;
set;
}
[JsonProperty(En ? "Embed Color (DECIMAL)" : "Цвет полосы (DECIMAL)")]
public int embedColor {
get;
set;
}
[JsonProperty(En ? "Keys of required messages" : "Ключи необходимых сообщений")]
public HashSet<string> keys {
get;
set;
}
}
public class AcceptableEntities {
[JsonProperty("ShortName")]
public string ShortName {
get;
set;
}
[JsonProperty(En ? "Allow this entity to be placed" : "Разрешить ставить этот предмет")]
public bool IsAllowPut {
get;
set;
}
[JsonProperty(En ? "The maximum amount that can be placed in one wagon (If previous parameter true)" : "Максимальное количество, которое можно ставить в одном вагоне (Если стоит true)")]
public int Amount {
get;
set;
}
}
public class PermissionsConfig {
[JsonProperty(En ? "Permission name (Example: trainhomes.name)" : "Название пермишена (Пример: trainhomes.name)")]
public string Name {
get;
set;
}
}
public class CrateConfig {
[JsonProperty("Prefab")]
public string Prefab {
get;
set;
}
[JsonProperty(En ? "Chance [0.0-100.0]" : "Шанс выпадения предмета [0.0-100.0]")]
public float Chance {
get;
set;
}
}
public class PluginConfig {
[JsonProperty(En ? "Record plugin logs" : "Записывать логи плагина")]
public bool Log {
get;
set;
}
[JsonProperty(En ? "Allow items to be placed on the roof of the wagon" : "Разрешить ставить предметы на крыше поезда")]
public bool IsAllowPutOnRoof {
get;
set;
}
[JsonProperty(En ? "Enable topology checking when a player calls a wagon onto the tracks" : "Включить проверку топологий, когда игрок вызывает вагон на рельсы")]
public bool CheckTopology {
get;
set;
}
[JsonProperty(En ? "The maximum distance at which a wagon can be moved" : "Максимальная дистанция при которой вагон может быть перемещен")]
public int MaxDistance {
get;
set;
}
[JsonProperty(En ? "HP of the wagon" : "HP вагона")]
public int HpWagon {
get;
set;
}
[JsonProperty(En ? "HP of the wagon stand" : "HP подставки")]
public int HpBarricade {
get;
set;
}
[JsonProperty(En ? "A constant amount of free wagons on the tracks" : "Постоянное количество бесплатных вагонов на рельсах")]
public int amountFreeWagons {
get;
set;
}
[JsonProperty(En ? "Wagon spawn settings in crates" : "Настройка появления вагона в ящиках")]
public HashSet<CrateConfig> Crates {
get;
set;
}
[JsonProperty(En ? "Whether to use permits for the number of wagons" : "Использовать ли пермишены на кол-во вагонов")]
public bool AmountWagons {
get;
set;
}
[JsonProperty(En ? "Permissions for amount wagons in using" : "Пермишены на кол-во вагонов для игрока")]
public Dictionary<string, int> PermissionsForAmountWagons {
get;
set;
}
[JsonProperty(En ? "List of entities" : "Список Entity")]
public HashSet<AcceptableEntities> AcceptableEntities {
get;
set;
}
[JsonProperty(En ? "Notification Settings" : "Настройки уведомлений")]
public NotifyConfig NotifyConfig {
get;
set;
}
[JsonProperty(En ? "Configuration Version" : "Версия конфигурации")]
public VersionNumber PluginVersion {
get;
set;
}
public static PluginConfig DefaultConfig() {
return new PluginConfig() {
Log = true, IsAllowPutOnRoof = true, CheckTopology = false, MaxDistance = 1500, HpWagon = 5000, HpBarricade = 1000, amountFreeWagons = 5, Crates = new HashSet<CrateConfig>() {
new CrateConfig {
Prefab = "assets/bundled/prefabs/radtown/crate_normal.prefab", Chance = 100f
}
, new CrateConfig {
Prefab = "assets/bundled/prefabs/radtown/crate_elite.prefab", Chance = 50f
}
}
, AmountWagons = false, PermissionsForAmountWagons = new Dictionary<string, int>() {
["trainhomes.amount1"]
= 1, ["trainhomes.amount10"] = 10
}
, AcceptableEntities = new HashSet<AcceptableEntities>() {
new AcceptableEntities {
ShortName = "box.wooden.large", IsAllowPut = true, Amount = 100
}
}
, NotifyConfig = new NotifyConfig {
prefix = "[TrainHomes]", chatConfig = new ChatConfig {
isEnabled = true,
}
, gameTipConfig = new GameTipConfig {
isEnabled = false, style = 2,
}
, guiAnnouncementsConfig = new GUIAnnouncementsConfig {
isEnabled = false, bannerColor = "Grey", textColor = "White", apiAdjustVPosition = 0.03f
}
, notifyPluginConfig = new NotifyPluginConfig {
isEnabled = false, type = "0"
}
, discordMessagesConfig = new DiscordMessagesConfig {
isEnabled = false, webhookUrl = "https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks", embedColor = 13516583, keys = new HashSet<string> {
"PreStart", "EventStart", "Finish"
}
}
}
, PluginVersion = new VersionNumber()
}
;
}
}
#endregion Config
#region Lang
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
["BaseHasntCupboard"]
= "{0} You can't do this because there is no cupboard.", ["NotAuthedInCupboard"] = "{0} You can't do this because you're not authorized in the cupboard.", ["NoNeedAmountBlocks"] = "{0} Your base must have at least 21 square foundations.(Details: /thinstruction)", ["NotValidPosForTrainCar"] = "{0} TrainCar cannot be spawned in this position.", ["CanntPutEntityOnRoof"] = "{0} You can't put objects on the roof.", ["CanntPutEntity"] = "{0} You can't put this object on the wagon.", ["SetMaxAmountObjects"] = "{0} You have set the maximum amount of these objects on the wagon.", ["LimitFloorsForHouse"] = "{0} Building blocks cannot be outside the wagon or above the 1st floor.", ["CodeOfTheWagon"] = "{0} Your code from the wagon [{1}].You can change these parameters.", ["FrequencyOfTheWagon"] = "{0} Your frequency from the wagon [{1}].You can change this parameter.", ["LongDistance"] = "{0} The distance from the wagon to the spawn point is too long.(Distance: {1}m, Maximum distance: {2}m)", ["TwoCallers"] = "{0} When calling a wagon, the detonator must be in the hand of only 1 player.", ["WagonAlreadyInGarage"] = "{0} The wagon is already in another base.", ["WagonAlreadyOnTracks"] = "{0} The wagon is already on tracks.", ["NotValidTopologies"] = "{0} There are no topologies for spawn in this position.Try to spawn the wagon in another position or contact the server owner.", ["TimerForSpawn"] = "{0} The wagon will spawn in {1}...", ["NotValidConstruction"] = "{0} Incorrect сonstruction for the wagon spawn.(Details: /thinstruction)", ["NotValidTarget"] = "{0} Incorrect сonstruction for the wagon spawn or cannot be spawned in this position.(Подробности: /thinstruction)", ["FoundationsExistInHashSet"] = "{0} You are trying to spawn the wagon in a place where there is already a position for the wagon.(Подробности: /thinstruction)", ["CommandForAdminsOnly"] = "{0} This command is for admins only.", ["RemoveTimeEnd"] = "{0} The time for removing the wagon is over.", ["CantCallAnotherWagon"] = "{0} Wait until the other wagon is spawned.", ["WagonAlreadyCalled"] = "{0} This wagon has already been called by another player.", ["WagonOnMonument"] = "{0} This wagon is located on the custom monument, in building mode.You can't move it.", ["ModeIsNotBuilding"] = "{0} Turn on the monument building mode using the button on the pillar.", ["NotOnBaseAndNotOnMonument"] = "{0} You can't build on a wagon not on base and not on a special custom monument.", ["MuchWagons"] = "{0} To enable building mode, there should not be more than 1 wagon inside the monument.", ["NotCustomWagon"] = "{0} To enable building mode, there should be a custom wagon inside the monument.", ["NotHaveWagons"] = "{0} To enable building mode, there should be a wagon inside the monument.", ["InvalidCmdChat1"] = "{0} You <color=#ce3f27>didn't</color> write amount and player's SteamID! \n/givewagon <amount> <SteamID>", ["InvalidCmdChat2"] = "{0} You <color=#ce3f27>didn't</color> write some player's SteamID! \n/givewagon <amount> <SteamID>", ["InvalidCmdChat3"] = "{0} Player with SteamID: {1} <color=#ce3f27>not found</color>!", ["ValidCmdChat"] = "{0} The wagon was successfully given to the player!", ["YouNotOwner"] = "{0} You can't do this because you are not the owner of the wagon!", ["CantBuildingOnFreeWagon"] = "{0} You can't build on the free wagon! Set the code for the codelock and try again.", ["NotHavePerm"] = "{0} You dont have permission to use this command.", ["NotHavePermForMoreWagons"] = "{0} You do not have perms to own a larger number of wagons.", ["GUI_General"] = "General", ["GUI_General_Description"] = "1) In the crates, you can find an item for the wagon spawn." + "\n2) On the railway tracks, occasionally, you can find an free wagon.To become its owner, enter any code." + "\n3) You can only place the wagon at your base.For details, see the section 'Construction'." + "\n4) You can build on a wagon only at your base or on a custom monument, if there is one.For more information, see the section 'Custom monument'." + "\n5) Any player can build on the wagon." + "\n6) There is no need to install a cupboard on the wagon, because the objects on it do not decay, as well as the wagon itself." + "\n7) To move the wagon from the base to the rails and back, you will need a detonator.Enter the frequency that is indicated on the wagon, stand in front of the place where you want to move it and press the button." + "\n8) All players who are authorized in the codelock have access to the wagon movement." + "\n9) Any player can change the frequency of the wagon." + "\n10) The owner of the wagon can remove his wagon and get a spawn item in return.Be careful! All objects on it will destroy, and resources will not be returned.(Command: /removewagon)", ["GUI_Construction"] = "Construction", ["GUI_Construction_Description"] = "1) The сonstruction must contain 7x3 foundations." + "\n2) To spawn the wagon, you must definitely put a cupboard." + "\n3) All foundations must be at the same height." + "\n4) If a cupboard, or one of the 21 foundations, or a stand breaks down on the сonstruction while the wagon is located, then the one will also be destroyed." + "\n5) To place a wagon, you must strictly specify the foundation that is the most central of the 21." + "\n6) The wagon must not be placed on foundations other than those.", ["GUI_CustomMonument"] = "Custom Monument", ["GUI_CustomMonument_Description"] = "1) You will not be able to build anything on the wagon until you activate the building mode." + "\n2) The construction mode is activated by pressing a button on one of the pillars." + "\n3) After pressing the button, the wagon will automatically reach the desired position if it is not entirely located in the construction area." + "\n4) Be careful! During the building mode, any player will be able to build anything on your wagon." + "\n5) To exit the building mode, press the button again.",
}
, this);
lang.RegisterMessages(new Dictionary<string, string> {
["BaseHasntCupboard"]
= "{0} Вы не можете это сделать, потому что нет шкафа.", ["NotAuthedInCupboard"] = "{0} Вы не можете это сделать, потому что не авторизованы в шкафу.", ["NoNeedAmountBlocks"] = "{0} У вашей постройки должно быть минимум 21 квадратных фундаментов.(Подробности: /thinstruction)", ["NotValidPosForTrainCar"] = "{0} В этой позиции нельзя заспавнить вагон.", ["CanntPutEntityOnRoof"] = "{0} Нельзя ставить объекты на крыше.", ["CanntPutEntity"] = "{0} Нельзя ставить этот объект на поезде.", ["SetMaxAmountObjects"] = "{0} Вы установили максимальное количество этих объектов на вагоне.", ["LimitFloorsForHouse"] = "{0} Строительные блоки не могут выходить за пределы одноэтажной конструкции.", ["CodeOfTheWagon"] = "{0} Ваш код от вагона [{1}].Вы можете изменить этот параметр.", ["FrequencyOfTheWagon"] = "{0} Ваша частота от вагона [{1}].Вы можете изменить этот параметр.", ["LongDistance"] = "{0} Дистанция от вагона до точки спавна слишком большая.(Дистанция: {1}м, Максимальная дистанция: {2}м)", ["TwoCallers"] = "{0} При вызове вагона, детонатор должен быть в руке только 1 игрока.", ["WagonAlreadyInGarage"] = "{0} Вагон уже находится на другой базе.", ["WagonAlreadyOnTracks"] = "{0} Вагон уже находится на рельсах.", ["NotValidTopologies"] = "{0} В этой позиции нет топологий для спавна.Попробуйте заспавнить вагон в другом месте или обратитесь к владельцу сервера.", ["TimerForSpawn"] = "{0} Вагон появится через {1}...", ["NotValidConstruction"] = "{0} Неправильная конструкция для спавна вагона.(Подробности: /thinstruction)", ["NotValidTarget"] = "{0} Неправильная конструкция или позиция для спавна вагона.(Подробности: /thinstruction)", ["FoundationsExistInHashSet"] = "{0} Вы пытаетесь заспавнить вагон в том месте, где уже есть позиция для вагона.(Подробности: /thinstruction)", ["CommandForAdminsOnly"] = "{0} Эта команда только для админов.", ["RemoveTimeEnd"] = "{0} Время для удаления вагона истекло.", ["CantCallAnotherWagon"] = "{0} Дождитесь пока другой вагон будет заспавнен.", ["WagonAlreadyCalled"] = "{0} Этот вагон уже вызвал другой игрок.", ["WagonOnMonument"] = "{0} Этот вагон находится на монументе, в режиме строитедства.Вы не можете его перемещать.", ["ModeIsNotBuilding"] = "{0} Включите режим строителтсва на монументе через кнопку на столбе.", ["NotOnBaseAndNotOnMonument"] = "{0} Вы не можете строить на вагоне не дома и не на специальном кастомном монументе.", ["MuchWagons"] = "{0} Чтобы включить режим редактирования, внутри монумента не должно быть более 1 вагона.", ["NotCustomWagon"] = "{0} Чтобы включить режим редактирования, внутри монумента должен быть вагон для строительста.", ["NotHaveWagons"] = "{0} Чтобы включить режим редактирования, внутри монумента должен быть вагон.", ["InvalidCmdChat1"] = "{0} Вы <color=#ce3f27>не написали</color> количество и SteamID игрока! \n/givewagon <amount> <SteamID>", ["InvalidCmdChat2"] = "{0} Вы <color=#ce3f27>не написали</color> SteamID игрока! \n/givewagon <amount> <SteamID>", ["InvalidCmdChat3"] = "{0} Игрок с SteamID: {1} <color=#ce3f27>не найден</color>", ["ValidCmdChat"] = "{0} Вагон был удачно выдан игоку!", ["YouNotOwner"] = "{0} Вы не можете это сделать потому что не являетесь владельцем вагона!", ["CantBuildingOnFreeWagon"] = "{0} Строиться на свободном вагоне нельзя! Введите код для кодлока и повторите попытку.", ["NotHavePerm"] = "{0} У вас нет разрешений на использование этой команды.", ["NotHavePermForMoreWagons"] = "{0} У вас нет разрешений на владение большего кол-ва вагонов.", ["GUI_General"] = "Общее", ["GUI_General_Description"] = "1) В ящиках, можно найти предмет для спавна вагона." + "\n2) На железнодорожных путях, изредка, можно встретить свободный вагон.Чтобы стать его владельцем, введите любой код." + "\n3) Разместить вагон вы можете только у себя на базе.Подробности смотрите в разделе 'Конструкция'." + "\n4) Строиться на вагоне вы можете только у себя на базе или на кастомном монументе, если он есть.Подробности смотрите в разделе ‘Кастом монумент’." + "\n5) Строиться на вагоне может любой игрок." + "\n6) На вагоне не нужно устанавливать шкаф, поскольку объекты на нем не гниют, также как и сам вагон." + "\n7) Для перемещения вагона с базы на рельсы и обратно, вам понадобиться детонатор.Введите частоту, которая указана на вагоне, встаньте перед тем место, куда хотите его переместить и нажмите кнопку." + "\n8) Доступ к перемещению вагона имеют все игроки, которые авторизованы в кодлоке." + "\n9) Частоту вагона может поменять любой игрок." + "\n10) Владелец вагона может удалить свой вагон и взамен получить предмет для спавна.Будьте осторожны! Все объекты на нем пропадут, а ресурсы возвращены не будут.(Команда: /removewagon)", ["GUI_Construction"] = "Конструкция", ["GUI_Construction_Description"] = "1) Конструкция должна содержать 7x3 фундамента." + "\n2) Для размещения вагона вы обязательно должны поставить шкаф." + "\n3) Все фундаменты должны быть на одной высоте." + "\n4) Если во время нахождения вагона на конструкции сломается шкаф, или один из 21 фундамента, или подставка, то вагон также уничтожится." + "\n5) Для размещения вагона, вы должны строго указывать тот фундамент, который самый центральный из 21." + "\n6) Вагон нельзя размещать не на фундаментах.", ["GUI_CustomMonument"] = "Кастом монумент", ["GUI_CustomMonument_Description"] = "1) Вы не сможете что либо построить на вагоне пока не активируете режим строительства." + "\n2) Активация режима строительства происходит путем нажатия кнопки на одном из столбов." + "\n3) После нажатия кнопки, вагон автоматически доедет до нужной позиции, если он целиком не находится в зоне строительства" + "\n4) Будьте осторожны! Во время режима строительства, любой игрок сможет построить что либо на вашем вагоне." + "\n5) Чтобы выйти из режима строительства, нажмите еще раз на кнопку.",
}
, this, "ru");
}
private static string GetMessage(string langKey, string userID) => ownIns.lang.GetMessage(langKey, ownIns, userID);
private static string GetMessage(string langKey, string userID, params object[] args) => (args.Length == 0) ? GetMessage(langKey, userID) : string.Format(GetMessage(langKey, userID), args);
#endregion Lang
#region GUI
[ConsoleCommand("Close_GUI")]
void DestroyGUI(ConsoleSystem.Arg arg) => GUIManager.DestroyGUI(arg.Player());
[ConsoleCommand("GUI_General")]
void CreateGUI_General(ConsoleSystem.Arg arg) => GUIManager.CreateGUI(arg.Player(), GUIManager.GUITopic.General);
[ConsoleCommand("GUI_Construction")]
void CreateGUI_Construction(ConsoleSystem.Arg arg) => GUIManager.CreateGUI(arg.Player(), GUIManager.GUITopic.Construction);
[ConsoleCommand("GUI_CustomMonument")]
void CreateGUI_CustomMonument(ConsoleSystem.Arg arg) => GUIManager.CreateGUI(arg.Player(), GUIManager.GUITopic.CustomMonument);
#endregion GUI
#region Data System
private void WriteData() {
CreateData();
Interface.Oxide.DataFileSystem.WriteObject("MM_Data/TrainHomes/Wagons", dataForWagons);
Interface.Oxide.DataFileSystem.WriteObject("MM_Data/TrainHomes/Garages", dataForGarages);
}
private void LoadFiles() {
dataForWagons = Interface.Oxide.DataFileSystem.ReadObject<HashSet<WagonData>>("MM_Data/TrainHomes/Wagons");
dataForGarages = Interface.Oxide.DataFileSystem.ReadObject<HashSet<GarageData>>("MM_Data/TrainHomes/Garages");
LoadDataForWagon();
LoadDataForGarage();
}
void LoadDataForWagon() {
foreach (WagonData wagonData in dataForWagons) {
Wagon wagon = new Wagon();
bool isValidData = true;
wagon.InitWithData(wagonData, ref isValidData);
if (isValidData) wagons.Add(wagon);
else {
wagon.RemoveWagon();
wagon = null;
}
}
}
void LoadDataForGarage() {
foreach (GarageData garageData in dataForGarages) {
BuildingPrivlidge cupboard = null;
foreach (var entity in BaseNetworkable.serverEntities) {
if (entity.net.ID.Value == garageData.idCupboard) {
cupboard = entity as BuildingPrivlidge;
break;
}
}
Garage garage = new Garage();
garage.InitWithData(garageData);
if (cupboard == null) {
garage.DestroyAllWagons();
continue;
}
if (garage.wagons.Count > 0) dicGarages.Add(cupboard, garage);
else garage = null;
}
}
void CreateData() {
dataForWagons.Clear();
dataForGarages.Clear();
CreateDataForWagon();
CreateDataForGarage();
}
void CreateDataForWagon() {
foreach (Wagon wagon in wagons.ToHashSet()) {
if (wagon == null || wagon.freeWagon) continue;
if (wagon.baseWagon != null) wagon.CreateObjectForUnload();
WagonData data = wagon.CreateInfoForData();
wagon.UpdateForUnload();
dataForWagons.Add(data);
}
}
void CreateDataForGarage() {
foreach (KeyValuePair<BuildingPrivlidge, Garage> garage in dicGarages) {
GarageData data = garage.Value.CreateInfoForData(garage.Key.net.ID.Value);
dataForGarages.Add(data);
}
}
#endregion Data System
#region Oxide Hooks
private void Init() {
ownIns = this;
PermissionManager.RegisterPermissions();
}
private void Unload() {
WriteData();
DestroyAllCustomMonuments();
dicGarages.Clear();
ControllerSpawnsFreeWagon.Unload();
ownIns = null;
}
private void OnServerInitialized() {
PluginUpdateManager.CheckPluginUpdate();
LoadFiles();
DetermineSetingsEntities();
ControllerSpawnsFreeWagon.Init();
DetermineAllMonumentsForWagon();
}
object OnEntityKill(BaseEntity entity) {
if (entity.net == null) return null;
ulong netId = entity.net.ID.Value;
if (entity is BaseCombatEntity) {
if (allBaseWagons.ContainsKey(netId)) OnWagonKill(allBaseWagons[netId]);
if (allBaseBarricades.ContainsKey(netId)) OnWagonKill(allBaseBarricades[netId]);
}
OnTrainCarKill(entity as TrainCar, netId);
OnBuildingBlockKill(entity as BuildingBlock, netId);
OnCupboardKill(entity as BuildingPrivlidge);
if (allBaseEntityByWagons.ContainsKey(netId)) {
Wagon wagon = allBaseEntityByWagons[netId];
wagon.RemoveEntityInLists(entity);
allBaseEntityByWagons.Remove(netId);
}
return null;
}
void OnWagonKill(Wagon wagon) {
wagon.RemoveWagon();
wagon = null;
}
void OnTrainCarKill(TrainCar trainCar, ulong netId) {
if (trainCar == null) return;
if (onServerInit) ControllerSpawnsFreeWagon.RemoveFreeWagon(trainCar);
if (allTrainCars.ContainsKey(netId)) OnWagonKill(allTrainCars[netId]);
}
void OnBuildingBlockKill(BuildingBlock block, ulong netId) {
if (block == null) return;
if (block.PrefabName != "assets/prefabs/building core/foundation/foundation.prefab" || !allFoundationsUnderWagons.ContainsKey(netId)) return;
Garage garage = allFoundationsUnderWagons[netId];
Vector3 pos = garage.GetPosWagon(block);
Wagon wagon = garage.GetWagon(pos);
wagon.RemoveWagon();
}
void OnCupboardKill(BuildingPrivlidge cupboard) {
if (cupboard == null) return;
if (!dicGarages.ContainsKey(cupboard)) return;
Garage garage = dicGarages[cupboard];
garage.DestroyAllWagons();
dicGarages.Remove(cupboard);
garage = null;
}
object OnConstructionPlace(BaseEntity baseEntity, Construction construction, Construction.Target target, BasePlayer player) {
NextTick(() => CheckBaseEntity(baseEntity, construction, target, player));
return null;
}
object CanPickupLock(BasePlayer player, CodeLock codelock) {
if (allCodeLocks.Contains(codelock)) return true;
return null;
}
object OnEntityTakeDamage(BaseCombatEntity baseCombatEntity, HitInfo info) {
if (baseCombatEntity == null || info == null || baseCombatEntity.net == null) return null;
if (_config.Log) LogManager.AddLogDamage(baseCombatEntity, info);
return null;
}
object OnEntityTakeDamage(BuildingBlock entity, HitInfo info) {
if (entity == null || entity.net == null) return null;
if (entity.PrefabName == "assets/prefabs/building core/foundation.steps/foundation.steps.prefab" && allObjectsOfWalls.Contains(entity.net.ID.Value)) return true;
return null;
}
object OnEntityTakeDamage(LootContainer container, HitInfo info) {
if (container == null || container.net == null) return null;
if (allObjectsOfWalls.Contains(container.net.ID.Value)) return true;
return null;
}
object OnEntityTakeDamage(Barricade barricade, HitInfo info) {
if (barricade == null || barricade.net == null) return null;
if (allObjectsOfWalls.Contains(barricade.net.ID.Value)) return true;
return null;
}
object OnEntityTakeDamage(NeonSign neonSign, HitInfo info) {
if (neonSign == null || neonSign.net == null) return null;
if (allObjectsOfWalls.Contains(neonSign.net.ID.Value)) return true;
return null;
}
object OnEntityTakeDamage(RFReceiver receiver, HitInfo info) {
if (receiver == null) return null;
if (allReceivers.Contains(receiver)) return true;
return null;
}
object OnEntityTakeDamage(RANDSwitch randSwitch, HitInfo info) {
if (randSwitch == null) return null;
if (allSwitches.Contains(randSwitch)) return true;
return null;
}
object OnStructureRepair(BaseCombatEntity entity, BasePlayer player) {
if (entity == null || entity.net == null) return null;
if (!allBaseWagons.ContainsKey(entity.net.ID.Value)) return null;
if (!playersWhoWantsToRemoveBaseWagon.Contains(player)) return null;
Item item = ItemManager.CreateByName("electric.flasherlight", 1, SkindIdFlasher);
MoveItem(player, item);
Wagon wagon = allBaseWagons[entity.net.ID.Value];
if (wagon.owner == player) {
wagon.RemoveWagon();
wagon = null;
}
else NotifyManager.SendMessageToPlayer(player, "YouNotOwner", ownIns._config.NotifyConfig.prefix);
return true;
}
object OnButtonPress(PressButton button, BasePlayer player) {
if (button == null || !player.IsPlayer()) return null;
CustomMonument monument;
if (buttonsOnMonuments.TryGetValue(button, out monument)) monument.TryUpdateState(player);
return null;
}
private void OnLootSpawn(LootContainer container) {
if (container == null || container.inventory == null) return;
CrateConfig config = _config.Crates.FirstOrDefault(x => x.Prefab == container.PrefabName);
if (config == null) return;
if (UnityEngine.Random.Range(0f, 100f) > config.Chance) return;
if (container.inventory.itemList.Count == container.inventory.capacity) container.inventory.capacity++;
Item wagon = ItemManager.CreateByName("electric.flasherlight", 1, SkindIdFlasher);
if (!wagon.MoveToContainer(container.inventory)) wagon.Remove();
}
object CanChangeCode(BasePlayer player, CodeLock codeLock, string newCode, bool isGuestCode) {
if (allCodeLocks.Contains(codeLock)) {
ModificationsWagon modifications = codeLock.GetParentEntity() as ModificationsWagon;
if (modifications != null) {
if (!CanHaveMoreWagons(player)) return true;
if (!amountWagons.ContainsKey(player)) amountWagons.Add(player, 0);
amountWagons[player]++;
NextTick(() => modifications.ChangeStateToLocked(player));
}
}
return null;
}
void OnEntitySpawned(TrainCar trainCar) {
NextTick(() => ControllerSpawnsFreeWagon.TryAddNewTrainCar(trainCar));
}
#endregion Oxide Hooks
#region RustEdit Hooks
void RustEdit_OnMapDataProcessed() => DetermineAllMonumentsForWagon();
#endregion RustEdit Hooks
#region Helpers
void CheckBaseEntity(BaseEntity baseEntity, Construction construction, Construction.Target target, BasePlayer player) {
if (!player.IsPlayer()) return;
if (baseEntity == null) return;
if (IsItItemForWagonSpawn(baseEntity)) {
if (!CanHaveMoreWagons(player)) {
CancelAction(baseEntity, player);
return;
}
TryCreateNewGarage(baseEntity, target.entity, player);
}
Wagon wagon;
if (target.entity == null) return;
if (!IsTargetEntityBelongWagon(target.entity, out wagon)) return;
if (wagon.baseWagon != null) wagon.CheckNewEntity(baseEntity, target.entity, player);
else CheckWagonOnCustomMonument(player, baseEntity, target.entity, wagon);
}
bool IsItItemForWagonSpawn(BaseEntity baseEntity) {
return baseEntity.ShortPrefabName == "electric.flasherlight.deployed" && baseEntity.skinID == SkindIdFlasher;
}
static bool CanHaveMoreWagons(BasePlayer player) {
if (!ownIns._config.AmountWagons) return true;
int maxAmountWagons = 0;
foreach (KeyValuePair<string, int> kvp in ownIns._config.PermissionsForAmountWagons) {
if (ownIns.permission.UserHasPermission(player.UserIDString, kvp.Key) && kvp.Value > maxAmountWagons) maxAmountWagons = kvp.Value;
}
if ((maxAmountWagons == 0) || (ownIns.amountWagons.ContainsKey(player) && ownIns.amountWagons[player] >= maxAmountWagons)) {
NotifyManager.SendMessageToPlayer(player, "NotHavePermForMoreWagons", ownIns._config.NotifyConfig.prefix);
return false;
}
return true;
}
void TryCreateNewGarage(BaseEntity baseEntity, BaseEntity targetEntity, BasePlayer player) {
if (!IsExistCupboard(baseEntity, player)) return;
if (!IsTargetValid(baseEntity, targetEntity, player)) return;
baseEntity.Kill();
TryCreateNewPosInGarage(targetEntity, player, player.GetBuildingPrivilege());
}
bool IsExistCupboard(BaseEntity baseEntity, BasePlayer player) {
BuildingPrivlidge cupboard = player.GetBuildingPrivilege();
if (cupboard == null) {
NotifyManager.SendMessageToPlayer(player, "BaseHasntCupboard", ownIns._config.NotifyConfig.prefix);
CancelAction(baseEntity, player);
return false;
}
return true;
}
static bool IsTargetValid(BaseEntity baseEntity, BaseEntity targetEntity, BasePlayer player) {
if (!(targetEntity is BuildingBlock) || targetEntity.PrefabName != "assets/prefabs/building core/foundation/foundation.prefab") {
NotifyManager.SendMessageToPlayer(player, "NotValidTarget", ownIns._config.NotifyConfig.prefix);
if (baseEntity.ShortPrefabName == "electric.flasherlight.deployed") CancelAction(baseEntity, player);
return false;
}
return true;
}
void TryCreateNewPosInGarage(BaseEntity targetEntity, BasePlayer player, BuildingPrivlidge cupboard, Wagon wagon = null) {
List<BuildingBlock> buildingBlocks = Facepunch.Pool.GetList<BuildingBlock>();
ConstructionMatrix matrix = new ConstructionMatrix();
Garage garage;
CreateListWithFoundations(buildingBlocks, targetEntity);
if (!IsRightAmountFoundations(buildingBlocks, player)) {
Facepunch.Pool.FreeList(ref buildingBlocks);
return;
}
if (!IsValidConstruction(matrix, targetEntity, buildingBlocks, player, wagon)) {
Facepunch.Pool.FreeList(ref buildingBlocks);
return;
}
if (!ownIns.dicGarages.TryGetValue(cupboard, out garage)) {
garage = new Garage();
dicGarages.Add(cupboard, garage);
}
if (wagon == null) wagon = GetNewWagon(player, matrix, garage);
else wagon.MoveWagonInBase(matrix.posForSpawnWagon, garage);
garage.AddNewPos(matrix.posForSpawnWagon, matrix.blocksUnderWagon);
garage.wagons.Add(matrix.posForSpawnWagon.Key, wagon);
Facepunch.Pool.FreeList(ref buildingBlocks);
return;
}
void CreateListWithFoundations(List<BuildingBlock> buildingBlocks, BaseEntity targetEntity) {
Vis.Entities(targetEntity.transform.position, 11f, buildingBlocks);
foreach (BuildingBlock buildingBlock in buildingBlocks.ToHashSet()) {
if (buildingBlock.PrefabName != "assets/prefabs/building core/foundation/foundation.prefab") buildingBlocks.Remove(buildingBlock);
}
}
bool IsRightAmountFoundations(List<BuildingBlock> buildingBlocks, BasePlayer player) {
if (buildingBlocks.Count < 21) {
NotifyManager.SendMessageToPlayer(player, "NoNeedAmountBlocks", ownIns._config.NotifyConfig.prefix);
GiveWagon(player, 1);
return false;
}
return true;
}
bool IsValidConstruction(ConstructionMatrix matrix, BaseEntity baseEntity, List<BuildingBlock> buildingBlocks, BasePlayer player, Wagon wagon) {
matrix.Init(baseEntity, buildingBlocks, player);
if (!matrix.isValid) {
NotifyManager.SendMessageToPlayer(player, "NotValidConstruction", ownIns._config.NotifyConfig.prefix);
if (wagon == null) GiveWagon(player, 1);
return false;
}
return true;
}
static Wagon GetNewWagon(BasePlayer player, ConstructionMatrix matrix, Garage garage) {
if (!ownIns.amountWagons.ContainsKey(player)) ownIns.amountWagons.Add(player, 0);
ownIns.amountWagons[player]++;
Wagon wagon = new Wagon();
wagon.Init(player, matrix.posForSpawnWagon, garage);
return wagon;
}
bool IsTargetEntityBelongWagon(BaseEntity targetEntity, out Wagon wagon) {
return allBaseEntityByWagons.TryGetValue(targetEntity.net.ID.Value, out wagon);
}
void CheckWagonOnCustomMonument(BasePlayer player, BaseEntity baseEntity, BaseEntity targetEntity, Wagon wagon) {
CustomMonument monument1;
if (playersOnMonuments.TryGetValue(player, out monument1) && !monument1.IsWagonOnMonument(wagon.trainCar)) return;
if (monument1 == null) {
NotifyManager.SendMessageToPlayer(player, "NotOnBaseAndNotOnMonument", ownIns._config.NotifyConfig.prefix);
CancelAction(baseEntity, player);
}
else if (monument1.isBuildingState) wagon.CheckNewEntity(baseEntity, targetEntity, player);
else {
NotifyManager.SendMessageToPlayer(player, "ModeIsNotBuilding", ownIns._config.NotifyConfig.prefix);
CancelAction(baseEntity, player);
}
}
void DetermineAllMonumentsForWagon() {
if (customMonuments.Count > 0) return;
foreach (BaseNetworkable entity in BaseNetworkable.serverEntities.entityList.Get().Values) {
ElectricalBranch branch = entity as ElectricalBranch;
if (branch == null || branch.branchAmount != 888444) continue;
CustomMonument monument = new GameObject().AddComponent<CustomMonument>();
monument.Init(branch);
customMonuments.Add(monument);
}
}
void DestroyAllCustomMonuments() {
foreach (CustomMonument monument in customMonuments) {
monument.Destroy();
UnityEngine.Object.Destroy(monument.gameObject);
}
}
void DetermineSetingsEntities() {
foreach (AcceptableEntities entity in ownIns._config.AcceptableEntities) {
acceptableEntities.Add(entity.ShortName, new SettingsEntity {
IsAllowPut = entity.IsAllowPut, Amount = entity.Amount
}
);
}
}
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);
}
}
static Quaternion GetGlobalRot(Transform Transform, Vector3 localRotation) {
return Transform.rotation * Quaternion.Euler(localRotation);
}
static Vector3 GetGlobalPos(Transform Transform, Vector3 localPosition) {
return Transform.TransformPoint(localPosition);
}
static void GiveWagon(BasePlayer player, int amount) {
Item item = ItemManager.CreateByName("electric.flasherlight", amount, SkindIdFlasher);
item.name = "Wagon";
MoveItem(player, item);
}
static void CancelAction(BaseEntity entity, BasePlayer player) {
if (entity is BuildingBlock) ReturnResourcesToPlayer(entity as BuildingBlock, player);
else ReturnEntityToPlayer(entity, player);
if (entity.IsExists()) entity.Kill();
}
static void ReturnResourcesToPlayer(BuildingBlock buildingBlock, BasePlayer player) {
foreach (ItemAmount itemAmount in buildingBlock.BuildCost()) {
Item item = ItemManager.CreateByItemID(itemAmount.itemid, (int)itemAmount.amount, 0);
MoveItem(player, item);
}
}
static void ReturnEntityToPlayer(BaseEntity entity, BasePlayer player) {
BaseCombatEntity baseCombatEntity = entity as BaseCombatEntity;
string strName = GetItemName(baseCombatEntity);
Item item = ItemManager.CreateByName(strName, 1, entity.skinID);
MoveItem(player, item);
}
static string GetItemName(BaseCombatEntity baseCombatEntity) {
if (baseCombatEntity.pickup.itemTarget == null) {
string strName;
if (ownIns.entityToItem.TryGetValue(baseCombatEntity.PrefabName, out strName)) return strName;
else return GetShortNameItem(baseCombatEntity);
}
else return baseCombatEntity.pickup.itemTarget.shortname;
}
static string GetShortNameItem(BaseCombatEntity baseCombatEntity) {
foreach (ItemDefinition itemDef in ItemManager.GetItemDefinitions()) {
if (itemDef == null) continue;
ItemModDeployable itemMod = itemDef.GetComponent<ItemModDeployable>();
if (ite
// ... [Code preview truncated due to length. Full source in attached file] ...