NTeleportation plugin update

Download Raw Clone


  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.Globalization;
  5. using System.Linq;
  6. using Facepunch;
  7. using Newtonsoft.Json;
  8. using Newtonsoft.Json.Converters;
  9. using Newtonsoft.Json.Linq;
  10. using Oxide.Core;
  11. using Oxide.Core.Configuration;
  12. using Oxide.Core.Plugins;
  13. using Oxide.Game.Rust;
  14. using Rust;
  15. using UnityEngine;
  16. namespace Oxide.Plugins
  17. {
  18. [Info("NTeleportation", "RFC1920", "1.0.34", ResourceId = 1832)]
  19. class NTeleportation : RustPlugin
  20. {
  21. private const string NewLine = "\n";
  22. private const string ConfigDefaultPermVip = "nteleportation.vip";
  23. private const string PermDeleteHome = "nteleportation.deletehome";
  24. private const string PermHomeHomes = "nteleportation.homehomes";
  25. private const string PermImportHomes = "nteleportation.importhomes";
  26. private const string PermRadiusHome = "nteleportation.radiushome";
  27. private const string PermTp = "nteleportation.tp";
  28. private const string PermTpB = "nteleportation.tpb";
  29. private const string PermTpConsole = "nteleportation.tpconsole";
  30. private const string PermTpHome = "nteleportation.tphome";
  31. private const string PermTpTown = "nteleportation.tptown";
  32. private const string PermTpN = "nteleportation.tpn";
  33. private const string PermTpL = "nteleportation.tpl";
  34. private const string PermTpRemove = "nteleportation.tpremove";
  35. private const string PermTpSave = "nteleportation.tpsave";
  36. private const string PermWipeHomes = "nteleportation.wipehomes";
  37. private const string PermCraftHome = "nteleportation.crafthome";
  38. private const string PermCraftTown = "nteleportation.crafttown";
  39. private const string PermCraftTpR = "nteleportation.crafttpr";
  40. private DynamicConfigFile dataAdmin;
  41. private DynamicConfigFile dataHome;
  42. private DynamicConfigFile dataTPR;
  43. private DynamicConfigFile dataTown;
  44. private Dictionary<ulong, AdminData> Admin;
  45. private Dictionary<ulong, HomeData> Home;
  46. private Dictionary<ulong, TeleportData> TPR;
  47. private Dictionary<ulong, TeleportData> Town;
  48. private bool changedAdmin;
  49. private bool changedHome;
  50. private bool changedTPR;
  51. private bool changedTown;
  52. private ConfigData configData;
  53. private float boundary;
  54. private readonly int triggerLayer = LayerMask.GetMask("Trigger");
  55. private readonly int groundLayer = LayerMask.GetMask("Terrain", "World");
  56. private readonly int buildingLayer = LayerMask.GetMask("Terrain", "World", "Construction", "Deployed");
  57. private readonly int blockLayer = LayerMask.GetMask("Construction");
  58. private readonly Dictionary<ulong, TeleportTimer> TeleportTimers = new Dictionary<ulong, TeleportTimer>();
  59. private readonly Dictionary<ulong, Timer> PendingRequests = new Dictionary<ulong, Timer>();
  60. private readonly Dictionary<ulong, BasePlayer> PlayersRequests = new Dictionary<ulong, BasePlayer>();
  61. private readonly Dictionary<int, string> ReverseBlockedItems = new Dictionary<int, string>();
  62. private readonly HashSet<ulong> teleporting = new HashSet<ulong>();
  63. [PluginReference]
  64. private Plugin Clans, Economics, ServerRewards, Friends, RustIO;
  65. class ConfigData
  66. {
  67. public SettingsData Settings { get; set; }
  68. public AdminSettingsData Admin { get; set; }
  69. public HomesSettingsData Home { get; set; }
  70. public TPRData TPR { get; set; }
  71. public TownData Town { get; set; }
  72. public VersionNumber Version { get; set; }
  73. }
  74. class SettingsData
  75. {
  76. public string ChatName { get; set; }
  77. public bool HomesEnabled { get; set; }
  78. public bool TPREnabled { get; set; }
  79. public bool TownEnabled { get; set; }
  80. public bool InterruptTPOnHurt { get; set; }
  81. public Dictionary<string, string> BlockedItems { get; set; } = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
  82. public string BypassCMD { get; set; }
  83. public bool UseEconomics { get; set; }
  84. public bool UseServerRewards { get; set; }
  85. }
  86. class AdminSettingsData
  87. {
  88. public bool AnnounceTeleportToTarget { get; set; }
  89. public bool UseableByModerators { get; set; }
  90. public int LocationRadius { get; set; }
  91. public int TeleportNearDefaultDistance { get; set; }
  92. }
  93. class HomesSettingsData
  94. {
  95. public int HomesLimit { get; set; }
  96. public Dictionary<string, int> VIPHomesLimits { get; set; }
  97. public int Cooldown { get; set; }
  98. public int Countdown { get; set; }
  99. public int DailyLimit { get; set; }
  100. public Dictionary<string, int> VIPDailyLimits { get; set; }
  101. public Dictionary<string, int> VIPCooldowns { get; set; }
  102. public Dictionary<string, int> VIPCountdowns { get; set; }
  103. public int LocationRadius { get; set; }
  104. public bool ForceOnTopOfFoundation { get; set; }
  105. public bool CheckFoundationForOwner { get; set; }
  106. public bool UseFriends { get; set; }
  107. public bool UsableOutOfBuildingBlocked { get; set; }
  108. public bool UsableIntoBuildingBlocked { get; set; }
  109. public bool CupOwnerAllowOnBuildingBlocked { get; set; }
  110. public bool AllowIceberg { get; set; }
  111. public bool AllowCave { get; set; }
  112. public bool AllowCraft { get; set; }
  113. public bool AllowAboveFoundation { get; set; }
  114. public bool CheckValidOnList { get; set; }
  115. public int Pay { get; set; }
  116. public int Bypass { get; set; }
  117. }
  118. class TPRData
  119. {
  120. public int Cooldown { get; set; }
  121. public int Countdown { get; set; }
  122. public int DailyLimit { get; set; }
  123. public Dictionary<string, int> VIPDailyLimits { get; set; }
  124. public Dictionary<string, int> VIPCooldowns { get; set; }
  125. public Dictionary<string, int> VIPCountdowns { get; set; }
  126. public int RequestDuration { get; set; }
  127. public bool BlockTPAOnCeiling { get; set; }
  128. public bool UsableOutOfBuildingBlocked { get; set; }
  129. public bool UsableIntoBuildingBlocked { get; set; }
  130. public bool CupOwnerAllowOnBuildingBlocked { get; set; }
  131. public bool AllowCraft { get; set; }
  132. public int Pay { get; set; }
  133. public int Bypass { get; set; }
  134. }
  135. class TownData
  136. {
  137. public int Cooldown { get; set; }
  138. public int Countdown { get; set; }
  139. public int DailyLimit { get; set; }
  140. public Dictionary<string, int> VIPDailyLimits { get; set; }
  141. public Dictionary<string, int> VIPCooldowns { get; set; }
  142. public Dictionary<string, int> VIPCountdowns { get; set; }
  143. public Vector3 Location { get; set; }
  144. public bool UsableOutOfBuildingBlocked { get; set; }
  145. public bool AllowCraft { get; set; }
  146. public int Pay { get; set; }
  147. public int Bypass { get; set; }
  148. }
  149. class AdminData
  150. {
  151. [JsonProperty("pl")]
  152. public Vector3 PreviousLocation { get; set; }
  153. [JsonProperty("l")]
  154. public Dictionary<string, Vector3> Locations { get; set; } = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase);
  155. }
  156. class HomeData
  157. {
  158. [JsonProperty("l")]
  159. public Dictionary<string, Vector3> Locations { get; set; } = new Dictionary<string, Vector3>(StringComparer.OrdinalIgnoreCase);
  160. [JsonProperty("t")]
  161. public TeleportData Teleports { get; set; } = new TeleportData();
  162. }
  163. class TeleportData
  164. {
  165. [JsonProperty("a")]
  166. public int Amount { get; set; }
  167. [JsonProperty("d")]
  168. public string Date { get; set; }
  169. [JsonProperty("t")]
  170. public int Timestamp { get; set; }
  171. }
  172. class TeleportTimer
  173. {
  174. public Timer Timer { get; set; }
  175. public BasePlayer OriginPlayer { get; set; }
  176. public BasePlayer TargetPlayer { get; set; }
  177. }
  178. protected override void LoadDefaultConfig()
  179. {
  180. Config.Settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  181. Config.Settings.Converters = new JsonConverter[] { new UnityVector3Converter() };
  182. Config.WriteObject(new ConfigData
  183. {
  184. Settings = new SettingsData
  185. {
  186. ChatName = "<color=red>Teleportation</color>: ",
  187. HomesEnabled = true,
  188. TPREnabled = true,
  189. TownEnabled = true,
  190. InterruptTPOnHurt = true,
  191. BypassCMD = "pay",
  192. UseEconomics = false,
  193. UseServerRewards = false
  194. },
  195. Admin = new AdminSettingsData
  196. {
  197. AnnounceTeleportToTarget = false,
  198. UseableByModerators = true,
  199. LocationRadius = 25,
  200. TeleportNearDefaultDistance = 30
  201. },
  202. Home = new HomesSettingsData
  203. {
  204. HomesLimit = 2,
  205. VIPHomesLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  206. Cooldown = 600,
  207. Countdown = 15,
  208. DailyLimit = 5,
  209. VIPDailyLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  210. VIPCooldowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  211. VIPCountdowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  212. LocationRadius = 25,
  213. ForceOnTopOfFoundation = true,
  214. CheckFoundationForOwner = true,
  215. UseFriends = true,
  216. AllowAboveFoundation = true,
  217. CheckValidOnList = false,
  218. CupOwnerAllowOnBuildingBlocked = true
  219. },
  220. TPR = new TPRData
  221. {
  222. Cooldown = 600,
  223. Countdown = 15,
  224. DailyLimit = 5,
  225. VIPDailyLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  226. VIPCooldowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  227. VIPCountdowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  228. RequestDuration = 30,
  229. BlockTPAOnCeiling = true,
  230. CupOwnerAllowOnBuildingBlocked = true
  231. },
  232. Town = new TownData
  233. {
  234. Cooldown = 600,
  235. Countdown = 15,
  236. DailyLimit = 5,
  237. VIPDailyLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  238. VIPCooldowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } },
  239. VIPCountdowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } }
  240. },
  241. Version = Version
  242. }, true);
  243. }
  244. private void Init()
  245. {
  246. lang.RegisterMessages(new Dictionary<string, string>
  247. {
  248. {"AdminTP", "You teleported to {0}!"},
  249. {"AdminTPTarget", "{0} teleported to you!"},
  250. {"AdminTPPlayers", "You teleported {0} to {1}!"},
  251. {"AdminTPPlayer", "{0} teleported you to {1}!"},
  252. {"AdminTPPlayerTarget", "{0} teleported {1} to you!"},
  253. {"AdminTPCoordinates", "You teleported to {0}!"},
  254. {"AdminTPTargetCoordinates", "You teleported {0} to {1}!"},
  255. {"AdminTPOutOfBounds", "You tried to teleport to a set of coordinates outside the map boundaries!"},
  256. {"AdminTPBoundaries", "X and Z values need to be between -{0} and {0} while the Y value needs to be between -100 and 2000!"},
  257. {"AdminTPLocation", "You teleported to {0}!"},
  258. {"AdminTPLocationSave", "You have saved the current location!"},
  259. {"AdminTPLocationRemove", "You have removed the location {0}!"},
  260. {"AdminLocationList", "The following locations are available:"},
  261. {"AdminLocationListEmpty", "You haven't saved any locations!"},
  262. {"AdminTPBack", "You've teleported back to your previous location!"},
  263. {"AdminTPBackSave", "Your previous location has been saved, use /tpb to teleport back!"},
  264. {"AdminTPTargetCoordinatesTarget", "{0} teleported you to {1}!"},
  265. {"AdminTPConsoleTP", "You were teleported to {0}"},
  266. {"AdminTPConsoleTPPlayer", "You were teleported to {0}"},
  267. {"AdminTPConsoleTPPlayerTarget", "{0} was teleported to you!"},
  268. {"HomeTP", "You teleported to your home '{0}'!"},
  269. {"HomeAdminTP", "You teleported to {0}'s home '{1}'!"},
  270. {"HomeSave", "You have saved the current location as your home!"},
  271. {"HomeNoFoundation", "You can only use a home location on a foundation!"},
  272. {"HomeFoundationNotOwned", "You can't use home on someone else's house."},
  273. {"HomeFoundationUnderneathFoundation", "You can't use home on a foundation that is underneath another foundation."},
  274. {"HomeFoundationNotFriendsOwned", "You or a friend need to own the house to use home!"},
  275. {"HomeRemovedInvalid", "Your home '{0}' was removed because not on a foundation or not owned!"},
  276. {"HomeRemovedInsideBlock", "Your home '{0}' was removed because inside a foundation!"},
  277. {"HomeRemove", "You have removed your home {0}!"},
  278. {"HomeDelete", "You have removed {0}'s home '{1}'!"},
  279. {"HomeList", "The following homes are available:"},
  280. {"HomeListEmpty", "You haven't saved any homes!"},
  281. {"HomeMaxLocations", "Unable to set your home here, you have reached the maximum of {0} homes!"},
  282. {"HomeQuota", "You have set {0} of the maximum {1} homes!"},
  283. {"HomeTPStarted", "Teleporting to your home {0} in {1} seconds!"},
  284. {"PayToHome", "Standard payment of {0} applies to all home teleports!"},
  285. {"PayToTown", "Standard payment of {0} applies to all town teleports!"},
  286. {"PayToTPR", "Standard payment of {0} applies to all tprs!"},
  287. {"HomeTPCooldown", "Your teleport is currently on cooldown. You'll have to wait {0} for your next teleport."},
  288. {"HomeTPCooldownBypass", "Your teleport was currently on cooldown. You chose to bypass that by paying {0} from your balance."},
  289. {"HomeTPCooldownBypassF", "Your teleport is currently on cooldown. You do not have sufficient funds - {0} - to bypass."},
  290. {"HomeTPCooldownBypassP", "You may choose to pay {0} to bypass this cooldown." },
  291. {"HomeTPCooldownBypassP2", "Type /home NAME {0}." },
  292. {"HomeTPLimitReached", "You have reached the daily limit of {0} teleports today!"},
  293. {"HomeTPAmount", "You have {0} home teleports left today!"},
  294. {"HomesListWiped", "You have wiped all the saved home locations!"},
  295. {"HomeTPBuildingBlocked", "You can't set your home if you are not allowed to build in this zone!"},
  296. {"HomeTPSwimming", "You can't set your home while swimming!"},
  297. {"HomeTPCrafting", "You can't set your home while crafting!"},
  298. {"Request", "You've requested a teleport to {0}!"},
  299. {"RequestTarget", "{0} requested to be teleported to you! Use '/tpa' to accept!"},
  300. {"PendingRequest", "You already have a request pending, cancel that request or wait until it gets accepted or times out!"},
  301. {"PendingRequestTarget", "The player you wish to teleport to already has a pending request, try again later!"},
  302. {"NoPendingRequest", "You have no pending teleport request!"},
  303. {"AcceptOnRoof", "You can't accept a teleport while you're on a ceiling, get to ground level!"},
  304. {"Accept", "{0} has accepted your teleport request! Teleporting in {1} seconds!"},
  305. {"AcceptTarget", "You've accepted the teleport request of {0}!"},
  306. {"NotAllowed", "You are not allowed to use this command!"},
  307. {"Success", "You teleported to {0}!"},
  308. {"SuccessTarget", "{0} teleported to you!"},
  309. {"Cancelled", "Your teleport request to {0} was cancelled!"},
  310. {"CancelledTarget", "{0} teleport request was cancelled!"},
  311. {"TPCancelled", "Your teleport was cancelled!"},
  312. {"TPCancelledTarget", "{0} cancelled teleport!"},
  313. {"TPYouCancelledTarget", "You cancelled {0} teleport!"},
  314. {"TimedOut", "{0} did not answer your request in time!"},
  315. {"TimedOutTarget", "You did not answer {0}'s teleport request in time!"},
  316. {"TargetDisconnected", "{0} has disconnected, your teleport was cancelled!"},
  317. {"TPRCooldown", "Your teleport requests are currently on cooldown. You'll have to wait {0} to send your next teleport request."},
  318. {"TPRCooldownBypass", "Your teleport request was on cooldown. You chose to bypass that by paying {0} from your balance."},
  319. {"TPRCooldownBypassF", "Your teleport is currently on cooldown. You do not have sufficient funds - {0} - to bypass."},
  320. {"TPRCooldownBypassP", "You may choose to pay {0} to bypass this cooldown." },
  321. {"TPMoney", "{0} deducted from your account!"},
  322. {"TPNoMoney", "You do not have {0} in any account!"},
  323. {"TPRCooldownBypassP2", "Type /tpr {0}." },
  324. {"TPRLimitReached", "You have reached the daily limit of {0} teleport requests today!"},
  325. {"TPRAmount", "You have {0} teleport requests left today!"},
  326. {"TPRTarget", "Your target is currently not available!"},
  327. {"TPDead", "You can't teleport while being dead!"},
  328. {"TPWounded", "You can't teleport while being wounded!"},
  329. {"TPMounted", "You can't teleport while seated!"},
  330. {"TPBuildingBlocked", "You can't teleport while in a building blocked zone!"},
  331. {"TPTargetBuildingBlocked", "You can't teleport in a building blocked zone!"},
  332. {"TPTargetInsideBlock", "You can't teleport into a foundation!"},
  333. {"TPSwimming", "You can't teleport while swimming!"},
  334. {"TPCargoShip", "You can't teleport from the cargo ship!"},
  335. {"TPHotAirBalloon", "You can't teleport to or from a hot air balloon!"},
  336. {"TPSafeZone", "You can't teleport from a safezone!"},
  337. {"TPCrafting", "You can't teleport while crafting!"},
  338. {"TPBlockedItem", "You can't teleport while carrying: {0}!"},
  339. {"TownTP", "You teleported to town!"},
  340. {"TownTPNotSet", "Town is currently not set!"},
  341. {"TownTPLocation", "You have set the town location set to {0}!"},
  342. {"TownTPStarted", "Teleporting to town in {0} seconds!"},
  343. {"TownTPCooldown", "Your teleport is currently on cooldown. You'll have to wait {0} for your next teleport."},
  344. {"TownTPCooldownBypass", "Your teleport request was on cooldown. You chose to bypass that by paying {0} from your balance."},
  345. {"TownTPCooldownBypassF", "Your teleport is currently on cooldown. You do not have sufficient funds - {0} - to bypass."},
  346. {"TownTPCooldownBypassP", "You may choose to pay {0} to bypass this cooldown." },
  347. {"TownTPCooldownBypassP2", "Type /town {0}." },
  348. {"TownTPLimitReached", "You have reached the daily limit of {0} teleports today!"},
  349. {"TownTPAmount", "You have {0} town teleports left today!"},
  350. {"Interrupted", "Your teleport was interrupted!"},
  351. {"InterruptedTarget", "{0}'s teleport was interrupted!"},
  352. {"Unlimited", "Unlimited"},
  353. {
  354. "TPInfoGeneral", string.Join(NewLine, new[]
  355. {
  356. "Please specify the module you want to view the info of.",
  357. "The available modules are: ",
  358. })
  359. },
  360. {
  361. "TPHelpGeneral", string.Join(NewLine, new[]
  362. {
  363. "/tpinfo - Shows limits and cooldowns.",
  364. "Please specify the module you want to view the help of.",
  365. "The available modules are: ",
  366. })
  367. },
  368. {
  369. "TPHelpadmintp", string.Join(NewLine, new[]
  370. {
  371. "As an admin you have access to the following commands:",
  372. "/tp \"targetplayer\" - Teleports yourself to the target player.",
  373. "/tp \"player\" \"targetplayer\" - Teleports the player to the target player.",
  374. "/tp x y z - Teleports you to the set of coordinates.",
  375. "/tpl - Shows a list of saved locations.",
  376. "/tpl \"location name\" - Teleports you to a saved location.",
  377. "/tpsave \"location name\" - Saves your current position as the location name.",
  378. "/tpremove \"location name\" - Removes the location from your saved list.",
  379. "/tpb - Teleports you back to the place where you were before teleporting.",
  380. "/home radius \"radius\" - Find all homes in radius.",
  381. "/home delete \"player name|id\" \"home name\" - Remove a home from a player.",
  382. "/home tp \"player name|id\" \"name\" - Teleports you to the home location with the name 'name' from the player.",
  383. "/home homes \"player name|id\" - Shows you a list of all homes from the player."
  384. })
  385. },
  386. {
  387. "TPHelphome", string.Join(NewLine, new[]
  388. {
  389. "With the following commands you can set your home location to teleport back to:",
  390. "/home add \"name\" - Saves your current position as the location name.",
  391. "/home list - Shows you a list of all the locations you have saved.",
  392. "/home remove \"name\" - Removes the location of your saved homes.",
  393. "/home \"name\" - Teleports you to the home location."
  394. })
  395. },
  396. {
  397. "TPHelptpr", string.Join(NewLine, new[]
  398. {
  399. "With these commands you can request to be teleported to a player or accept someone else's request:",
  400. "/tpr \"player name\" - Sends a teleport request to the player.",
  401. "/tpa - Accepts an incoming teleport request.",
  402. "/tpc - Cancel teleport or request."
  403. })
  404. },
  405. {
  406. "TPSettingsGeneral", string.Join(NewLine, new[]
  407. {
  408. "Please specify the module you want to view the settings of. ",
  409. "The available modules are:",
  410. })
  411. },
  412. {
  413. "TPSettingshome", string.Join(NewLine, new[]
  414. {
  415. "Home System has the current settings enabled:",
  416. "Time between teleports: {0}",
  417. "Daily amount of teleports: {1}",
  418. "Amount of saved Home locations: {2}"
  419. })
  420. },
  421. {
  422. "TPSettingstpr", string.Join(NewLine, new[]
  423. {
  424. "TPR System has the current settings enabled:",
  425. "Time between teleports: {0}",
  426. "Daily amount of teleports: {1}"
  427. })
  428. },
  429. {
  430. "TPSettingstown", string.Join(NewLine, new[]
  431. {
  432. "Town System has the current settings enabled:",
  433. "Time between teleports: {0}",
  434. "Daily amount of teleports: {1}"
  435. })
  436. },
  437. {"PlayerNotFound", "The specified player couldn't be found please try again!"},
  438. {"MultiplePlayers", "Found multiple players: {0}"},
  439. {"CantTeleportToSelf", "You can't teleport to yourself!"},
  440. {"CantTeleportPlayerToSelf", "You can't teleport a player to himself!"},
  441. {"TeleportPending", "You can't initiate another teleport while you have a teleport pending!"},
  442. {"TeleportPendingTarget", "You can't request a teleport to someone who's about to teleport!"},
  443. {"LocationExists", "A location with this name already exists at {0}!"},
  444. {"LocationExistsNearby", "A location with the name {0} already exists near this position!"},
  445. {"LocationNotFound", "Couldn't find a location with that name!"},
  446. {"NoPreviousLocationSaved", "No previous location saved!"},
  447. {"HomeExists", "You have already saved a home location by this name!"},
  448. {"HomeExistsNearby", "A home location with the name {0} already exists near this position!"},
  449. {"HomeNotFound", "Couldn't find your home with that name!"},
  450. {"InvalidCoordinates", "The coordinates you've entered are invalid!"},
  451. {"InvalidHelpModule", "Invalid module supplied!"},
  452. {"InvalidCharacter", "You have used an invalid character, please limit yourself to the letters a to z and numbers."},
  453. {
  454. "SyntaxCommandTP", string.Join(NewLine, new[]
  455. {
  456. "A Syntax Error Occurred!",
  457. "You can only use the /tp command as follows:",
  458. "/tp \"targetplayer\" - Teleports yourself to the target player.",
  459. "/tp \"player\" \"targetplayer\" - Teleports the player to the target player.",
  460. "/tp x y z - Teleports you to the set of coordinates.",
  461. "/tp \"player\" x y z - Teleports the player to the set of coordinates."
  462. })
  463. },
  464. {
  465. "SyntaxCommandTPL", string.Join(NewLine, new[]
  466. {
  467. "A Syntax Error Occurred!",
  468. "You can only use the /tpl command as follows:",
  469. "/tpl - Shows a list of saved locations.",
  470. "/tpl \"location name\" - Teleports you to a saved location."
  471. })
  472. },
  473. {
  474. "SyntaxCommandTPSave", string.Join(NewLine, new[]
  475. {
  476. "A Syntax Error Occurred!",
  477. "You can only use the /tpsave command as follows:",
  478. "/tpsave \"location name\" - Saves your current position as 'location name'."
  479. })
  480. },
  481. {
  482. "SyntaxCommandTPRemove", string.Join(NewLine, new[]
  483. {
  484. "A Syntax Error Occurred!",
  485. "You can only use the /tpremove command as follows:",
  486. "/tpremove \"location name\" - Removes the location with the name 'location name'."
  487. })
  488. },
  489. {
  490. "SyntaxCommandTPN", string.Join(NewLine, new[]
  491. {
  492. "A Syntax Error Occurred!",
  493. "You can only use the /tpn command as follows:",
  494. "/tpn \"targetplayer\" - Teleports yourself the default distance behind the target player.",
  495. "/tpn \"targetplayer\" \"distance\" - Teleports you the specified distance behind the target player."
  496. })
  497. },
  498. {
  499. "SyntaxCommandSetHome", string.Join(NewLine, new[]
  500. {
  501. "A Syntax Error Occurred!",
  502. "You can only use the /home add command as follows:",
  503. "/home add \"name\" - Saves the current location as your home with the name 'name'."
  504. })
  505. },
  506. {
  507. "SyntaxCommandRemoveHome", string.Join(NewLine, new[]
  508. {
  509. "A Syntax Error Occurred!",
  510. "You can only use the /home remove command as follows:",
  511. "/home remove \"name\" - Removes the home location with the name 'name'."
  512. })
  513. },
  514. {
  515. "SyntaxCommandHome", string.Join(NewLine, new[]
  516. {
  517. "A Syntax Error Occurred!",
  518. "You can only use the /home command as follows:",
  519. "/home \"name\" - Teleports yourself to your home with the name 'name'.",
  520. "/home \"name\" pay - Teleports yourself to your home with the name 'name', avoiding cooldown by paying for it.",
  521. "/home add \"name\" - Saves the current location as your home with the name 'name'.",
  522. "/home list - Shows you a list of all your saved home locations.",
  523. "/home remove \"name\" - Removes the home location with the name 'name'."
  524. })
  525. },
  526. {
  527. "SyntaxCommandHomeAdmin", string.Join(NewLine, new[]
  528. {
  529. "/home radius \"radius\" - Shows you a list of all homes in radius(10).",
  530. "/home delete \"player name|id\" \"name\" - Removes the home location with the name 'name' from the player.",
  531. "/home tp \"player name|id\" \"name\" - Teleports you to the home location with the name 'name' from the player.",
  532. "/home homes \"player name|id\" - Shows you a list of all homes from the player."
  533. })
  534. },
  535. {
  536. "SyntaxCommandTown", string.Join(NewLine, new[]
  537. {
  538. "A Syntax Error Occurred!",
  539. "You can only use the /town command as follows:",
  540. "/town - Teleports yourself to town.",
  541. "/town pay - Teleports yourself to town, paying the penalty."
  542. })
  543. },
  544. {
  545. "SyntaxCommandTownAdmin", string.Join(NewLine, new[]
  546. {
  547. "/town set - Saves the current location as town.",
  548. })
  549. },
  550. {
  551. "SyntaxCommandHomeDelete", string.Join(NewLine, new[]
  552. {
  553. "A Syntax Error Occurred!",
  554. "You can only use the /home delete command as follows:",
  555. "/home delete \"player name|id\" \"name\" - Removes the home location with the name 'name' from the player."
  556. })
  557. },
  558. {
  559. "SyntaxCommandHomeAdminTP", string.Join(NewLine, new[]
  560. {
  561. "A Syntax Error Occurred!",
  562. "You can only use the /home tp command as follows:",
  563. "/home tp \"player name|id\" \"name\" - Teleports you to the home location with the name 'name' from the player."
  564. })
  565. },
  566. {
  567. "SyntaxCommandHomeHomes", string.Join(NewLine, new[]
  568. {
  569. "A Syntax Error Occurred!",
  570. "You can only use the /home homes command as follows:",
  571. "/home homes \"player name|id\" - Shows you a list of all homes from the player."
  572. })
  573. },
  574. {
  575. "SyntaxCommandListHomes", string.Join(NewLine, new[]
  576. {
  577. "A Syntax Error Occurred!",
  578. "You can only use the /home list command as follows:",
  579. "/home list - Shows you a list of all your saved home locations."
  580. })
  581. },
  582. {
  583. "SyntaxCommandTPR", string.Join(NewLine, new[]
  584. {
  585. "A Syntax Error Occurred!",
  586. "You can only use the /tpr command as follows:",
  587. "/tpr \"player name\" - Sends out a teleport request to 'player name'."
  588. })
  589. },
  590. {
  591. "SyntaxCommandTPA", string.Join(NewLine, new[]
  592. {
  593. "A Syntax Error Occurred!",
  594. "You can only use the /tpa command as follows:",
  595. "/tpa - Accepts an incoming teleport request."
  596. })
  597. },
  598. {
  599. "SyntaxCommandTPC", string.Join(NewLine, new[]
  600. {
  601. "A Syntax Error Occurred!",
  602. "You can only use the /tpc command as follows:",
  603. "/tpc - Cancels an teleport request."
  604. })
  605. },
  606. {
  607. "SyntaxConsoleCommandToPos", string.Join(NewLine, new[]
  608. {
  609. "A Syntax Error Occurred!",
  610. "You can only use the teleport.topos console command as follows:",
  611. " > teleport.topos \"player\" x y z"
  612. })
  613. },
  614. {
  615. "SyntaxConsoleCommandToPlayer", string.Join(NewLine, new[]
  616. {
  617. "A Syntax Error Occurred!",
  618. "You can only use the teleport.toplayer console command as follows:",
  619. " > teleport.toplayer \"player\" \"target player\""
  620. })
  621. },
  622. {"LogTeleport", "{0} teleported to {1}."},
  623. {"LogTeleportPlayer", "{0} teleported {1} to {2}."},
  624. {"LogTeleportBack", "{0} teleported back to previous location."}
  625. }, this);
  626. Config.Settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  627. Config.Settings.Converters = new JsonConverter[] { new UnityVector3Converter() };
  628. try
  629. {
  630. configData = Config.ReadObject<ConfigData>();
  631. }
  632. catch (Exception)
  633. {
  634. Puts("Corrupt config, loading default...");
  635. LoadDefaultConfig();
  636. }
  637. if (!(configData.Version == Version))
  638. {
  639. if (configData.Home.VIPHomesLimits == null)
  640. {
  641. configData.Home.VIPHomesLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  642. configData.Home.VIPDailyLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  643. configData.Home.VIPCooldowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  644. configData.TPR.VIPDailyLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  645. configData.TPR.VIPCooldowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  646. configData.Town.VIPDailyLimits = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  647. configData.Town.VIPCooldowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  648. }
  649. if (configData.Home.VIPCountdowns == null)
  650. {
  651. configData.Home.VIPCountdowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  652. configData.TPR.VIPCountdowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  653. configData.Town.VIPCountdowns = new Dictionary<string, int> { { ConfigDefaultPermVip, 5 } };
  654. }
  655. if (configData.Version <= new VersionNumber(1, 0, 4))
  656. configData.Home.AllowAboveFoundation = true;
  657. if (configData.Version < new VersionNumber(1, 0, 14))
  658. {
  659. configData.Home.UsableIntoBuildingBlocked = true;
  660. configData.TPR.UsableIntoBuildingBlocked = true;
  661. }
  662. configData.Version = Version;
  663. Config.WriteObject(configData, true);
  664. }
  665. dataAdmin = GetFile(nameof(NTeleportation) + "Admin");
  666. Admin = dataAdmin.ReadObject<Dictionary<ulong, AdminData>>();
  667. dataHome = GetFile(nameof(NTeleportation) + "Home");
  668. Home = dataHome.ReadObject<Dictionary<ulong, HomeData>>();
  669. dataTPR = GetFile(nameof(NTeleportation) + "TPR");
  670. TPR = dataTPR.ReadObject<Dictionary<ulong, TeleportData>>();
  671. dataTown = GetFile(nameof(NTeleportation) + "Town");
  672. Town = dataTown.ReadObject<Dictionary<ulong, TeleportData>>();
  673. cmd.AddConsoleCommand("teleport.toplayer", this, ccmdTeleport);
  674. cmd.AddConsoleCommand("teleport.topos", this, ccmdTeleport);
  675. permission.RegisterPermission(PermDeleteHome, this);
  676. permission.RegisterPermission(PermHomeHomes, this);
  677. permission.RegisterPermission(PermImportHomes, this);
  678. permission.RegisterPermission(PermRadiusHome, this);
  679. permission.RegisterPermission(PermTp, this);
  680. permission.RegisterPermission(PermTpB, this);
  681. permission.RegisterPermission(PermTpConsole, this);
  682. permission.RegisterPermission(PermTpHome, this);
  683. permission.RegisterPermission(PermTpTown, this);
  684. permission.RegisterPermission(PermTpN, this);
  685. permission.RegisterPermission(PermTpL, this);
  686. permission.RegisterPermission(PermTpRemove, this);
  687. permission.RegisterPermission(PermTpSave, this);
  688. permission.RegisterPermission(PermWipeHomes, this);
  689. permission.RegisterPermission(PermCraftHome, this);
  690. permission.RegisterPermission(PermCraftTown, this);
  691. permission.RegisterPermission(PermCraftTpR, this);
  692. foreach (var key in configData.Home.VIPCooldowns.Keys)
  693. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  694. foreach (var key in configData.Home.VIPCountdowns.Keys)
  695. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  696. foreach (var key in configData.Home.VIPDailyLimits.Keys)
  697. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  698. foreach (var key in configData.Home.VIPHomesLimits.Keys)
  699. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  700. foreach (var key in configData.TPR.VIPCooldowns.Keys)
  701. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  702. foreach (var key in configData.TPR.VIPCountdowns.Keys)
  703. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  704. foreach (var key in configData.TPR.VIPDailyLimits.Keys)
  705. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  706. foreach (var key in configData.Town.VIPCooldowns.Keys)
  707. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  708. foreach (var key in configData.Town.VIPCountdowns.Keys)
  709. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  710. foreach (var key in configData.Town.VIPDailyLimits.Keys)
  711. if (!permission.PermissionExists(key, this)) permission.RegisterPermission(key, this);
  712. }
  713. private DynamicConfigFile GetFile(string name)
  714. {
  715. var file = Interface.Oxide.DataFileSystem.GetFile(name);
  716. file.Settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
  717. file.Settings.Converters = new JsonConverter[] { new UnityVector3Converter(), new CustomComparerDictionaryCreationConverter<string>(StringComparer.OrdinalIgnoreCase) };
  718. return file;
  719. }
  720. void OnServerInitialized()
  721. {
  722. boundary = TerrainMeta.Size.x / 2;
  723. CheckPerms(configData.Home.VIPHomesLimits);
  724. CheckPerms(configData.Home.VIPDailyLimits);
  725. CheckPerms(configData.Home.VIPCooldowns);
  726. CheckPerms(configData.TPR.VIPDailyLimits);
  727. CheckPerms(configData.TPR.VIPCooldowns);
  728. CheckPerms(configData.Town.VIPDailyLimits);
  729. CheckPerms(configData.Town.VIPCooldowns);
  730. foreach (var item in configData.Settings.BlockedItems)
  731. {
  732. var definition = ItemManager.FindItemDefinition(item.Key);
  733. if (definition == null)
  734. {
  735. Puts("Blocked item not found: {0}", item.Key);
  736. continue;
  737. }
  738. ReverseBlockedItems[definition.itemid] = item.Value;
  739. }
  740. }
  741. void OnServerSave()
  742. {
  743. SaveTeleportsAdmin();
  744. SaveTeleportsHome();
  745. SaveTeleportsTPR();
  746. SaveTeleportsTown();
  747. }
  748. void OnServerShutdown() => OnServerSave();
  749. void Unload() => OnServerSave();
  750. void OnEntityTakeDamage(BaseCombatEntity entity, HitInfo hitinfo)
  751. {
  752. var player = entity.ToPlayer();
  753. if (player == null || hitinfo == null) return;
  754. if (hitinfo.damageTypes.Has(DamageType.Fall) && teleporting.Contains(player.userID))
  755. {
  756. hitinfo.damageTypes = new DamageTypeList();
  757. teleporting.Remove(player.userID);
  758. }
  759. TeleportTimer teleportTimer;
  760. if (!TeleportTimers.TryGetValue(player.userID, out teleportTimer)) return;
  761. NextTick(() =>
  762. {
  763. if (hitinfo.damageTypes.Total() <= 0) return;
  764. PrintMsgL(teleportTimer.OriginPlayer, "Interrupted");
  765. if (teleportTimer.TargetPlayer != null)
  766. PrintMsgL(teleportTimer.TargetPlayer, "InterruptedTarget", teleportTimer.OriginPlayer.displayName);
  767. teleportTimer.Timer.Destroy();
  768. TeleportTimers.Remove(player.userID);
  769. });
  770. }
  771. void OnPlayerSleepEnded(BasePlayer player)
  772. {
  773. if (teleporting.Contains(player.userID))
  774. timer.Once(3, () => { teleporting.Remove(player.userID); });
  775. }
  776. void OnPlayerDisconnected(BasePlayer player)
  777. {
  778. Timer reqTimer;
  779. if (PendingRequests.TryGetValue(player.userID, out reqTimer))
  780. {
  781. var originPlayer = PlayersRequests[player.userID];
  782. PrintMsgL(originPlayer, "RequestTargetOff");
  783. reqTimer.Destroy();
  784. PendingRequests.Remove(player.userID);
  785. PlayersRequests.Remove(player.userID);
  786. PlayersRequests.Remove(originPlayer.userID);
  787. }
  788. TeleportTimer teleportTimer;
  789. if (TeleportTimers.TryGetValue(player.userID, out teleportTimer))
  790. {
  791. teleportTimer.Timer.Destroy();
  792. TeleportTimers.Remove(player.userID);
  793. }
  794. teleporting.Remove(player.userID);
  795. }
  796. private void SaveTeleportsAdmin()
  797. {
  798. if (Admin == null || !changedAdmin) return;
  799. dataAdmin.WriteObject(Admin);
  800. changedAdmin = false;
  801. }
  802. private void SaveTeleportsHome()
  803. {
  804. if (Home == null || !changedHome) return;
  805. dataHome.WriteObject(Home);
  806. changedHome = false;
  807. }
  808. private void SaveTeleportsTPR()
  809. {
  810. if (TPR == null || !changedTPR) return;
  811. dataTPR.WriteObject(TPR);
  812. changedTPR = false;
  813. }
  814. private void SaveTeleportsTown()
  815. {
  816. if (Town == null || !changedTown) return;
  817. dataTown.WriteObject(Town);
  818. changedTown = false;
  819. }
  820. private void SaveLocation(BasePlayer player)
  821. {
  822. if (!IsAllowed(player, PermTpB)) return;
  823. AdminData adminData;
  824. if (!Admin.TryGetValue(player.userID, out adminData))
  825. Admin[player.userID] = adminData = new AdminData();
  826. adminData.PreviousLocation = player.transform.position;
  827. changedAdmin = true;
  828. PrintMsgL(player, "AdminTPBackSave");
  829. }
  830. [ChatCommand("tp")]
  831. private void cmdChatTeleport(BasePlayer player, string command, string[] args)
  832. {
  833. if (!IsAllowedMsg(player, PermTp)) return;
  834. BasePlayer target;
  835. float x, y, z;
  836. switch (args.Length)
  837. {
  838. case 1:
  839. target = FindPlayersSingle(args[0], player);
  840. if (target == null) return;
  841. if (target == player)
  842. {
  843. PrintMsgL(player, "CantTeleportToSelf");
  844. return;
  845. }
  846. TeleportToPlayer(player, target);
  847. PrintMsgL(player, "AdminTP", target.displayName);
  848. Puts(_("LogTeleport", null, player.displayName, target.displayName));
  849. if (configData.Admin.AnnounceTeleportToTarget)
  850. PrintMsgL(target, "AdminTPTarget", player.displayName);
  851. break;
  852. case 2:
  853. var origin = FindPlayersSingle(args[0], player);
  854. if (origin == null) return;
  855. target = FindPlayersSingle(args[1], player);
  856. if (target == null) return;
  857. if (target == origin)
  858. {
  859. PrintMsgL(player, "CantTeleportPlayerToSelf");
  860. return;
  861. }
  862. TeleportToPlayer(origin, target);
  863. PrintMsgL(player, "AdminTPPlayers", origin.displayName, target.displayName);
  864. PrintMsgL(origin, "AdminTPPlayer", player.displayName, target.displayName);
  865. PrintMsgL(target, "AdminTPPlayerTarget", player.displayName, origin.displayName);
  866. Puts(_("LogTeleportPlayer", null, player.displayName, origin.displayName, target.displayName));
  867. break;
  868. case 3:
  869. if (!float.TryParse(args[0], out x) || !float.TryParse(args[1], out y) || !float.TryParse(args[2], out z))
  870. {
  871. PrintMsgL(player, "InvalidCoordinates");
  872. return;
  873. }
  874. if (!CheckBoundaries(x, y, z))
  875. {
  876. PrintMsgL(player, "AdminTPOutOfBounds");
  877. PrintMsgL(player, "AdminTPBoundaries", boundary);
  878. return;
  879. }
  880. TeleportToPosition(player, x, y, z);
  881. PrintMsgL(player, "AdminTPCoordinates", player.transform.position);
  882. Puts(_("LogTeleport", null, player.displayName, player.transform.position));
  883. break;
  884. case 4:
  885. target = FindPlayersSingle(args[0], player);
  886. if (target == null) return;
  887. if (!float.TryParse(args[0], out x) || !float.TryParse(args[1], out y) || !float.TryParse(args[2], out z))
  888. {
  889. PrintMsgL(player, "InvalidCoordinates");
  890. return;
  891. }
  892. if (!CheckBoundaries(x, y, z))
  893. {
  894. PrintMsgL(player, "AdminTPOutOfBounds");
  895. PrintMsgL(player, "AdminTPBoundaries", boundary);
  896. return;
  897. }
  898. TeleportToPosition(target, x, y, z);
  899. if (player == target)
  900. {
  901. PrintMsgL(player, "AdminTPCoordinates", player.transform.position);
  902. Puts(_("LogTeleport", null, player.displayName, player.transform.position));
  903. }
  904. else
  905. {
  906. PrintMsgL(player, "AdminTPTargetCoordinates", target.displayName, player.transform.position);
  907. PrintMsgL(target, "AdminTPTargetCoordinatesTarget", player.displayName, player.transform.position);
  908. Puts(_("LogTeleportPlayer", null, player.displayName, target.displayName, player.transform.position));
  909. }
  910. break;
  911. default:
  912. PrintMsgL(player, "SyntaxCommandTP");
  913. break;
  914. }
  915. }
  916. [ChatCommand("tpn")]
  917. private void cmdChatTeleportNear(BasePlayer player, string command, string[] args)
  918. {
  919. if (!IsAllowedMsg(player, PermTpN)) return;
  920. switch (args.Length)
  921. {
  922. case 1:
  923. case 2:
  924. var target = FindPlayersSingle(args[0], player);
  925. if (target == null) return;
  926. if (target == player)
  927. {
  928. PrintMsgL(player, "CantTeleportToSelf");
  929. return;
  930. }
  931. int distance;
  932. if (args.Length != 2 || !int.TryParse(args[1], out distance))
  933. distance = configData.Admin.TeleportNearDefaultDistance;
  934. float x = UnityEngine.Random.Range(-distance, distance);
  935. var z = (float)System.Math.Sqrt(System.Math.Pow(distance, 2) - System.Math.Pow(x, 2));
  936. var destination = target.transform.position;
  937. destination.x = destination.x - x;
  938. destination.z = destination.z - z;
  939. Teleport(player, GetGroundBuilding(destination));
  940. PrintMsgL(player, "AdminTP", target.displayName);
  941. Puts(_("LogTeleport", null, player.displayName, target.displayName));
  942. if (configData.Admin.AnnounceTeleportToTarget)
  943. PrintMsgL(target, "AdminTPTarget", player.displayName);
  944. break;
  945. default:
  946. PrintMsgL(player, "SyntaxCommandTPN");
  947. break;
  948. }
  949. }
  950. [ChatCommand("tpl")]
  951. private void cmdChatTeleportLocation(BasePlayer player, string command, string[] args)
  952. {
  953. if (!IsAllowedMsg(player, PermTpL)) return;
  954. AdminData adminData;
  955. if (!Admin.TryGetValue(player.userID, out adminData) || adminData.Locations.Count <= 0)
  956. {
  957. PrintMsgL(player, "AdminLocationListEmpty");
  958. return;
  959. }
  960. switch (args.Length)
  961. {
  962. case 0:
  963. PrintMsgL(player, "AdminLocationList");
  964. foreach (var location in adminData.Locations)
  965. PrintMsgL(player, $"{location.Key} {location.Value}");
  966. break;
  967. case 1:
  968. Vector3 loc;
  969. if (!adminData.Locations.TryGetValue(args[0], out loc))
  970. {
  971. PrintMsgL(player, "LocationNotFound");
  972. return;
  973. }
  974. Teleport(player, loc);
  975. PrintMsgL(player, "AdminTPLocation", args[0]);
  976. break;
  977. default:
  978. PrintMsgL(player, "SyntaxCommandTPL");
  979. break;
  980. }
  981. }
  982. [ChatCommand("tpsave")]
  983. private void cmdChatSaveTeleportLocation(BasePlayer player, string command, string[] args)
  984. {
  985. if (!IsAllowedMsg(player, PermTpSave)) return;
  986. if (args.Length != 1)
  987. {
  988. PrintMsgL(player, "SyntaxCommandTPSave");
  989. return;
  990. }
  991. AdminData adminData;
  992. if (!Admin.TryGetValue(player.userID, out adminData))
  993. Admin[player.userID] = adminData = new AdminData();
  994. Vector3 location;
  995. if (adminData.Locations.TryGetValue(args[0], out location))
  996. {
  997. PrintMsgL(player, "LocationExists", location);
  998. return;
  999. }
  1000. var positionCoordinates = player.transform.position;
  1001. foreach (var loc in adminData.Locations)
  1002. {
  1003. if (Vector3.Distance(positionCoordinates, loc.Value) < configData.Admin.LocationRadius)
  1004. {
  1005. PrintMsgL(player, "LocationExistsNearby", loc.Key);
  1006. return;
  1007. }
  1008. }
  1009. adminData.Locations[args[0]] = positionCoordinates;
  1010. PrintMsgL(player, "AdminTPLocationSave");
  1011. changedAdmin = true;
  1012. }
  1013. [ChatCommand("tpremove")]
  1014. private void cmdChatRemoveTeleportLocation(BasePlayer player, string command, string[] args)
  1015. {
  1016. if (!IsAllowedMsg(player, PermTpRemove)) return;
  1017. if (args.Length != 1)
  1018. {
  1019. PrintMsgL(player, "SyntaxCommandTPRemove");
  1020. return;
  1021. }
  1022. AdminData adminData;
  1023. if (!Admin.TryGetValue(player.userID, out adminData) || adminData.Locations.Count <= 0)
  1024. {
  1025. PrintMsgL(player, "AdminLocationListEmpty");
  1026. return;
  1027. }
  1028. if (adminData.Locations.Remove(args[0]))
  1029. {
  1030. PrintMsgL(player, "AdminTPLocationRemove", args[0]);
  1031. changedAdmin = true;
  1032. return;
  1033. }
  1034. PrintMsgL(player, "LocationNotFound");
  1035. }
  1036. [ChatCommand("tpb")]
  1037. private void cmdChatTeleportBack(BasePlayer player, string command, string[] args)
  1038. {
  1039. if (!IsAllowedMsg(player, PermTpB)) return;
  1040. if (args.Length != 0)
  1041. {
  1042. PrintMsgL(player, "SyntaxCommandTPB");
  1043. return;
  1044. }
  1045. AdminData adminData;
  1046. if (!Admin.TryGetValue(player.userID, out adminData) || adminData.PreviousLocation == default(Vector3))
  1047. {
  1048. PrintMsgL(player, "NoPreviousLocationSaved");
  1049. return;
  1050. }
  1051. Teleport(player, adminData.PreviousLocation);
  1052. adminData.PreviousLocation = default(Vector3);
  1053. changedAdmin = true;
  1054. PrintMsgL(player, "AdminTPBack");
  1055. Puts(_("LogTeleportBack", null, player.displayName));
  1056. }
  1057. [ChatCommand("sethome")]
  1058. private void cmdChatSetHome(BasePlayer player, string command, string[] args)
  1059. {
  1060. if (!configData.Settings.HomesEnabled) return;
  1061. if (args.Length != 1)
  1062. {
  1063. PrintMsgL(player, "SyntaxCommandSetHome");
  1064. return;
  1065. }
  1066. var err = CheckPlayer(player, false, CanCraftHome(player));
  1067. if (err != null)
  1068. {
  1069. PrintMsgL(player, $"Home{err}");
  1070. return;
  1071. }
  1072. if (!player.CanBuild())
  1073. {
  1074. PrintMsgL(player, "HomeTPBuildingBlocked");
  1075. return;
  1076. }
  1077. if (!args[0].All(char.IsLetterOrDigit))
  1078. {
  1079. PrintMsgL(player, "InvalidCharacter");
  1080. return;
  1081. }
  1082. HomeData homeData;
  1083. if (!Home.TryGetValue(player.userID, out homeData))
  1084. Home[player.userID] = homeData = new HomeData();
  1085. var limit = GetHigher(player, configData.Home.VIPHomesLimits, configData.Home.HomesLimit);
  1086. if (homeData.Locations.Count >= limit)
  1087. {
  1088. PrintMsgL(player, "HomeMaxLocations", limit);
  1089. return;
  1090. }
  1091. Vector3 location;
  1092. if (homeData.Locations.TryGetValue(args[0], out location))
  1093. {
  1094. PrintMsgL(player, "HomeExists", location);
  1095. return;
  1096. }
  1097. var positionCoordinates = player.transform.position;
  1098. foreach (var loc in homeData.Locations)
  1099. {
  1100. if (Vector3.Distance(positionCoordinates, loc.Value) < configData.Home.LocationRadius)
  1101. {
  1102. PrintMsgL(player, "HomeExistsNearby", loc.Key);
  1103. return;
  1104. }
  1105. }
  1106. err = CanPlayerTeleport(player);
  1107. if (err != null)
  1108. {
  1109. SendReply(player, err);
  1110. return;
  1111. }
  1112. if (player.IsAdmin)
  1113. player.SendConsoleCommand("ddraw.sphere", 60f, Color.blue, GetGround(positionCoordinates), 2.5f);
  1114. err = CheckFoundation(player.userID, positionCoordinates);
  1115. if (err != null)
  1116. {
  1117. PrintMsgL(player, err);
  1118. return;
  1119. }
  1120. err = CheckInsideBlock(positionCoordinates);
  1121. if (err != null)
  1122. {
  1123. PrintMsgL(player, err);
  1124. return;
  1125. }
  1126. homeData.Locations[args[0]] = positionCoordinates;
  1127. changedHome = true;
  1128. PrintMsgL(player, "HomeSave");
  1129. PrintMsgL(player, "HomeQuota", homeData.Locations.Count, limit);
  1130. }
  1131. [ChatCommand("removehome")]
  1132. private void cmdChatRemoveHome(BasePlayer player, string command, string[] args)
  1133. {
  1134. if (!configData.Settings.HomesEnabled) return;
  1135. if (args.Length != 1)
  1136. {
  1137. PrintMsgL(player, "SyntaxCommandRemoveHome");
  1138. return;
  1139. }
  1140. HomeData homeData;
  1141. if (!Home.TryGetValue(player.userID, out homeData) || homeData.Locations.Count <= 0)
  1142. {
  1143. PrintMsgL(player, "HomeListEmpty");
  1144. return;
  1145. }
  1146. if (homeData.Locations.Remove(args[0]))
  1147. {
  1148. changedHome = true;
  1149. PrintMsgL(player, "HomeRemove", args[0]);
  1150. }
  1151. else
  1152. PrintMsgL(player, "HomeNotFound");
  1153. }
  1154. [ChatCommand("home")]
  1155. private void cmdChatHome(BasePlayer player, string command, string[] args)
  1156. {
  1157. if (!configData.Settings.HomesEnabled) return;
  1158. if (args.Length == 0)
  1159. {
  1160. PrintMsgL(player, "SyntaxCommandHome");
  1161. if (IsAllowed(player)) PrintMsgL(player, "SyntaxCommandHomeAdmin");
  1162. return;
  1163. }
  1164. switch (args[0].ToLower())
  1165. {
  1166. case "add":
  1167. cmdChatSetHome(player, command, args.Skip(1).ToArray());
  1168. break;
  1169. case "list":
  1170. cmdChatListHome(player, command, args.Skip(1).ToArray());
  1171. break;
  1172. case "remove":
  1173. cmdChatRemoveHome(player, command, args.Skip(1).ToArray());
  1174. break;
  1175. case "radius":
  1176. cmdChatHomeRadius(player, command, args.Skip(1).ToArray());
  1177. break;
  1178. case "delete":
  1179. cmdChatHomeDelete(player, command, args.Skip(1).ToArray());
  1180. break;
  1181. case "tp":
  1182. cmdChatHomeAdminTP(player, command, args.Skip(1).ToArray());
  1183. break;
  1184. case "homes":
  1185. cmdChatHomeHomes(player, command, args.Skip(1).ToArray());
  1186. break;
  1187. case "wipe":
  1188. cmdChatWipeHomes(player, command, args.Skip(1).ToArray());
  1189. break;
  1190. default:
  1191. cmdChatHomeTP(player, command, args);
  1192. break;
  1193. }
  1194. }
  1195. [ChatCommand("radiushome")]
  1196. private void cmdChatHomeRadius(BasePlayer player, string command, string[] args)
  1197. {
  1198. if (!IsAllowedMsg(player, PermRadiusHome)) return;
  1199. float radius;
  1200. if (args.Length != 1 || !float.TryParse(args[0], out radius)) radius = 10;
  1201. var found = false;
  1202. foreach (var homeData in Home)
  1203. {
  1204. var toRemove = new List<string>();
  1205. var target = RustCore.FindPlayerById(homeData.Key)?.displayName ?? homeData.Key.ToString();
  1206. foreach (var location in homeData.Value.Locations)
  1207. {
  1208. if (Vector3.Distance(player.transform.position, location.Value) <= radius)
  1209. {
  1210. if (CheckFoundation(homeData.Key, location.Value) != null)
  1211. {
  1212. toRemove.Add(location.Key);
  1213. continue;
  1214. }
  1215. var entity = GetFoundationOwned(location.Value, homeData.Key);
  1216. if (entity == null) continue;
  1217. player.SendConsoleCommand("ddraw.text", 30f, Color.blue, entity.CenterPoint() + new Vector3(0, .5f), $"<size=20>{target} - {location.Key} {location.Value}</size>");
  1218. DrawBox(player, entity.CenterPoint(), entity.transform.rotation, entity.bounds.size);
  1219. PrintMsg(player, $"{target} - {location.Key} {location.Value}");
  1220. found = true;
  1221. }
  1222. }
  1223. foreach (var loc in toRemove)
  1224. {
  1225. homeData.Value.Locations.Remove(loc);
  1226. changedHome = true;
  1227. }
  1228. }
  1229. if (!found)
  1230. PrintMsgL(player, "HomeNoFound");
  1231. }
  1232. [ChatCommand("deletehome")]
  1233. private void cmdChatHomeDelete(BasePlayer player, string command, string[] args)
  1234. {
  1235. if (!IsAllowedMsg(player, PermDeleteHome)) return;
  1236. if (args.Length != 2)
  1237. {
  1238. PrintMsgL(player, "SyntaxCommandHomeDelete");
  1239. return;
  1240. }
  1241. var userId = FindPlayersSingleId(args[0], player);
  1242. if (userId <= 0) return;
  1243. HomeData targetHome;
  1244. if (!Home.TryGetValue(userId, out targetHome) || !targetHome.Locations.Remove(args[1]))
  1245. {
  1246. PrintMsgL(player, "HomeNotFound");
  1247. return;
  1248. }
  1249. changedHome = true;
  1250. PrintMsgL(player, "HomeDelete", args[0], args[1]);
  1251. }
  1252. [ChatCommand("tphome")]
  1253. private void cmdChatHomeAdminTP(BasePlayer player, string command, string[] args)
  1254. {
  1255. if (!IsAllowedMsg(player, PermTpHome)) return;
  1256. if (args.Length != 2)
  1257. {
  1258. PrintMsgL(player, "SyntaxCommandHomeAdminTP");
  1259. return;
  1260. }
  1261. var userId = FindPlayersSingleId(args[0], player);
  1262. if (userId <= 0) return;
  1263. HomeData targetHome;
  1264. Vector3 location;
  1265. if (!Home.TryGetValue(userId, out targetHome) || !targetHome.Locations.TryGetValue(args[1], out location))
  1266. {
  1267. PrintMsgL(player, "HomeNotFound");
  1268. return;
  1269. }
  1270. Teleport(player, location);
  1271. PrintMsgL(player, "HomeAdminTP", args[0], args[1]);
  1272. }
  1273. // Check that plugins are available and enabled for CheckEconomy()
  1274. private bool UseEconomy()
  1275. {
  1276. if((configData.Settings.UseEconomics && Economics) ||
  1277. (configData.Settings.UseServerRewards && ServerRewards))
  1278. {
  1279. return true;
  1280. }
  1281. return false;
  1282. }
  1283. // Check balance on multiple plugins and optionally withdraw money from the player
  1284. private bool CheckEconomy(BasePlayer player, double bypass, bool withdraw = false)
  1285. {
  1286. double balance = 0;
  1287. bool foundmoney = false;
  1288. // Check Economics first. If not in use or balance low, check ServerRewards below
  1289. if(configData.Settings.UseEconomics && Economics)
  1290. {
  1291. balance = (double)Economics?.CallHook("Balance", player.UserIDString);
  1292. if(balance >= bypass)
  1293. {
  1294. foundmoney = true;
  1295. if(withdraw == true)
  1296. {
  1297. var w = (bool)Economics?.CallHook("Withdraw", player.userID, bypass);
  1298. return w;
  1299. }
  1300. }
  1301. }
  1302. // No money via Economics, or plugin not in use. Try ServerRewards.
  1303. if(configData.Settings.UseServerRewards && ServerRewards)
  1304. {
  1305. object bal = ServerRewards?.Call("CheckPoints", player.userID);
  1306. balance = Convert.ToDouble(bal);
  1307. if(balance >= bypass && foundmoney == false)
  1308. {
  1309. foundmoney = true;
  1310. if(withdraw == true)
  1311. {
  1312. var w = (bool)ServerRewards?.Call("TakePoints", player.userID, (int)bypass);
  1313. return w;
  1314. }
  1315. }
  1316. }
  1317. // Just checking balance without withdrawal - did we find anything?
  1318. if(foundmoney == true)
  1319. {
  1320. return true;
  1321. }
  1322. return false;
  1323. }
  1324. private void cmdChatHomeTP(BasePlayer player, string command, string[] args)
  1325. {
  1326. if (!configData.Settings.HomesEnabled) return;
  1327. if (args.Length < 1)
  1328. {
  1329. PrintMsgL(player, "SyntaxCommandHome");
  1330. return;
  1331. }
  1332. var err = CheckPlayer(player, configData.Home.UsableOutOfBuildingBlocked, CanCraftHome(player));
  1333. if (err != null)
  1334. {
  1335. PrintMsgL(player, err);
  1336. return;
  1337. }
  1338. HomeData homeData;
  1339. if (!Home.TryGetValue(player.userID, out homeData) || homeData.Locations.Count <= 0)
  1340. {
  1341. PrintMsgL(player, "HomeListEmpty");
  1342. return;
  1343. }
  1344. Vector3 location;
  1345. if (!homeData.Locations.TryGetValue(args[0], out location))
  1346. {
  1347. PrintMsgL(player, "HomeNotFound");
  1348. return;
  1349. }
  1350. err = CheckFoundation(player.userID, location) ?? CheckTargetLocation(player, location, configData.Home.UsableIntoBuildingBlocked, configData.Home.CupOwnerAllowOnBuildingBlocked);
  1351. if (err != null)
  1352. {
  1353. PrintMsgL(player, "HomeRemovedInvalid", args[0]);
  1354. homeData.Locations.Remove(args[0]);
  1355. changedHome = true;
  1356. return;
  1357. }
  1358. err = CheckInsideBlock(location);
  1359. if (err != null)
  1360. {
  1361. PrintMsgL(player, "HomeRemovedInsideBlock", args[0]);
  1362. homeData.Locations.Remove(args[0]);
  1363. changedHome = true;
  1364. return;
  1365. }
  1366. var timestamp = Facepunch.Math.Epoch.Current;
  1367. var currentDate = DateTime.Now.ToString("d");
  1368. if (homeData.Teleports.Date != currentDate)
  1369. {
  1370. homeData.Teleports.Amount = 0;
  1371. homeData.Teleports.Date = currentDate;
  1372. }
  1373. var cooldown = GetLower(player, configData.Home.VIPCooldowns, configData.Home.Cooldown);
  1374. if (cooldown > 0 && timestamp - homeData.Teleports.Timestamp < cooldown)
  1375. {
  1376. var cmdSent = "";
  1377. bool foundmoney = CheckEconomy(player, configData.Home.Bypass);
  1378. try
  1379. {
  1380. cmdSent = args[1].ToLower();
  1381. }
  1382. catch {}
  1383. bool payalso = false;
  1384. if(configData.Home.Pay > 0)
  1385. {
  1386. payalso = true;
  1387. }
  1388. if((configData.Settings.BypassCMD != null) && (cmdSent == configData.Settings.BypassCMD.ToLower()))
  1389. {
  1390. if(foundmoney == true)
  1391. {
  1392. CheckEconomy(player, configData.Home.Bypass, true);
  1393. PrintMsgL(player, "HomeTPCooldownBypass", configData.Home.Bypass);
  1394. if(payalso)
  1395. {
  1396. PrintMsgL(player, "PayToHome", configData.Home.Pay);
  1397. }
  1398. }
  1399. else
  1400. {
  1401. PrintMsgL(player, "HomeTPCooldownBypassF", configData.Home.Bypass);
  1402. return;
  1403. }
  1404. }
  1405. else if(UseEconomy())
  1406. {
  1407. var remain = cooldown - (timestamp - homeData.Teleports.Timestamp);
  1408. PrintMsgL(player, "HomeTPCooldown", FormatTime(remain));
  1409. if(configData.Home.Bypass > 0 && configData.Settings.BypassCMD != null)
  1410. {
  1411. PrintMsgL(player, "HomeTPCooldownBypassP", configData.Home.Bypass);
  1412. PrintMsgL(player, "HomeTPCooldownBypassP2", configData.Settings.BypassCMD);
  1413. }
  1414. return;
  1415. }
  1416. else
  1417. {
  1418. var remain = cooldown - (timestamp - homeData.Teleports.Timestamp);
  1419. PrintMsgL(player, "HomeTPCooldown", FormatTime(remain));
  1420. return;
  1421. }
  1422. }
  1423. var limit = GetHigher(player, configData.Home.VIPDailyLimits, configData.Home.DailyLimit);
  1424. if (limit > 0 && homeData.Teleports.Amount >= limit)
  1425. {
  1426. PrintMsgL(player, "HomeTPLimitReached", limit);
  1427. return;
  1428. }
  1429. if (TeleportTimers.ContainsKey(player.userID))
  1430. {
  1431. PrintMsgL(player, "TeleportPending");
  1432. return;
  1433. }
  1434. err = CanPlayerTeleport(player);
  1435. if (err != null)
  1436. {
  1437. SendReply(player, err);
  1438. return;
  1439. }
  1440. err = CheckItems(player);
  1441. if (err != null)
  1442. {
  1443. PrintMsgL(player, "TPBlockedItem", err);
  1444. return;
  1445. }
  1446. var countdown = GetLower(player, configData.Home.VIPCountdowns, configData.Home.Countdown);
  1447. TeleportTimers[player.userID] = new TeleportTimer
  1448. {
  1449. OriginPlayer = player,
  1450. Timer = timer.Once(countdown, () =>
  1451. {
  1452. err = CheckPlayer(player, configData.Home.UsableOutOfBuildingBlocked, CanCraftHome(player));
  1453. if (err != null)
  1454. {
  1455. PrintMsgL(player, "Interrupted");
  1456. PrintMsgL(player, err);
  1457. TeleportTimers.Remove(player.userID);
  1458. return;
  1459. }
  1460. err = CanPlayerTeleport(player);
  1461. if (err != null)
  1462. {
  1463. PrintMsgL(player, "Interrupted");
  1464. SendReply(player, err);
  1465. TeleportTimers.Remove(player.userID);
  1466. return;
  1467. }
  1468. err = CheckItems(player);
  1469. if (err != null)
  1470. {
  1471. PrintMsgL(player, "Interrupted");
  1472. PrintMsgL(player, "TPBlockedItem", err);
  1473. TeleportTimers.Remove(player.userID);
  1474. return;
  1475. }
  1476. err = CheckFoundation(player.userID, location) ?? CheckTargetLocation(player, location, configData.Home.UsableIntoBuildingBlocked, configData.Home.CupOwnerAllowOnBuildingBlocked);
  1477. if (err != null)
  1478. {
  1479. PrintMsgL(player, "HomeRemovedInvalid", args[0]);
  1480. homeData.Locations.Remove(args[0]);
  1481. changedHome = true;
  1482. return;
  1483. }
  1484. err = CheckInsideBlock(location);
  1485. if (err != null)
  1486. {
  1487. PrintMsgL(player, "HomeRemovedInsideBlock", args[0]);
  1488. homeData.Locations.Remove(args[0]);
  1489. changedHome = true;
  1490. return;
  1491. }
  1492. if(UseEconomy())
  1493. {
  1494. if (configData.Home.Pay > 0 && !CheckEconomy(player, configData.Home.Pay))
  1495. {
  1496. PrintMsgL(player, "Interrupted");
  1497. PrintMsgL(player, "TPNoMoney", configData.Home.Pay);
  1498. TeleportTimers.Remove(player.userID);
  1499. return;
  1500. }
  1501. else if(configData.Home.Pay > 0)
  1502. {
  1503. var w = CheckEconomy(player, (double)configData.Home.Pay, true);
  1504. PrintMsgL(player, "TPMoney", (double)configData.Home.Pay);
  1505. }
  1506. }
  1507. Teleport(player, location);
  1508. homeData.Teleports.Amount++;
  1509. homeData.Teleports.Timestamp = timestamp;
  1510. changedHome = true;
  1511. PrintMsgL(player, "HomeTP", args[0]);
  1512. if (limit > 0) PrintMsgL(player, "HomeTPAmount", limit - homeData.Teleports.Amount);
  1513. TeleportTimers.Remove(player.userID);
  1514. })
  1515. };
  1516. PrintMsgL(player, "HomeTPStarted", args[0], countdown);
  1517. }
  1518. [ChatCommand("listhomes")]
  1519. private void cmdChatListHome(BasePlayer player, string command, string[] args)
  1520. {
  1521. if (!configData.Settings.HomesEnabled) return;
  1522. if (args.Length != 0)
  1523. {
  1524. PrintMsgL(player, "SyntaxCommandListHomes");
  1525. return;
  1526. }
  1527. HomeData homeData;
  1528. if (!Home.TryGetValue(player.userID, out homeData) || homeData.Locations.Count <= 0)
  1529. {
  1530. PrintMsgL(player, "HomeListEmpty");
  1531. return;
  1532. }
  1533. PrintMsgL(player, "HomeList");
  1534. if (configData.Home.CheckValidOnList)
  1535. {
  1536. var toRemove = new List<string>();
  1537. foreach (var location in homeData.Locations)
  1538. {
  1539. var err = CheckFoundation(player.userID, location.Value);
  1540. if (err != null)
  1541. {
  1542. toRemove.Add(location.Key);
  1543. continue;
  1544. }
  1545. PrintMsgL(player, $"{location.Key} {location.Value}");
  1546. }
  1547. foreach (var loc in toRemove)
  1548. {
  1549. PrintMsgL(player, "HomeRemovedInvalid", loc);
  1550. homeData.Locations.Remove(loc);
  1551. changedHome = true;
  1552. }
  1553. return;
  1554. }
  1555. foreach (var location in homeData.Locations)
  1556. PrintMsgL(player, $"{location.Key} {location.Value}");
  1557. }
  1558. [ChatCommand("homehomes")]
  1559. private void cmdChatHomeHomes(BasePlayer player, string command, string[] args)
  1560. {
  1561. if (!IsAllowedMsg(player, PermHomeHomes)) return;
  1562. if (args.Length != 1)
  1563. {
  1564. PrintMsgL(player, "SyntaxCommandHomeHomes");
  1565. return;
  1566. }
  1567. var userId = FindPlayersSingleId(args[0], player);
  1568. if (userId <= 0) return;
  1569. HomeData homeData;
  1570. if (!Home.TryGetValue(userId, out homeData) || homeData.Locations.Count <= 0)
  1571. {
  1572. PrintMsgL(player, "HomeListEmpty");
  1573. return;
  1574. }
  1575. PrintMsgL(player, "HomeList");
  1576. var toRemove = new List<string>();
  1577. foreach (var location in homeData.Locations)
  1578. {
  1579. var err = CheckFoundation(userId, location.Value);
  1580. if (err != null)
  1581. {
  1582. toRemove.Add(location.Key);
  1583. continue;
  1584. }
  1585. PrintMsgL(player, $"{location.Key} {location.Value}");
  1586. }
  1587. foreach (var loc in toRemove)
  1588. {
  1589. PrintMsgL(player, "HomeRemovedInvalid", loc);
  1590. homeData.Locations.Remove(loc);
  1591. changedHome = true;
  1592. }
  1593. }
  1594. [ChatCommand("tpr")]
  1595. private void cmdChatTeleportRequest(BasePlayer player, string command, string[] args)
  1596. {
  1597. if (!configData.Settings.TPREnabled) return;
  1598. if (args.Length != 1)
  1599. {
  1600. PrintMsgL(player, "SyntaxCommandTPR");
  1601. return;
  1602. }
  1603. var targets = FindPlayersOnline(args[0]);
  1604. if (targets.Count <= 0)
  1605. {
  1606. PrintMsgL(player, "PlayerNotFound");
  1607. return;
  1608. }
  1609. if (targets.Count > 1)
  1610. {
  1611. PrintMsgL(player, "MultiplePlayers", string.Join(", ", targets.ConvertAll(p => p.displayName).ToArray()));
  1612. return;
  1613. }
  1614. var target = targets[0];
  1615. if (target == player)
  1616. {
  1617. PrintMsgL(player, "CantTeleportToSelf");
  1618. return;
  1619. }
  1620. var err = CheckPlayer(player, configData.TPR.UsableOutOfBuildingBlocked, CanCraftTPR(player));
  1621. if (err != null)
  1622. {
  1623. PrintMsgL(player, err);
  1624. return;
  1625. }
  1626. err = CheckTargetLocation(target, target.transform.position, configData.TPR.UsableIntoBuildingBlocked, configData.TPR.CupOwnerAllowOnBuildingBlocked);
  1627. if (err != null)
  1628. {
  1629. PrintMsgL(player, err);
  1630. return;
  1631. }
  1632. var timestamp = Facepunch.Math.Epoch.Current;
  1633. var currentDate = DateTime.Now.ToString("d");
  1634. TeleportData tprData;
  1635. if (!TPR.TryGetValue(player.userID, out tprData))
  1636. TPR[player.userID] = tprData = new TeleportData();
  1637. if (tprData.Date != currentDate)
  1638. {
  1639. tprData.Amount = 0;
  1640. tprData.Date = currentDate;
  1641. }
  1642. var cooldown = GetLower(player, configData.TPR.VIPCooldowns, configData.TPR.Cooldown);
  1643. if (cooldown > 0 && timestamp - tprData.Timestamp < cooldown)
  1644. {
  1645. var cmdSent = "";
  1646. bool foundmoney = CheckEconomy(player, configData.TPR.Bypass);
  1647. try
  1648. {
  1649. cmdSent = args[1].ToLower();
  1650. }
  1651. catch {}
  1652. bool payalso = false;
  1653. if(configData.TPR.Pay > 0)
  1654. {
  1655. payalso = true;
  1656. }
  1657. if((configData.Settings.BypassCMD != null) && (cmdSent == configData.Settings.BypassCMD.ToLower()))
  1658. {
  1659. if(foundmoney == true)
  1660. {
  1661. CheckEconomy(player, configData.TPR.Bypass, true);
  1662. PrintMsgL(player, "TPRCooldownBypass", configData.TPR.Bypass);
  1663. if(payalso)
  1664. {
  1665. PrintMsgL(player, "PayToTPR", configData.TPR.Pay);
  1666. }
  1667. }
  1668. else
  1669. {
  1670. PrintMsgL(player, "TPRCooldownBypassF", configData.TPR.Bypass);
  1671. return;
  1672. }
  1673. }
  1674. else if(UseEconomy())
  1675. {
  1676. var remain = cooldown - (timestamp - tprData.Timestamp);
  1677. PrintMsgL(player, "TPRCooldown", FormatTime(remain));
  1678. if(configData.TPR.Bypass > 0 && configData.Settings.BypassCMD != null)
  1679. {
  1680. PrintMsgL(player, "TPRCooldownBypassP", configData.TPR.Bypass);
  1681. PrintMsgL(player, "TPRCooldownBypassP2", configData.Settings.BypassCMD);
  1682. }
  1683. return;
  1684. }
  1685. else
  1686. {
  1687. var remain = cooldown - (timestamp - tprData.Timestamp);
  1688. PrintMsgL(player, "TPRCooldown", FormatTime(remain));
  1689. return;
  1690. }
  1691. }
  1692. var limit = GetHigher(player, configData.TPR.VIPDailyLimits, configData.TPR.DailyLimit);
  1693. if (limit > 0 && tprData.Amount >= limit)
  1694. {
  1695. PrintMsgL(player, "TPRLimitReached", limit);
  1696. return;
  1697. }
  1698. if (TeleportTimers.ContainsKey(player.userID))
  1699. {
  1700. PrintMsgL(player, "TeleportPending");
  1701. return;
  1702. }
  1703. if (TeleportTimers.ContainsKey(target.userID))
  1704. {
  1705. PrintMsgL(player, "TeleportPendingTarget");
  1706. return;
  1707. }
  1708. if (PlayersRequests.ContainsKey(player.userID))
  1709. {
  1710. PrintMsgL(player, "PendingRequest");
  1711. return;
  1712. }
  1713. if (PlayersRequests.ContainsKey(target.userID))
  1714. {
  1715. PrintMsgL(player, "PendingRequestTarget");
  1716. return;
  1717. }
  1718. err = CanPlayerTeleport(player);
  1719. if (err != null)
  1720. {
  1721. SendReply(player, err);
  1722. return;
  1723. }
  1724. err = CanPlayerTeleport(target);
  1725. if (err != null)
  1726. {
  1727. PrintMsgL(player, "TPRTarget");
  1728. return;
  1729. }
  1730. err = CheckItems(player);
  1731. if (err != null)
  1732. {
  1733. PrintMsgL(player, "TPBlockedItem", err);
  1734. return;
  1735. }
  1736. if(UseEconomy())
  1737. {
  1738. if (configData.TPR.Pay > 0 && !CheckEconomy(player, configData.TPR.Pay))
  1739. {
  1740. PrintMsgL(player, "TPNoMoney", configData.TPR.Pay);
  1741. return;
  1742. }
  1743. else if(configData.TPR.Pay > 0)
  1744. {
  1745. var w = CheckEconomy(player, (double)configData.TPR.Pay, true);
  1746. PrintMsgL(player, "TPMoney", (double)configData.TPR.Pay);
  1747. }
  1748. }
  1749. PlayersRequests[player.userID] = target;
  1750. PlayersRequests[target.userID] = player;
  1751. PendingRequests[target.userID] = timer.Once(configData.TPR.RequestDuration, () => { RequestTimedOut(player, target); });
  1752. PrintMsgL(player, "Request", target.displayName);
  1753. PrintMsgL(target, "RequestTarget", player.displayName);
  1754. }
  1755. [ChatCommand("tpa")]
  1756. private void cmdChatTeleportAccept(BasePlayer player, string command, string[] args)
  1757. {
  1758. if (!configData.Settings.TPREnabled) return;
  1759. if (args.Length != 0)
  1760. {
  1761. PrintMsgL(player, "SyntaxCommandTPA");
  1762. return;
  1763. }
  1764. Timer reqTimer;
  1765. if (!PendingRequests.TryGetValue(player.userID, out reqTimer))
  1766. {
  1767. PrintMsgL(player, "NoPendingRequest");
  1768. return;
  1769. }
  1770. var err = CheckPlayer(player, false, CanCraftTPR(player));
  1771. if (err != null)
  1772. {
  1773. PrintMsgL(player, err);
  1774. return;
  1775. }
  1776. err = CanPlayerTeleport(player);
  1777. if (err != null)
  1778. {
  1779. SendReply(player, err);
  1780. return;
  1781. }
  1782. var originPlayer = PlayersRequests[player.userID];
  1783. err = CheckTargetLocation(originPlayer, player.transform.position, configData.TPR.UsableIntoBuildingBlocked, configData.TPR.CupOwnerAllowOnBuildingBlocked);
  1784. if (err != null)
  1785. {
  1786. SendReply(player, err);
  1787. return;
  1788. }
  1789. if (configData.TPR.BlockTPAOnCeiling)
  1790. {
  1791. var position = GetGround(player.transform.position);
  1792. if (Vector3.Distance(position, player.transform.position) > 2)
  1793. {
  1794. RaycastHit hitInfo;
  1795. BaseEntity entity = null;
  1796. if (Physics.SphereCast(player.transform.position, .5f, Vector3.down, out hitInfo, 5, blockLayer))
  1797. entity = hitInfo.GetEntity();
  1798. if (entity != null && !entity.PrefabName.Contains("foundation"))
  1799. {
  1800. PrintMsgL(player, "AcceptOnRoof");
  1801. return;
  1802. }
  1803. }
  1804. }
  1805. var countdown = GetLower(originPlayer, configData.TPR.VIPCountdowns, configData.TPR.Countdown);
  1806. PrintMsgL(originPlayer, "Accept", player.displayName, countdown);
  1807. PrintMsgL(player, "AcceptTarget", originPlayer.displayName);
  1808. var timestamp = Facepunch.Math.Epoch.Current;
  1809. TeleportTimers[originPlayer.userID] = new TeleportTimer
  1810. {
  1811. OriginPlayer = originPlayer,
  1812. TargetPlayer = player,
  1813. Timer = timer.Once(countdown, () =>
  1814. {
  1815. err = CheckPlayer(originPlayer, configData.TPR.UsableOutOfBuildingBlocked, CanCraftTPR(originPlayer)) ?? CheckPlayer(player, false, CanCraftTPR(player));
  1816. if (err != null)
  1817. {
  1818. PrintMsgL(player, "InterruptedTarget", originPlayer.displayName);
  1819. PrintMsgL(originPlayer, "Interrupted");
  1820. PrintMsgL(originPlayer, err);
  1821. TeleportTimers.Remove(originPlayer.userID);
  1822. return;
  1823. }
  1824. err = CheckTargetLocation(originPlayer, player.transform.position, configData.TPR.UsableIntoBuildingBlocked, configData.TPR.CupOwnerAllowOnBuildingBlocked);
  1825. if (err != null)
  1826. {
  1827. SendReply(player, err);
  1828. PrintMsgL(originPlayer, "Interrupted");
  1829. SendReply(originPlayer, err);
  1830. TeleportTimers.Remove(originPlayer.userID);
  1831. return;
  1832. }
  1833. err = CanPlayerTeleport(originPlayer) ?? CanPlayerTeleport(player);
  1834. if (err != null)
  1835. {
  1836. SendReply(player, err);
  1837. PrintMsgL(originPlayer, "Interrupted");
  1838. SendReply(originPlayer, err);
  1839. TeleportTimers.Remove(originPlayer.userID);
  1840. return;
  1841. }
  1842. err = CheckItems(originPlayer);
  1843. if (err != null)
  1844. {
  1845. PrintMsgL(player, "InterruptedTarget", originPlayer.displayName);
  1846. PrintMsgL(originPlayer, "Interrupted");
  1847. PrintMsgL(originPlayer, "TPBlockedItem", err);
  1848. TeleportTimers.Remove(originPlayer.userID);
  1849. return;
  1850. }
  1851. if(UseEconomy())
  1852. {
  1853. if (configData.TPR.Pay > 0 && !CheckEconomy(player, configData.TPR.Pay))
  1854. {
  1855. PrintMsgL(player, "InterruptedTarget", originPlayer.displayName);
  1856. PrintMsgL(originPlayer, "TPNoMoney", configData.TPR.Pay);
  1857. TeleportTimers.Remove(originPlayer.userID);
  1858. return;
  1859. }
  1860. else if (configData.TPR.Pay > 0)
  1861. {
  1862. CheckEconomy(player, configData.TPR.Pay, true);
  1863. PrintMsgL(player, "TPMoney", (double)configData.TPR.Pay);
  1864. }
  1865. }
  1866. Teleport(originPlayer, CheckPosition(player.transform.position));
  1867. var tprData = TPR[originPlayer.userID];
  1868. tprData.Amount++;
  1869. tprData.Timestamp = timestamp;
  1870. changedTPR = true;
  1871. PrintMsgL(player, "SuccessTarget", originPlayer.displayName);
  1872. PrintMsgL(originPlayer, "Success", player.displayName);
  1873. var limit = GetHigher(player, configData.TPR.VIPDailyLimits, configData.TPR.DailyLimit);
  1874. if (limit > 0) PrintMsgL(originPlayer, "TPRAmount", limit - tprData.Amount);
  1875. TeleportTimers.Remove(originPlayer.userID);
  1876. })
  1877. };
  1878. reqTimer.Destroy();
  1879. PendingRequests.Remove(player.userID);
  1880. PlayersRequests.Remove(player.userID);
  1881. PlayersRequests.Remove(originPlayer.userID);
  1882. }
  1883. [ChatCommand("wipehomes")]
  1884. private void cmdChatWipeHomes(BasePlayer player, string command, string[] args)
  1885. {
  1886. if (!IsAllowedMsg(player, PermWipeHomes)) return;
  1887. Home.Clear();
  1888. changedHome = true;
  1889. PrintMsgL(player, "HomesListWiped");
  1890. }
  1891. [ChatCommand("tphelp")]
  1892. private void cmdChatTeleportHelp(BasePlayer player, string command, string[] args)
  1893. {
  1894. if (!configData.Settings.HomesEnabled && !configData.Settings.TPREnabled && !IsAllowedMsg(player)) return;
  1895. if (args.Length == 1)
  1896. {
  1897. var key = $"TPHelp{args[0].ToLower()}";
  1898. var msg = _(key, player);
  1899. if (key.Equals(msg))
  1900. PrintMsgL(player, "InvalidHelpModule");
  1901. else
  1902. PrintMsg(player, msg);
  1903. }
  1904. else
  1905. {
  1906. var msg = _("TPHelpGeneral", player);
  1907. if (IsAllowed(player))
  1908. msg += NewLine + "/tphelp AdminTP";
  1909. if (configData.Settings.HomesEnabled)
  1910. msg += NewLine + "/tphelp Home";
  1911. if (configData.Settings.TPREnabled)
  1912. msg += NewLine + "/tphelp TPR";
  1913. PrintMsg(player, msg);
  1914. }
  1915. }
  1916. [ChatCommand("tpinfo")]
  1917. private void cmdChatTeleportInfo(BasePlayer player, string command, string[] args)
  1918. {
  1919. if (!configData.Settings.HomesEnabled && !configData.Settings.TPREnabled && !configData.Settings.TownEnabled) return;
  1920. if (args.Length == 1)
  1921. {
  1922. var module = args[0].ToLower();
  1923. var msg = _($"TPSettings{module}", player);
  1924. var timestamp = Facepunch.Math.Epoch.Current;
  1925. var currentDate = DateTime.Now.ToString("d");
  1926. TeleportData teleportData;
  1927. int limit;
  1928. int cooldown;
  1929. switch (module)
  1930. {
  1931. case "home":
  1932. limit = GetHigher(player, configData.Home.VIPDailyLimits, configData.Home.DailyLimit);
  1933. cooldown = GetLower(player, configData.Home.VIPCooldowns, configData.Home.Cooldown);
  1934. PrintMsg(player, string.Format(msg, FormatTime(cooldown), limit > 0 ? limit.ToString() : _("Unlimited", player), GetHigher(player, configData.Home.VIPHomesLimits, configData.Home.HomesLimit)));
  1935. HomeData homeData;
  1936. if (!Home.TryGetValue(player.userID, out homeData))
  1937. Home[player.userID] = homeData = new HomeData();
  1938. if (homeData.Teleports.Date != currentDate)
  1939. {
  1940. homeData.Teleports.Amount = 0;
  1941. homeData.Teleports.Date = currentDate;
  1942. }
  1943. if (limit > 0) PrintMsgL(player, "HomeTPAmount", limit - homeData.Teleports.Amount);
  1944. if (cooldown > 0 && timestamp - homeData.Teleports.Timestamp < cooldown)
  1945. {
  1946. var remain = cooldown - (timestamp - homeData.Teleports.Timestamp);
  1947. PrintMsgL(player, "HomeTPCooldown", FormatTime(remain));
  1948. }
  1949. break;
  1950. case "tpr":
  1951. limit = GetHigher(player, configData.TPR.VIPDailyLimits, configData.TPR.DailyLimit);
  1952. cooldown = GetLower(player, configData.TPR.VIPCooldowns, configData.TPR.Cooldown);
  1953. PrintMsg(player, string.Format(msg, FormatTime(cooldown), limit > 0 ? limit.ToString() : _("Unlimited", player)));
  1954. if (!TPR.TryGetValue(player.userID, out teleportData))
  1955. TPR[player.userID] = teleportData = new TeleportData();
  1956. if (teleportData.Date != currentDate)
  1957. {
  1958. teleportData.Amount = 0;
  1959. teleportData.Date = currentDate;
  1960. }
  1961. if (limit > 0) PrintMsgL(player, "TPRAmount", limit - teleportData.Amount);
  1962. if (cooldown > 0 && timestamp - teleportData.Timestamp < cooldown)
  1963. {
  1964. var remain = cooldown - (timestamp - teleportData.Timestamp);
  1965. PrintMsgL(player, "TPRCooldown", FormatTime(remain));
  1966. }
  1967. break;
  1968. case "town":
  1969. limit = GetHigher(player, configData.Town.VIPDailyLimits, configData.Town.DailyLimit);
  1970. cooldown = GetLower(player, configData.Town.VIPCooldowns, configData.Town.Cooldown);
  1971. PrintMsg(player, string.Format(msg, FormatTime(cooldown), limit > 0 ? limit.ToString() : _("Unlimited", player)));
  1972. if (!Town.TryGetValue(player.userID, out teleportData))
  1973. Town[player.userID] = teleportData = new TeleportData();
  1974. if (teleportData.Date != currentDate)
  1975. {
  1976. teleportData.Amount = 0;
  1977. teleportData.Date = currentDate;
  1978. }
  1979. if (limit > 0) PrintMsgL(player, "TownTPAmount", limit - teleportData.Amount);
  1980. if (cooldown > 0 && timestamp - teleportData.Timestamp < cooldown)
  1981. {
  1982. var remain = cooldown - (timestamp - teleportData.Timestamp);
  1983. PrintMsgL(player, "TownTPCooldown", FormatTime(remain));
  1984. PrintMsgL(player, "TownTPCooldownBypassP", configData.Town.Bypass);
  1985. PrintMsgL(player, "TownTPCooldownBypassP2", configData.Settings.BypassCMD);
  1986. }
  1987. break;
  1988. default:
  1989. PrintMsgL(player, "InvalidHelpModule");
  1990. break;
  1991. }
  1992. }
  1993. else
  1994. {
  1995. var msg = _("TPInfoGeneral", player);
  1996. if (configData.Settings.HomesEnabled)
  1997. msg += NewLine + "/tpinfo Home";
  1998. if (configData.Settings.TPREnabled)
  1999. msg += NewLine + "/tpinfo TPR";
  2000. if (configData.Settings.TownEnabled)
  2001. msg += NewLine + "/tpinfo Town";
  2002. PrintMsgL(player, msg);
  2003. }
  2004. }
  2005. [ChatCommand("tpc")]
  2006. private void cmdChatTeleportCancel(BasePlayer player, string command, string[] args)
  2007. {
  2008. if (!configData.Settings.TPREnabled) return;
  2009. if (args.Length != 0)
  2010. {
  2011. PrintMsgL(player, "SyntaxCommandTPC");
  2012. return;
  2013. }
  2014. TeleportTimer teleportTimer;
  2015. if (TeleportTimers.TryGetValue(player.userID, out teleportTimer))
  2016. {
  2017. teleportTimer.Timer?.Destroy();
  2018. PrintMsgL(player, "TPCancelled");
  2019. PrintMsgL(teleportTimer.TargetPlayer, "TPCancelledTarget", player.displayName);
  2020. TeleportTimers.Remove(player.userID);
  2021. return;
  2022. }
  2023. foreach (var keyValuePair in TeleportTimers)
  2024. {
  2025. if (keyValuePair.Value.TargetPlayer != player) continue;
  2026. keyValuePair.Value.Timer?.Destroy();
  2027. PrintMsgL(keyValuePair.Value.OriginPlayer, "TPCancelledTarget", player.displayName);
  2028. PrintMsgL(player, "TPYouCancelledTarget", keyValuePair.Value.OriginPlayer.displayName);
  2029. TeleportTimers.Remove(keyValuePair.Key);
  2030. return;
  2031. }
  2032. BasePlayer target;
  2033. if (!PlayersRequests.TryGetValue(player.userID, out target))
  2034. {
  2035. PrintMsgL(player, "NoPendingRequest");
  2036. return;
  2037. }
  2038. Timer reqTimer;
  2039. if (PendingRequests.TryGetValue(player.userID, out reqTimer))
  2040. {
  2041. reqTimer.Destroy();
  2042. PendingRequests.Remove(player.userID);
  2043. }
  2044. else if (PendingRequests.TryGetValue(target.userID, out reqTimer))
  2045. {
  2046. reqTimer.Destroy();
  2047. PendingRequests.Remove(target.userID);
  2048. var temp = player;
  2049. player = target;
  2050. target = temp;
  2051. }
  2052. PlayersRequests.Remove(target.userID);
  2053. PlayersRequests.Remove(player.userID);
  2054. PrintMsgL(player, "Cancelled", target.displayName);
  2055. PrintMsgL(target, "CancelledTarget", player.displayName);
  2056. }
  2057. [ChatCommand("town")]
  2058. private void cmdChatTown(BasePlayer player, string command, string[] args)
  2059. {
  2060. if (!IsAllowedMsg(player, PermTpTown)) return;
  2061. if (args.Length == 1 && IsAllowed(player) && args[0].ToLower().Equals("set"))
  2062. {
  2063. configData.Town.Location = player.transform.position;
  2064. Config.WriteObject(configData, true);
  2065. PrintMsgL(player, "TownTPLocation", configData.Town.Location);
  2066. return;
  2067. }
  2068. if (args.Length == 1 && (args[0].ToLower() != configData.Settings.BypassCMD.ToLower()))
  2069. {
  2070. PrintMsgL(player, "SyntaxCommandTown");
  2071. if (IsAllowed(player)) PrintMsgL(player, "SyntaxCommandTownAdmin");
  2072. return;
  2073. }
  2074. if (configData.Town.Location == default(Vector3))
  2075. {
  2076. PrintMsgL(player, "TownTPNotSet");
  2077. return;
  2078. }
  2079. var err = CheckPlayer(player, configData.Town.UsableOutOfBuildingBlocked, CanCraftTown(player));
  2080. if (err != null)
  2081. {
  2082. PrintMsgL(player, err);
  2083. return;
  2084. }
  2085. TeleportData teleportData;
  2086. if (!Town.TryGetValue(player.userID, out teleportData))
  2087. Town[player.userID] = teleportData = new TeleportData();
  2088. var timestamp = Facepunch.Math.Epoch.Current;
  2089. var currentDate = DateTime.Now.ToString("d");
  2090. if (teleportData.Date != currentDate)
  2091. {
  2092. teleportData.Amount = 0;
  2093. teleportData.Date = currentDate;
  2094. }
  2095. var cooldown = GetLower(player, configData.Town.VIPCooldowns, configData.Town.Cooldown);
  2096. if (cooldown > 0 && timestamp - teleportData.Timestamp < cooldown)
  2097. {
  2098. var cmdSent = "";
  2099. bool foundmoney = CheckEconomy(player, configData.Town.Bypass);
  2100. try
  2101. {
  2102. cmdSent = args[0].ToLower();
  2103. }
  2104. catch {}
  2105. bool payalso = false;
  2106. if(configData.Town.Pay > 0)
  2107. {
  2108. payalso = true;
  2109. }
  2110. if((configData.Settings.BypassCMD != null) && (cmdSent == configData.Settings.BypassCMD.ToLower()))
  2111. {
  2112. if(foundmoney == true)
  2113. {
  2114. CheckEconomy(player, configData.Town.Bypass, true);
  2115. PrintMsgL(player, "TownTPCooldownBypass", configData.Town.Bypass);
  2116. if(payalso)
  2117. {
  2118. PrintMsgL(player, "PayToTown", configData.Town.Pay);
  2119. }
  2120. }
  2121. else
  2122. {
  2123. PrintMsgL(player, "TownTPCooldownBypassF", configData.Town.Bypass);
  2124. return;
  2125. }
  2126. }
  2127. else if(UseEconomy())
  2128. {
  2129. var remain = cooldown - (timestamp - teleportData.Timestamp);
  2130. PrintMsgL(player, "TownTPCooldown", FormatTime(remain));
  2131. if(configData.Town.Bypass > 0 && configData.Settings.BypassCMD != null)
  2132. {
  2133. PrintMsgL(player, "TownTPCooldownBypassP", configData.Town.Bypass);
  2134. PrintMsgL(player, "TownTPCooldownBypassP2", configData.Settings.BypassCMD);
  2135. }
  2136. return;
  2137. }
  2138. else
  2139. {
  2140. var remain = cooldown - (timestamp - teleportData.Timestamp);
  2141. PrintMsgL(player, "TownTPCooldown", FormatTime(remain));
  2142. return;
  2143. }
  2144. }
  2145. var limit = GetHigher(player, configData.Town.VIPDailyLimits, configData.Town.DailyLimit);
  2146. if (limit > 0 && teleportData.Amount >= limit)
  2147. {
  2148. PrintMsgL(player, "TownTPLimitReached", limit);
  2149. return;
  2150. }
  2151. if (TeleportTimers.ContainsKey(player.userID))
  2152. {
  2153. PrintMsgL(player, "TeleportPending");
  2154. return;
  2155. }
  2156. err = CanPlayerTeleport(player);
  2157. if (err != null)
  2158. {
  2159. SendReply(player, err);
  2160. return;
  2161. }
  2162. err = CheckItems(player);
  2163. if (err != null)
  2164. {
  2165. PrintMsgL(player, "TPBlockedItem", err);
  2166. return;
  2167. }
  2168. var countdown = GetLower(player, configData.Town.VIPCountdowns, configData.Town.Countdown);
  2169. TeleportTimers[player.userID] = new TeleportTimer
  2170. {
  2171. OriginPlayer = player,
  2172. Timer = timer.Once(countdown, () =>
  2173. {
  2174. err = CheckPlayer(player, configData.Town.UsableOutOfBuildingBlocked, CanCraftTown(player));
  2175. if (err != null)
  2176. {
  2177. PrintMsgL(player, "Interrupted");
  2178. PrintMsgL(player, err);
  2179. TeleportTimers.Remove(player.userID);
  2180. return;
  2181. }
  2182. err = CanPlayerTeleport(player);
  2183. if (err != null)
  2184. {
  2185. PrintMsgL(player, "Interrupted");
  2186. SendReply(player, err);
  2187. TeleportTimers.Remove(player.userID);
  2188. return;
  2189. }
  2190. err = CheckItems(player);
  2191. if (err != null)
  2192. {
  2193. PrintMsgL(player, "Interrupted");
  2194. PrintMsgL(player, "TPBlockedItem", err);
  2195. TeleportTimers.Remove(player.userID);
  2196. return;
  2197. }
  2198. if(UseEconomy())
  2199. {
  2200. if(configData.Town.Pay > 0 && ! CheckEconomy(player, configData.Town.Pay))
  2201. {
  2202. PrintMsgL(player, "Interrupted");
  2203. PrintMsgL(player, "TPNoMoney", configData.Town.Pay);
  2204. TeleportTimers.Remove(player.userID);
  2205. return;
  2206. }
  2207. else if (configData.Town.Pay > 0)
  2208. {
  2209. CheckEconomy(player, configData.Town.Pay, true);
  2210. PrintMsgL(player, "TPMoney", (double)configData.Town.Pay);
  2211. }
  2212. }
  2213. Teleport(player, configData.Town.Location);
  2214. teleportData.Amount++;
  2215. teleportData.Timestamp = timestamp;
  2216. changedTown = true;
  2217. PrintMsgL(player, "TownTP");
  2218. if (limit > 0) PrintMsgL(player, "TownTPAmount", limit - teleportData.Amount);
  2219. TeleportTimers.Remove(player.userID);
  2220. })
  2221. };
  2222. PrintMsgL(player, "TownTPStarted", countdown);
  2223. }
  2224. private bool ccmdTeleport(ConsoleSystem.Arg arg)
  2225. {
  2226. if (arg.Player() != null && !IsAllowedMsg(arg.Player(), PermTpConsole)) return false;
  2227. HashSet<BasePlayer> players;
  2228. switch (arg.cmd.FullName)
  2229. {
  2230. case "teleport.topos":
  2231. if (!arg.HasArgs(4))
  2232. {
  2233. arg.ReplyWith(_("SyntaxConsoleCommandToPos", arg.Player()));
  2234. return false;
  2235. }
  2236. players = FindPlayers(arg.GetString(0));
  2237. if (players.Count <= 0)
  2238. {
  2239. arg.ReplyWith(_("PlayerNotFound", arg.Player()));
  2240. return false;
  2241. }
  2242. if (players.Count > 1)
  2243. {
  2244. arg.ReplyWith(_("MultiplePlayers", arg.Player(), string.Join(", ", players.Select(p => p.displayName).ToArray())));
  2245. return false;
  2246. }
  2247. var targetPlayer = players.First();
  2248. var x = arg.GetFloat(1, -10000);
  2249. var y = arg.GetFloat(2, -10000);
  2250. var z = arg.GetFloat(3, -10000);
  2251. if (!CheckBoundaries(x, y, z))
  2252. {
  2253. arg.ReplyWith(_("AdminTPOutOfBounds", arg.Player()) + Environment.NewLine + _("AdminTPBoundaries", arg.Player(), boundary));
  2254. return false;
  2255. }
  2256. TeleportToPosition(targetPlayer, x, y, z);
  2257. PrintMsgL(targetPlayer, "AdminTPConsoleTP", targetPlayer.transform.position);
  2258. arg.ReplyWith(_("AdminTPTargetCoordinates", arg.Player(), targetPlayer.displayName, targetPlayer.transform.position));
  2259. Puts(_("LogTeleportPlayer", null, arg.Player()?.displayName, targetPlayer.displayName, targetPlayer.transform.position));
  2260. break;
  2261. case "teleport.toplayer":
  2262. if (!arg.HasArgs(2))
  2263. {
  2264. arg.ReplyWith(_("SyntaxConsoleCommandToPlayer", arg.Player()));
  2265. return false;
  2266. }
  2267. players = FindPlayers(arg.GetString(0));
  2268. if (players.Count <= 0)
  2269. {
  2270. arg.ReplyWith(_("PlayerNotFound", arg.Player()));
  2271. return false;
  2272. }
  2273. if (players.Count > 1)
  2274. {
  2275. arg.ReplyWith(_("MultiplePlayers", arg.Player(), string.Join(", ", players.Select(p => p.displayName).ToArray())));
  2276. return false;
  2277. }
  2278. var originPlayer = players.First();
  2279. players = FindPlayers(arg.GetString(1));
  2280. if (players.Count <= 0)
  2281. {
  2282. arg.ReplyWith(_("PlayerNotFound", arg.Player()));
  2283. return false;
  2284. }
  2285. if (players.Count > 1)
  2286. {
  2287. arg.ReplyWith(_("MultiplePlayers", arg.Player(), string.Join(", ", players.Select(p => p.displayName).ToArray())));
  2288. return false;
  2289. }
  2290. targetPlayer = players.First();
  2291. if (targetPlayer == originPlayer)
  2292. {
  2293. arg.ReplyWith(_("CantTeleportPlayerToSelf", arg.Player()));
  2294. return false;
  2295. }
  2296. TeleportToPlayer(originPlayer, targetPlayer);
  2297. arg.ReplyWith(_("AdminTPPlayers", arg.Player(), originPlayer.displayName, targetPlayer.displayName));
  2298. PrintMsgL(originPlayer, "AdminTPConsoleTPPlayer", targetPlayer.displayName);
  2299. PrintMsgL(targetPlayer, "AdminTPConsoleTPPlayerTarget", originPlayer.displayName);
  2300. Puts(_("LogTeleportPlayer", null, arg.Player()?.displayName, originPlayer.displayName, targetPlayer.displayName));
  2301. break;
  2302. }
  2303. return false;
  2304. }
  2305. [ConsoleCommand("teleport.importhomes")]
  2306. private bool ccmdImportHomes(ConsoleSystem.Arg arg)
  2307. {
  2308. if (arg.Player() != null && !IsAllowedMsg(arg.Player(), PermImportHomes))
  2309. {
  2310. arg.ReplyWith("Not allowed.");
  2311. return false;
  2312. }
  2313. var datafile = Interface.Oxide.DataFileSystem.GetFile("m-Teleportation");
  2314. if (!datafile.Exists())
  2315. {
  2316. arg.ReplyWith("No m-Teleportation.json exists.");
  2317. return false;
  2318. }
  2319. datafile.Load();
  2320. var allHomeData = datafile["HomeData"] as Dictionary<string, object>;
  2321. if (allHomeData == null)
  2322. {
  2323. arg.ReplyWith("Empty HomeData.");
  2324. return false;
  2325. }
  2326. var count = 0;
  2327. foreach (var kvp in allHomeData)
  2328. {
  2329. var homeDataOld = kvp.Value as Dictionary<string, object>;
  2330. if (homeDataOld == null) continue;
  2331. if (!homeDataOld.ContainsKey("HomeLocations")) continue;
  2332. var homeList = homeDataOld["HomeLocations"] as Dictionary<string, object>;
  2333. if (homeList == null) continue;
  2334. var userId = Convert.ToUInt64(kvp.Key);
  2335. HomeData homeData;
  2336. if (!Home.TryGetValue(userId, out homeData))
  2337. Home[userId] = homeData = new HomeData();
  2338. foreach (var kvp2 in homeList)
  2339. {
  2340. var positionData = kvp2.Value as Dictionary<string, object>;
  2341. if (positionData == null) continue;
  2342. if (!positionData.ContainsKey("x") || !positionData.ContainsKey("y") || !positionData.ContainsKey("z")) continue;
  2343. var position = new Vector3(Convert.ToSingle(positionData["x"]), Convert.ToSingle(positionData["y"]), Convert.ToSingle(positionData["z"]));
  2344. homeData.Locations[kvp2.Key] = position;
  2345. changedHome = true;
  2346. count++;
  2347. }
  2348. }
  2349. arg.ReplyWith(string.Format("Imported {0} homes.", count));
  2350. return false;
  2351. }
  2352. private void RequestTimedOut(BasePlayer player, BasePlayer target)
  2353. {
  2354. PlayersRequests.Remove(player.userID);
  2355. PlayersRequests.Remove(target.userID);
  2356. PendingRequests.Remove(target.userID);
  2357. PrintMsgL(player, "TimedOut", target.displayName);
  2358. PrintMsgL(target, "TimedOutTarget", player.displayName);
  2359. }
  2360. #region Util
  2361. private string FormatTime(long seconds)
  2362. {
  2363. var timespan = TimeSpan.FromSeconds(seconds);
  2364. return string.Format(timespan.TotalHours >= 1 ? "{2:00}:{0:00}:{1:00}" : "{0:00}:{1:00}", timespan.Minutes, timespan.Seconds, System.Math.Floor(timespan.TotalHours));
  2365. }
  2366. private double ConvertToRadians(double angle)
  2367. {
  2368. return System.Math.PI / 180 * angle;
  2369. }
  2370. #region Teleport
  2371. public void TeleportToPlayer(BasePlayer player, BasePlayer target) => Teleport(player, target.transform.position);
  2372. public void TeleportToPosition(BasePlayer player, float x, float y, float z) => Teleport(player, new Vector3(x, y, z));
  2373. public void Teleport(BasePlayer player, Vector3 position)
  2374. {
  2375. SaveLocation(player);
  2376. teleporting.Add(player.userID);
  2377. if (player.net?.connection != null)
  2378. player.ClientRPCPlayer(null, player, "StartLoading");
  2379. StartSleeping(player);
  2380. player.MovePosition(position);
  2381. if (player.net?.connection != null)
  2382. player.ClientRPCPlayer(null, player, "ForcePositionTo", position);
  2383. if (player.net?.connection != null)
  2384. player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
  2385. player.UpdateNetworkGroup();
  2386. //player.UpdatePlayerCollider(true, false);
  2387. player.SendNetworkUpdateImmediate(false);
  2388. if (player.net?.connection == null) return;
  2389. //TODO temporary for potential rust bug
  2390. try
  2391. {
  2392. player.ClearEntityQueue(null);
  2393. }
  2394. catch
  2395. {
  2396. }
  2397. player.SendFullSnapshot();
  2398. }
  2399. private void StartSleeping(BasePlayer player)
  2400. {
  2401. if (player.IsSleeping())
  2402. return;
  2403. player.SetPlayerFlag(BasePlayer.PlayerFlags.Sleeping, true);
  2404. if (!BasePlayer.sleepingPlayerList.Contains(player))
  2405. BasePlayer.sleepingPlayerList.Add(player);
  2406. player.CancelInvoke("InventoryUpdate");
  2407. //player.inventory.crafting.CancelAll(true);
  2408. //player.UpdatePlayerCollider(true, false);
  2409. }
  2410. #endregion
  2411. #region Checks
  2412. private Vector3 CheckPosition(Vector3 position)
  2413. {
  2414. var hits = Physics.OverlapSphere(position, 2, blockLayer);
  2415. var distance = 5f;
  2416. BuildingBlock buildingBlock = null;
  2417. for (var i = 0; i < hits.Length; i++)
  2418. {
  2419. var block = hits[i].GetComponentInParent<BuildingBlock>();
  2420. if (block == null) continue;
  2421. var prefab = block.PrefabName;
  2422. if (!prefab.Contains("foundation", CompareOptions.OrdinalIgnoreCase) && !prefab.Contains("floor", CompareOptions.OrdinalIgnoreCase) && !prefab.Contains("pillar", CompareOptions.OrdinalIgnoreCase)) continue;
  2423. if (!(Vector3.Distance(block.transform.position, position) < distance)) continue;
  2424. buildingBlock = block;
  2425. distance = Vector3.Distance(block.transform.position, position);
  2426. }
  2427. if (buildingBlock == null) return position;
  2428. var blockRotation = buildingBlock.transform.rotation.eulerAngles.y;
  2429. var angles = new[] { 360 - blockRotation, 180 - blockRotation };
  2430. var location = default(Vector3);
  2431. const double r = 1.9;
  2432. var locationDistance = 100f;
  2433. for (var i = 0; i < angles.Length; i++)
  2434. {
  2435. var radians = ConvertToRadians(angles[i]);
  2436. var newX = r * System.Math.Cos(radians);
  2437. var newZ = r * System.Math.Sin(radians);
  2438. var newLoc = new Vector3((float)(buildingBlock.transform.position.x + newX), buildingBlock.transform.position.y + .2f, (float)(buildingBlock.transform.position.z + newZ));
  2439. if (Vector3.Distance(position, newLoc) < locationDistance)
  2440. {
  2441. location = newLoc;
  2442. locationDistance = Vector3.Distance(position, newLoc);
  2443. }
  2444. }
  2445. return location;
  2446. }
  2447. private string CanPlayerTeleport(BasePlayer player)
  2448. {
  2449. return Interface.Oxide.CallHook("CanTeleport", player) as string;
  2450. }
  2451. private bool CanCraftHome(BasePlayer player)
  2452. {
  2453. return configData.Home.AllowCraft || permission.UserHasPermission(player.UserIDString, PermCraftHome);
  2454. }
  2455. private bool CanCraftTown(BasePlayer player)
  2456. {
  2457. return configData.Town.AllowCraft || permission.UserHasPermission(player.UserIDString, PermCraftTown);
  2458. }
  2459. private bool CanCraftTPR(BasePlayer player)
  2460. {
  2461. return configData.TPR.AllowCraft || permission.UserHasPermission(player.UserIDString, PermCraftTpR);
  2462. }
  2463. private string CheckPlayer(BasePlayer player, bool build = false, bool craft = false)
  2464. {
  2465. var onship = player.GetComponentInParent<CargoShip>();
  2466. var onballoon = player.GetComponentInParent<HotAirBalloon>();
  2467. if (player.isMounted)
  2468. return "TPMounted";
  2469. if (!player.IsAlive())
  2470. return "TPDead";
  2471. if (player.IsWounded())
  2472. return "TPWounded";
  2473. if (!build && !player.CanBuild())
  2474. return "TPBuildingBlocked";
  2475. if (player.IsSwimming())
  2476. return "TPSwimming";
  2477. if (onship)
  2478. return "TPCargoShip";
  2479. if (onballoon)
  2480. return "TPHotAirBalloon";
  2481. if (player.InSafeZone())
  2482. return "TPSafeZone";
  2483. if (!craft && player.inventory.crafting.queue.Count > 0)
  2484. return "TPCrafting";
  2485. return null;
  2486. }
  2487. private string CheckTargetLocation(BasePlayer player, Vector3 targetLocation, bool build, bool owner)
  2488. {
  2489. var colliders = Pool.GetList<Collider>();
  2490. Vis.Colliders(targetLocation, 0.1f, colliders, triggerLayer);
  2491. var cups = false;
  2492. foreach (var collider in colliders)
  2493. {
  2494. var cup = collider.GetComponentInParent<BuildingPrivlidge>();
  2495. if (cup == null) continue;
  2496. cups = true;
  2497. if (owner && player.userID == cup.OwnerID)
  2498. {
  2499. Pool.FreeList(ref colliders);
  2500. return null;
  2501. }
  2502. if (cup.IsAuthed(player))
  2503. {
  2504. Pool.FreeList(ref colliders);
  2505. return null;
  2506. }
  2507. }
  2508. Pool.FreeList(ref colliders);
  2509. return cups && !build ? "TPTargetBuildingBlocked" : null;
  2510. }
  2511. private string CheckInsideBlock(Vector3 targetLocation)
  2512. {
  2513. List<BuildingBlock> blocks = Pool.GetList<BuildingBlock>();
  2514. Vis.Entities(targetLocation + new Vector3(0, 0.25f), 0.1f, blocks, blockLayer);
  2515. bool inside = blocks.Count > 0;
  2516. Pool.FreeList(ref blocks);
  2517. return inside ? "TPTargetInsideBlock" : null;
  2518. }
  2519. private string CheckItems(BasePlayer player)
  2520. {
  2521. foreach (var blockedItem in ReverseBlockedItems)
  2522. {
  2523. if (player.inventory.containerMain.GetAmount(blockedItem.Key, true) > 0)
  2524. return blockedItem.Value;
  2525. if (player.inventory.containerBelt.GetAmount(blockedItem.Key, true) > 0)
  2526. return blockedItem.Value;
  2527. if (player.inventory.containerWear.GetAmount(blockedItem.Key, true) > 0)
  2528. return blockedItem.Value;
  2529. }
  2530. return null;
  2531. }
  2532. private string CheckFoundation(ulong userID, Vector3 position)
  2533. {
  2534. if (UnderneathFoundation(position))
  2535. {
  2536. return "HomeFoundationUnderneathFoundation";
  2537. }
  2538. if (!configData.Home.ForceOnTopOfFoundation) return null;
  2539. var entities = GetFoundation(position);
  2540. if (entities.Count == 0)
  2541. return "HomeNoFoundation";
  2542. if (!configData.Home.CheckFoundationForOwner) return null;
  2543. for (var i = 0; i < entities.Count; i++)
  2544. if (entities[i].OwnerID == userID) return null;
  2545. if (!configData.Home.UseFriends)
  2546. return "HomeFoundationNotOwned";
  2547. var moderator = (bool)(Clans?.CallHook("IsModerator", userID) ?? false);
  2548. var userIdString = userID.ToString();
  2549. for (var i = 0; i < entities.Count; i++)
  2550. {
  2551. var entity = entities[i];
  2552. if ((bool)(Friends?.CallHook("HasFriend", entity.OwnerID, userID) ?? false) || (bool)(Clans?.CallHook("HasFriend", entity.OwnerID, userID) ?? false) && moderator || (bool)(RustIO?.CallHook("HasFriend", entity.OwnerID.ToString(), userIdString) ?? false))
  2553. return null;
  2554. }
  2555. return "HomeFoundationNotFriendsOwned";
  2556. }
  2557. private BuildingBlock GetFoundationOwned(Vector3 position, ulong userID)
  2558. {
  2559. var entities = GetFoundation(position);
  2560. if (entities.Count == 0)
  2561. return null;
  2562. if (!configData.Home.CheckFoundationForOwner) return entities[0];
  2563. for (var i = 0; i < entities.Count; i++)
  2564. if (entities[i].OwnerID == userID) return entities[i];
  2565. if (!configData.Home.UseFriends)
  2566. return null;
  2567. var moderator = (bool)(Clans?.CallHook("IsModerator", userID) ?? false);
  2568. var userIdString = userID.ToString();
  2569. for (var i = 0; i < entities.Count; i++)
  2570. {
  2571. var entity = entities[i];
  2572. if ((bool)(Friends?.CallHook("HasFriend", entity.OwnerID, userID) ?? false) || (bool)(Clans?.CallHook("HasFriend", entity.OwnerID, userID) ?? false) && moderator || (bool)(RustIO?.CallHook("HasFriend", entity.OwnerID.ToString(), userIdString) ?? false))
  2573. return entity;
  2574. }
  2575. return null;
  2576. }
  2577. private List<BuildingBlock> GetFoundation(Vector3 positionCoordinates)
  2578. {
  2579. var position = GetGround(positionCoordinates);
  2580. var entities = new List<BuildingBlock>();
  2581. var hits = Pool.GetList<BuildingBlock>();
  2582. Vis.Entities(position, 2.5f, hits, buildingLayer);
  2583. for (var i = 0; i < hits.Count; i++)
  2584. {
  2585. var entity = hits[i];
  2586. if (!entity.PrefabName.Contains("foundation") || positionCoordinates.y < entity.WorldSpaceBounds().ToBounds().max.y) continue;
  2587. entities.Add(entity);
  2588. }
  2589. Pool.FreeList(ref hits);
  2590. return entities;
  2591. }
  2592. private bool CheckBoundaries(float x, float y, float z)
  2593. {
  2594. return x <= boundary && x >= -boundary && y < 2000 && y >= -100 && z <= boundary && z >= -boundary;
  2595. }
  2596. private Vector3 GetGround(Vector3 sourcePos)
  2597. {
  2598. if (!configData.Home.AllowAboveFoundation) return sourcePos;
  2599. var newPos = sourcePos;
  2600. newPos.y = TerrainMeta.HeightMap.GetHeight(newPos);
  2601. sourcePos.y += .5f;
  2602. RaycastHit hitinfo;
  2603. var done = false;
  2604. if (Physics.SphereCast(sourcePos, .1f, Vector3.down, out hitinfo, 250, groundLayer))
  2605. {
  2606. if ((configData.Home.AllowIceberg && hitinfo.collider.name.Contains("iceberg")) || (configData.Home.AllowCave && hitinfo.collider.name.Contains("cave_")))
  2607. {
  2608. sourcePos.y = hitinfo.point.y;
  2609. done = true;
  2610. }
  2611. else
  2612. {
  2613. var mesh = hitinfo.collider.GetComponentInChildren<MeshCollider>();
  2614. if (mesh != null && mesh.sharedMesh.name.Contains("rock_"))
  2615. {
  2616. sourcePos.y = hitinfo.point.y;
  2617. done = true;
  2618. }
  2619. }
  2620. }
  2621. if (!configData.Home.AllowCave && Physics.SphereCast(sourcePos, .1f, Vector3.up, out hitinfo, 250, groundLayer) && hitinfo.collider.name.Contains("rock_"))
  2622. {
  2623. sourcePos.y = newPos.y - 10;
  2624. done = true;
  2625. }
  2626. return done ? sourcePos : newPos;
  2627. }
  2628. private Vector3 GetGroundBuilding(Vector3 sourcePos)
  2629. {
  2630. sourcePos.y = TerrainMeta.HeightMap.GetHeight(sourcePos);
  2631. RaycastHit hitinfo;
  2632. if (Physics.Raycast(sourcePos, Vector3.down, out hitinfo, buildingLayer))
  2633. {
  2634. sourcePos.y = System.Math.Max(hitinfo.point.y, sourcePos.y);
  2635. return sourcePos;
  2636. }
  2637. if (Physics.Raycast(sourcePos, Vector3.up, out hitinfo, buildingLayer))
  2638. sourcePos.y = System.Math.Max(hitinfo.point.y, sourcePos.y);
  2639. return sourcePos;
  2640. }
  2641. private bool UnderneathFoundation(Vector3 position)
  2642. {
  2643. RaycastHit hit;
  2644. if (Physics.Raycast(new Ray(position, Vector3.up), out hit, 10, buildingLayer))
  2645. {
  2646. if (hit.GetCollider().name.Contains("foundation"))
  2647. {
  2648. return true;
  2649. }
  2650. }
  2651. return false;
  2652. }
  2653. private bool IsAllowed(BasePlayer player, string perm = null)
  2654. {
  2655. var playerAuthLevel = player.net?.connection?.authLevel;
  2656. var requiredAuthLevel = configData.Admin.UseableByModerators ? 1 : 2;
  2657. if (playerAuthLevel >= requiredAuthLevel) return true;
  2658. return !string.IsNullOrEmpty(perm) && permission.UserHasPermission(player.UserIDString, perm);
  2659. }
  2660. private bool IsAllowedMsg(BasePlayer player, string perm = null)
  2661. {
  2662. if (IsAllowed(player, perm)) return true;
  2663. PrintMsg(player, "NotAllowed");
  2664. return false;
  2665. }
  2666. private int GetHigher(BasePlayer player, Dictionary<string, int> limits, int limit)
  2667. {
  2668. foreach (var l in limits)
  2669. {
  2670. if (permission.UserHasPermission(player.UserIDString, l.Key) && l.Value > limit)
  2671. limit = l.Value;
  2672. }
  2673. return limit;
  2674. }
  2675. private int GetLower(BasePlayer player, Dictionary<string, int> times, int time)
  2676. {
  2677. foreach (var l in times)
  2678. {
  2679. if (permission.UserHasPermission(player.UserIDString, l.Key) && l.Value < time)
  2680. time = l.Value;
  2681. }
  2682. return time;
  2683. }
  2684. private void CheckPerms(Dictionary<string, int> limits)
  2685. {
  2686. foreach (var limit in limits)
  2687. {
  2688. if (!permission.PermissionExists(limit.Key))
  2689. permission.RegisterPermission(limit.Key, this);
  2690. }
  2691. }
  2692. #endregion
  2693. #region Message
  2694. private string _(string msgId, BasePlayer player, params object[] args)
  2695. {
  2696. var msg = lang.GetMessage(msgId, this, player?.UserIDString);
  2697. return args.Length > 0 ? string.Format(msg, args) : msg;
  2698. }
  2699. private void PrintMsgL(BasePlayer player, string msgId, params object[] args)
  2700. {
  2701. if (player == null) return;
  2702. PrintMsg(player, _(msgId, player, args));
  2703. }
  2704. private void PrintMsg(BasePlayer player, string msg)
  2705. {
  2706. if (player == null) return;
  2707. SendReply(player, $"{configData.Settings.ChatName}{msg}");
  2708. }
  2709. #endregion
  2710. #region DrawBox
  2711. private static void DrawBox(BasePlayer player, Vector3 center, Quaternion rotation, Vector3 size)
  2712. {
  2713. size = size / 2;
  2714. var point1 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y + size.y, center.z + size.z), center, rotation);
  2715. var point2 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y - size.y, center.z + size.z), center, rotation);
  2716. var point3 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y + size.y, center.z - size.z), center, rotation);
  2717. var point4 = RotatePointAroundPivot(new Vector3(center.x + size.x, center.y - size.y, center.z - size.z), center, rotation);
  2718. var point5 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y + size.y, center.z + size.z), center, rotation);
  2719. var point6 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y - size.y, center.z + size.z), center, rotation);
  2720. var point7 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y + size.y, center.z - size.z), center, rotation);
  2721. var point8 = RotatePointAroundPivot(new Vector3(center.x - size.x, center.y - size.y, center.z - size.z), center, rotation);
  2722. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point1, point2);
  2723. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point1, point3);
  2724. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point1, point5);
  2725. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point4, point2);
  2726. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point4, point3);
  2727. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point4, point8);
  2728. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point5, point6);
  2729. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point5, point7);
  2730. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point6, point2);
  2731. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point8, point6);
  2732. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point8, point7);
  2733. player.SendConsoleCommand("ddraw.line", 30f, Color.blue, point7, point3);
  2734. }
  2735. private static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion rotation)
  2736. {
  2737. return rotation * (point - pivot) + pivot;
  2738. }
  2739. #endregion
  2740. #region FindPlayer
  2741. private ulong FindPlayersSingleId(string nameOrIdOrIp, BasePlayer player)
  2742. {
  2743. var targets = FindPlayers(nameOrIdOrIp);
  2744. if (targets.Count > 1)
  2745. {
  2746. PrintMsgL(player, "MultiplePlayers", string.Join(", ", targets.Select(p => p.displayName).ToArray()));
  2747. return 0;
  2748. }
  2749. ulong userId;
  2750. if (targets.Count <= 0)
  2751. {
  2752. if (ulong.TryParse(nameOrIdOrIp, out userId)) return userId;
  2753. PrintMsgL(player, "PlayerNotFound");
  2754. return 0;
  2755. }
  2756. else
  2757. userId = targets.First().userID;
  2758. return userId;
  2759. }
  2760. private BasePlayer FindPlayersSingle(string nameOrIdOrIp, BasePlayer player)
  2761. {
  2762. var targets = FindPlayers(nameOrIdOrIp);
  2763. if (targets.Count <= 0)
  2764. {
  2765. PrintMsgL(player, "PlayerNotFound");
  2766. return null;
  2767. }
  2768. if (targets.Count > 1)
  2769. {
  2770. PrintMsgL(player, "MultiplePlayers", string.Join(", ", targets.Select(p => p.displayName).ToArray()));
  2771. return null;
  2772. }
  2773. return targets.First();
  2774. }
  2775. private static HashSet<BasePlayer> FindPlayers(string nameOrIdOrIp)
  2776. {
  2777. var players = new HashSet<BasePlayer>();
  2778. if (string.IsNullOrEmpty(nameOrIdOrIp)) return players;
  2779. foreach (var activePlayer in BasePlayer.activePlayerList)
  2780. {
  2781. if (activePlayer.UserIDString.Equals(nameOrIdOrIp))
  2782. players.Add(activePlayer);
  2783. else if (!string.IsNullOrEmpty(activePlayer.displayName) && activePlayer.displayName.ToLower().IndexOf(nameOrIdOrIp.ToLower()) != -1)
  2784. players.Add(activePlayer);
  2785. else if (activePlayer.net?.connection != null && activePlayer.net.connection.ipaddress.Equals(nameOrIdOrIp))
  2786. players.Add(activePlayer);
  2787. }
  2788. foreach (var sleepingPlayer in BasePlayer.sleepingPlayerList)
  2789. {
  2790. if (sleepingPlayer.UserIDString.Equals(nameOrIdOrIp))
  2791. players.Add(sleepingPlayer);
  2792. else if (!string.IsNullOrEmpty(sleepingPlayer.displayName) && sleepingPlayer.displayName.ToLower().IndexOf(nameOrIdOrIp.ToLower()) != -1)
  2793. players.Add(sleepingPlayer);
  2794. }
  2795. return players;
  2796. }
  2797. private static List<BasePlayer> FindPlayersOnline(string nameOrIdOrIp)
  2798. {
  2799. var players = new List<BasePlayer>();
  2800. if (string.IsNullOrEmpty(nameOrIdOrIp)) return players;
  2801. foreach (var activePlayer in BasePlayer.activePlayerList)
  2802. {
  2803. if (activePlayer.UserIDString.Equals(nameOrIdOrIp))
  2804. players.Add(activePlayer);
  2805. else if (!string.IsNullOrEmpty(activePlayer.displayName) && activePlayer.displayName.Contains(nameOrIdOrIp, CompareOptions.IgnoreCase))
  2806. players.Add(activePlayer);
  2807. else if (activePlayer.net?.connection != null && activePlayer.net.connection.ipaddress.Equals(nameOrIdOrIp))
  2808. players.Add(activePlayer);
  2809. }
  2810. return players;
  2811. }
  2812. #endregion
  2813. #endregion
  2814. #region API
  2815. private Dictionary<string, Vector3> GetHomes(object playerObj)
  2816. {
  2817. if (playerObj == null) return null;
  2818. if (playerObj is string)
  2819. playerObj = Convert.ToUInt64(playerObj);
  2820. if (!(playerObj is ulong))
  2821. throw new ArgumentException("playerObj");
  2822. var playerId = (ulong)playerObj;
  2823. HomeData homeData;
  2824. if (!Home.TryGetValue(playerId, out homeData) || homeData.Locations.Count == 0)
  2825. return null;
  2826. return homeData.Locations;
  2827. }
  2828. private int GetLimitRemaining(BasePlayer player, string type)
  2829. {
  2830. if (player == null || string.IsNullOrEmpty(type)) return 0;
  2831. var currentDate = DateTime.Now.ToString("d");
  2832. int limit;
  2833. var remaining = -1;
  2834. switch (type.ToLower())
  2835. {
  2836. case "home":
  2837. limit = GetHigher(player, configData.Home.VIPDailyLimits, configData.Home.DailyLimit);
  2838. HomeData homeData;
  2839. if (!Home.TryGetValue(player.userID, out homeData))
  2840. Home[player.userID] = homeData = new HomeData();
  2841. if (homeData.Teleports.Date != currentDate)
  2842. {
  2843. homeData.Teleports.Amount = 0;
  2844. homeData.Teleports.Date = currentDate;
  2845. }
  2846. if (limit > 0)
  2847. remaining = limit - homeData.Teleports.Amount;
  2848. break;
  2849. case "town":
  2850. limit = GetHigher(player, configData.Town.VIPDailyLimits, configData.Town.DailyLimit);
  2851. TeleportData townData;
  2852. if (!Town.TryGetValue(player.userID, out townData))
  2853. Town[player.userID] = townData = new TeleportData();
  2854. if (townData.Date != currentDate)
  2855. {
  2856. townData.Amount = 0;
  2857. townData.Date = currentDate;
  2858. }
  2859. if (limit > 0)
  2860. remaining = limit - townData.Amount;
  2861. break;
  2862. case "tpr":
  2863. limit = GetHigher(player, configData.TPR.VIPDailyLimits, configData.TPR.DailyLimit);
  2864. TeleportData tprData;
  2865. if (!TPR.TryGetValue(player.userID, out tprData))
  2866. TPR[player.userID] = tprData = new TeleportData();
  2867. if (tprData.Date != currentDate)
  2868. {
  2869. tprData.Amount = 0;
  2870. tprData.Date = currentDate;
  2871. }
  2872. if (limit > 0)
  2873. remaining = limit - tprData.Amount;
  2874. break;
  2875. }
  2876. return remaining;
  2877. }
  2878. private int GetCooldownRemaining(BasePlayer player, string type)
  2879. {
  2880. if (player == null || string.IsNullOrEmpty(type)) return 0;
  2881. var currentDate = DateTime.Now.ToString("d");
  2882. var timestamp = Facepunch.Math.Epoch.Current;
  2883. int cooldown;
  2884. var remaining = -1;
  2885. switch (type.ToLower())
  2886. {
  2887. case "home":
  2888. cooldown = GetLower(player, configData.Home.VIPCooldowns, configData.Home.Cooldown);
  2889. HomeData homeData;
  2890. if (!Home.TryGetValue(player.userID, out homeData))
  2891. Home[player.userID] = homeData = new HomeData();
  2892. if (homeData.Teleports.Date != currentDate)
  2893. {
  2894. homeData.Teleports.Amount = 0;
  2895. homeData.Teleports.Date = currentDate;
  2896. }
  2897. if (cooldown > 0 && timestamp - homeData.Teleports.Timestamp < cooldown)
  2898. remaining = cooldown - (timestamp - homeData.Teleports.Timestamp);
  2899. break;
  2900. case "town":
  2901. cooldown = GetLower(player, configData.Town.VIPCooldowns, configData.Town.Cooldown);
  2902. TeleportData townData;
  2903. if (!Town.TryGetValue(player.userID, out townData))
  2904. Town[player.userID] = townData = new TeleportData();
  2905. if (townData.Date != currentDate)
  2906. {
  2907. townData.Amount = 0;
  2908. townData.Date = currentDate;
  2909. }
  2910. if (cooldown > 0 && timestamp - townData.Timestamp < cooldown)
  2911. remaining = cooldown - (timestamp - townData.Timestamp);
  2912. break;
  2913. case "tpr":
  2914. cooldown = GetLower(player, configData.TPR.VIPCooldowns, configData.TPR.Cooldown);
  2915. TeleportData tprData;
  2916. if (!TPR.TryGetValue(player.userID, out tprData))
  2917. TPR[player.userID] = tprData = new TeleportData();
  2918. if (tprData.Date != currentDate)
  2919. {
  2920. tprData.Amount = 0;
  2921. tprData.Date = currentDate;
  2922. }
  2923. if (cooldown > 0 && timestamp - tprData.Timestamp < cooldown)
  2924. remaining = cooldown - (timestamp - tprData.Timestamp);
  2925. break;
  2926. }
  2927. return remaining;
  2928. }
  2929. #endregion
  2930. private class UnityVector3Converter : JsonConverter
  2931. {
  2932. public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  2933. {
  2934. var vector = (Vector3)value;
  2935. writer.WriteValue($"{vector.x} {vector.y} {vector.z}");
  2936. }
  2937. public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  2938. {
  2939. if (reader.TokenType == JsonToken.String)
  2940. {
  2941. var values = reader.Value.ToString().Trim().Split(' ');
  2942. return new Vector3(Convert.ToSingle(values[0]), Convert.ToSingle(values[1]), Convert.ToSingle(values[2]));
  2943. }
  2944. var o = JObject.Load(reader);
  2945. return new Vector3(Convert.ToSingle(o["x"]), Convert.ToSingle(o["y"]), Convert.ToSingle(o["z"]));
  2946. }
  2947. public override bool CanConvert(Type objectType)
  2948. {
  2949. return objectType == typeof(Vector3);
  2950. }
  2951. }
  2952. private class CustomComparerDictionaryCreationConverter<T> : CustomCreationConverter<IDictionary>
  2953. {
  2954. private readonly IEqualityComparer<T> comparer;
  2955. public CustomComparerDictionaryCreationConverter(IEqualityComparer<T> comparer)
  2956. {
  2957. if (comparer == null)
  2958. throw new ArgumentNullException(nameof(comparer));
  2959. this.comparer = comparer;
  2960. }
  2961. public override bool CanConvert(Type objectType)
  2962. {
  2963. return HasCompatibleInterface(objectType) && HasCompatibleConstructor(objectType);
  2964. }
  2965. private static bool HasCompatibleInterface(Type objectType)
  2966. {
  2967. return objectType.GetInterfaces().Where(i => HasGenericTypeDefinition(i, typeof(IDictionary<,>))).Any(i => typeof(T).IsAssignableFrom(i.GetGenericArguments().First()));
  2968. }
  2969. private static bool HasGenericTypeDefinition(Type objectType, Type typeDefinition)
  2970. {
  2971. return objectType.IsGenericType && objectType.GetGenericTypeDefinition() == typeDefinition;
  2972. }
  2973. private static bool HasCompatibleConstructor(Type objectType)
  2974. {
  2975. return objectType.GetConstructor(new[] { typeof(IEqualityComparer<T>) }) != null;
  2976. }
  2977. public override IDictionary Create(Type objectType)
  2978. {
  2979. return Activator.CreateInstance(objectType, comparer) as IDictionary;
  2980. }
  2981. }
  2982. }
  2983. }

Raw paste data: