Advertisement
Xyberviri

m-Teleportation.lua

Mar 29th, 2015
505
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 134.92 KB | None | 0 0
  1.  
  2. -- ----------------------------------------------------------------------------
  3. -- Teleportation System                                          Version 1.4.15
  4. -- ----------------------------------------------------------------------------
  5. -- Filename:          m-Teleportation.lua
  6. -- Last Modification: 04-25-2015
  7. -- ----------------------------------------------------------------------------
  8. -- Description:
  9. --
  10. -- This plugin is developed for Rust servers with the Oxide Server Mod and
  11. -- offers the following teleportation methods: Admin Teleports, Homes and TPR.
  12. -- ----------------------------------------------------------------------------
  13.  
  14.  
  15. PLUGIN.Title       = "Teleportation System"
  16. PLUGIN.Description = "Multiple teleportation systems for admins and players."
  17. PLUGIN.Version     = V( 1, 4, 15)
  18. PLUGIN.HasConfig   = true
  19. PLUGIN.Author      = "Mughisi"
  20. PLUGIN.ResourceId  = 660
  21.  
  22. -- ----------------------------------------------------------------------------
  23. -- Globals
  24. -- ----------------------------------------------------------------------------
  25. -- Some globals that are used in multiple functions.
  26. -- ----------------------------------------------------------------------------
  27. local PendingRequests = {}
  28. local PlayersRequests = {}
  29. local TeleportTimers  = {}
  30.  
  31. local TeleportData    = {}
  32.  
  33. local FriendsAPI      = nil
  34.  
  35. local OverlapSphere   = UnityEngine.Physics.OverlapSphere.methodarray[1]
  36. local RaycastAll      = UnityEngine.Physics.RaycastAll["methodarray"][5]
  37.  
  38. -- ----------------------------------------------------------------------------
  39. -- PLUGIN:Init()
  40. -- ----------------------------------------------------------------------------
  41. -- On plugin initialisation the required in-game chat commands are registered
  42. -- and data from the DataTable file is loaded. Also running a temporary player
  43. -- check to prevent bugs with `player.transform.position` after reloading the
  44. -- plugin.
  45. -- ----------------------------------------------------------------------------
  46. function PLUGIN:Init()
  47.     -- Add the chat commands for the Admin TP System:
  48.     command.AddChatCommand( "tp",       self.Plugin, "cmdTeleport" )
  49.     command.AddChatCommand( "tpl",      self.Plugin, "cmdTeleportLocation" )
  50.     command.AddChatCommand( "tpsave",   self.Plugin, "cmdSaveTeleportLocation" )
  51.     command.AddChatCommand( "tpremove", self.Plugin, "cmdRemoveTeleportLocation" )
  52.     command.AddChatCommand( "tpb",      self.Plugin, "cmdTeleportBack" )
  53.     command.AddChatCommand( "tpn",      self.Plugin, "cmdTeleportNear" )
  54.  
  55.     -- Add the chat commands for the Homes System:
  56.     command.AddChatCommand( "sethome",    self.Plugin, "cmdSetHome" )
  57.     command.AddChatCommand( "removehome", self.Plugin, "cmdRemoveHome" )
  58.     command.AddChatCommand( "home",       self.Plugin, "cmdTeleportHome" )
  59.     command.AddChatCommand( "listhomes",  self.Plugin, "cmdListHomes" )
  60.  
  61.     -- Add the chat commands for the TPR System:
  62.     command.AddChatCommand( "tpr", self.Plugin, "cmdTeleportRequest" )
  63.     command.AddChatCommand( "tpa", self.Plugin, "cmdTeleportAccept" )
  64.  
  65.     -- Add the Help commands:
  66.     command.AddChatCommand( "tphelp",   self.Plugin, "cmdTeleportHelp" )
  67.     command.AddChatCommand( "tplimits", self.Plugin, "cmdTeleportLimits" )
  68.  
  69.     -- Add the admin wipe command to remove all saved homes.
  70.     command.AddChatCommand( "wipehomes", self.Plugin, "cmdWipeHomes" )
  71.  
  72.     -- Add the Console commands:
  73.     command.AddConsoleCommand("teleport.toplayer", self.Plugin, "ccmdTeleport")
  74.     command.AddConsoleCommand("teleport.topos", self.Plugin, "ccmdTeleport")
  75.  
  76.     -- Load the teleport datatable file.
  77.     self:LoadSavedData()
  78.  
  79.     -- Check if the configuration file is up to date.
  80.     if self.Config.Settings.ConfigVersion ~= "1.4.15" then
  81.         -- The configuration file needs an update.
  82.         self:UpdateConfig()
  83.     end
  84. end
  85.  
  86. -- ----------------------------------------------------------------------------
  87. -- PLUGIN:OnServerInitialized()
  88. -- ----------------------------------------------------------------------------
  89. -- When the server has finished the startup process we will check if the
  90. -- required API plugins are available and get a few variables.
  91. -- ----------------------------------------------------------------------------
  92. function PLUGIN:OnServerInitialized()
  93.     -- Check if the CheckFoundationForOwner configuration value is set to true.
  94.     -- If it is true we need the plugin `Building Owners`.
  95.     if self.Config.Homes.CheckFoundationForOwner then
  96.         -- The setting CheckFoundationForOwner is true, check if
  97.         -- `Building Owners` is installed.
  98.         if not plugins.Exists( "BuildingOwners" ) then
  99.             -- The plugin isn't installed, print a message in the console and
  100.             -- disable the owner check.
  101.             print( "m-Teleportation: To limit Homes to only be set on foundations owned by the player the plugin `Building Owners` is required!" )
  102.             print( "                 This plugin can be downloaded at http://forum.rustoxide.com/plugins/building-owners.682/" )
  103.             print( "                 The owner check has temporarily been disabled to prevent problems." )
  104.             self.Config.Homes.CheckFoundationForOwner = false
  105.         end
  106.     end
  107.    
  108.     -- Check if the UseFriendsAPI configuration value is set to true. If it  is
  109.     -- true we need the plugin `FriendsAPI`.
  110.     if self.Config.Homes.UseFriendsAPI then
  111.         -- The setting CheckFoundationForOwner is true, check if `Friends API`
  112.         -- is installed.
  113.         if not plugins.Exists( "0friendsAPI" ) then
  114.             -- The plugin isn't installed, print a message in the console and
  115.             -- disable the owner check.
  116.             print( "m-Teleportation: To allow Homes to be set on foundations owned by friends of the player the plugin `Friends API` is required!" )
  117.             print( "                 This plugin can be downloaded at http://forum.rustoxide.com/plugins/friends-api.686/" )
  118.             print( "                 The friends check has temporarily been disabled to prevent problems." )
  119.             self.Config.Homes.UseFriendsAPI = false
  120.         else
  121.             -- Grab the plugin.
  122.             FriendsAPI = plugins.Find( "0friendsAPI" )
  123.         end
  124.     end
  125.    
  126.     -- "Fix" for the GetCurrentTime() problem that is causing it to throw an
  127.     -- "AmibiguousMatchException: Ambiguous matching in method resolution"
  128.     -- error when called for the first time.
  129.     status, err = pcall( time.GetCurrentTime )
  130.     date = time.GetCurrentTime():ToString( "d" )
  131. end
  132.  
  133. -- ----------------------------------------------------------------------------
  134. -- PLUGIN:LoadDefaultConfig()
  135. -- ----------------------------------------------------------------------------
  136. -- The plugin uses a configuration file to save certain settings and uses it
  137. -- for localized messages that are send in-game to the players. When this file
  138. -- doesn't exist a new one will be created with these default values.
  139. -- ----------------------------------------------------------------------------
  140. function PLUGIN:LoadDefaultConfig()
  141.     -- General Settings:
  142.     self.Config.Settings = {
  143.         ChatName          = "Teleportation",
  144.         ConfigVersion     = "1.4.15",
  145.         HomesEnabled      = true,
  146.         TPREnabled        = true,
  147.         InterruptTPOnHurt = true
  148.     }
  149.  
  150.     -- Admin TP System Settings:
  151.     self.Config.AdminTP = {
  152.         AnnounceTeleportToTarget    = false,
  153.         UseableByModerators         = true,
  154.         LocationRadius              = 25,
  155.         TeleportNearDefaultDistance = 30
  156.     }
  157.    
  158.     -- Homes System Settings:
  159.     self.Config.Homes = {
  160.         HomesLimit              = 2,
  161.         Cooldown                = 600,
  162.         Countdown               = 15,
  163.         DailyLimit              = 5,
  164.         LocationRadius          = 25,
  165.         ForceOnTopOfFoundation  = true,
  166.         CheckFoundationForOwner = true,
  167.         UseFriendsAPI           = true
  168.     }
  169.  
  170.     -- TPR System Settings:
  171.     self.Config.TPR = {
  172.         Cooldown          = 600,
  173.         Countdown         = 15,
  174.         DailyLimit        = 5,
  175.         RequestDuration   = 30,
  176.         BlockTPAOnCeiling = true
  177.     }
  178.  
  179.     -- Plugin Messages:
  180.     self.Config.Messages = {
  181.         -- Admin TP System:
  182.         AdminTP                        = "You teleported to {player}!",
  183.         AdminTPTarget                  = "{player} teleported to you!",
  184.         AdminTPPlayers                 = "You teleported {player} to {target}!",
  185.         AdminTPPlayer                  = "{admin} teleported you to {player}!",
  186.         AdminTPPlayerTarget            = "{admin} teleported {player} to you!",
  187.         AdminTPCoordinates             = "You teleported to {coordinates}!",
  188.         AdminTPTargetCoordinates       = "You teleported {player} to {coordinates}!",
  189.         AdminTPOutOfBounds             = "You tried to teleport to a set of coordinates outside the map boundaries!",
  190.         AdminTPBoundaries              = "X and Z values need to be between -{boundary} and {boundary} while the Y value needs to be between -100 and 2000!",
  191.         AdminTPLocation                = "You teleported to {location}!",
  192.         AdminTPLocationSave            = "You have saved the current location!",
  193.         AdminTPLocationRemove          = "You have removed the location {location}!",
  194.         AdminLocationList              = "The following locations are available:",
  195.         AdminLocationListEmpty         = "You haven't saved any locations!",
  196.         AdminTPBack                    = "You've teleported back to your previous location!",
  197.         AdminTPBackSave                = "Your previous location has been saved, use /tpb to teleport back!",
  198.         AdminTPTargetCoordinatesTarget = "{admin} teleported you to {coordinates}!",
  199.         AdminTPConsoleTP               = "You were teleported to {destination}",
  200.         AdminTPConsoleTPPlayer         = "You were teleported to {player}",
  201.  
  202.         -- Homes System:
  203.         HomeTP                        = "You teleported to your home '{home}'!",
  204.         HomeSave                      = "You have saved the current location as your home!",
  205.         HomeSaveFoundationOnly        = "You can only save a home location on a foundation!",
  206.         HomeFoundationNotOwned        = "You can't set your home on someone else's house.",
  207.         HomeFoundationNotFriendsOwned = "You need to be in your own or in a friend's house to set your home!",
  208.         HomeRemove                    = "You have removed your home {home}!",
  209.         HomeList                      = "The following homes are available:",
  210.         HomeListEmpty                 = "You haven't saved any homes!",
  211.         HomeMaxLocations              = "Unable to set your home here, you have reached the maximum of {amount} homes!",
  212.         HomeTPStarted                 = "Teleporting to your home {home} in {countdown} seconds!",
  213.         HomeTPCooldown                = "Your teleport is currently on cooldown. You'll have to wait {time} for your next teleport.",
  214.         HomeTPLimitReached            = "You have reached the daily limit of {limit} teleports today!",
  215.         HomesListWiped                = "You have wiped all the saved home locations!",
  216.  
  217.         -- TPR System:
  218.         Request              = "You've requested a teleport to {player}!",
  219.         RequestTarget        = "{player} requested to be teleported to you! Use '/tpa' to accept!",
  220.         PendingRequest       = "You already have a request pending, cancel that request or wait until it gets accepted or times out!",
  221.         PendingRequestTarget = "The player you wish to teleport to already has a pending request, try again later!",
  222.         NoPendingRequest     = "You have no pending teleport request!",
  223.         AcceptOnRoof         = "You can't accept a teleport while you're on a ceiling, get to ground level!",
  224.         Accept               = "{player} has accepted your teleport request! Teleporting in {countdown} seconds!",
  225.         AcceptTarget         = "You've accepted the teleport request of {player}!",
  226.         Success              = "You teleported to {player}!",
  227.         SuccessTarget        = "{player} teleported to you!",
  228.         TimedOut             = "{player} did not answer your request in time!",
  229.         TimedOutTarget       = "You did not answer {player}'s teleport request in time!",
  230.         TargetDisconnected   = "{player} has disconnected, your teleport was cancelled!",
  231.         TPRCooldown          = "Your teleport requests are currently on cooldown. You'll have to wait {time} to send your next teleport request.",
  232.         TPRLimitReached      = "You have reached the daily limit of {limit} teleport requests today!",
  233.  
  234.         -- General Messages:
  235.         Interrupted          = "Your teleport was interrupted!",
  236.         InterruptedTarget    = "{player}'s teleport was interrupted!",
  237.  
  238.         -- Help Messages:
  239.         TPHelp = {
  240.             General = {
  241.                 "Please specify the module you want to view the help of. ",
  242.                 "The available modules are: ",
  243.             },
  244.             admintp = {
  245.                 "As an admin you have access to the following commands:",
  246.                 "/tp <targetplayer> - Teleports yourself to the target player.",
  247.                 "/tp <player> <targetplayer> - Teleports the player to the target player.",
  248.                 "/tp <x> <y> <z> - Teleports you to the set of coordinates.",
  249.                 "/tpl - Shows a list of saved locations.",
  250.                 "/tpl <location name> - Teleports you to a saved location.",
  251.                 "/tpsave <location name> - Saves your current position as the location name.",
  252.                 "/tpremove <location name> - Removes the location from your saved list.",
  253.                 "/tpb - Teleports you back to the place where you were before teleporting."
  254.             },
  255.  
  256.             home = {
  257.                 "With the following commands you can set your home location to teleport back to:",
  258.                 "/sethome <home name> - Saves your current position as the location name.",
  259.                 "/listhomes - Shows you a list of all the locations you have saved.",
  260.                 "/removehome <home name> - Removes the location of your saved homes.",
  261.                 "/home <home name> - Teleports you to the home location."
  262.             },
  263.             tpr = {
  264.                 "With these commands you can request to be teleported to a player or accept someone else's request:",
  265.                 "/tpr <player name> - Sends a teleport request to the player.",
  266.                 "/tpa - Accepts an incoming teleport request."
  267.             }
  268.         },
  269.  
  270.         -- Settings Messages:
  271.         TPSettings = {
  272.             General = {
  273.                 "Please specify the module you want to view the settings of. ",
  274.                 "The available modules are: ",
  275.             },
  276.             home = {
  277.                 "Home System as the current settings enabled: ",
  278.                 "Time between teleports: {cooldown}",
  279.                 "Daily amount of teleports: {limit}",
  280.                 "Amount of saved Home locations: {amount}"
  281.             },
  282.             tpr = {
  283.                 "TPR System as the current settings enabled: ",
  284.                 "Time between teleports: {cooldown}",
  285.                 "Daily amount of teleports: {limit}"
  286.             }
  287.         },
  288.  
  289.         -- Error Messages:
  290.         PlayerNotFound           = "The specified player couldn't be found please try again!",
  291.         MultiplePlayersFound     = "Found multiple players with that name!",
  292.         CantTeleportToSelf       = "You can't teleport to yourself!",
  293.         CantTeleportPlayerToSelf = "You can't teleport a player to himself!",
  294.         TeleportPending          = "You can't initiate another teleport while you have a teleport pending!",
  295.         TeleportPendingTarget    = "You can't request a teleport to someone who's about to teleport!",
  296.         LocationExists           = "A location with this name already exists at {location}!",
  297.         LocationExistsNearby     = "A location with the name {name} already exists near this position!",
  298.         LocationNotFound         = "Couldn't find a location with that name!",
  299.         NoPreviousLocationSaved  = "No previous location saved!",
  300.         HomeExists               = "You have already saved a home location by this name!",
  301.         HomeExistsNearby         = "A home location with the name {name} already exists near this position!",
  302.         HomeNotFound             = "Couldn't find your home with that name!",
  303.         InvalidCoordinates       = "The coordinates you've entered are invalid!",
  304.         InvalidHelpModule        = "Invalid module supplied!",
  305.         InvalidCharacter         = "You have used an invalid character, please limit yourself to the letters a to z and numbers.",
  306.  
  307.         -- Syntax Errors Admin TP System:
  308.         SyntaxCommandTP = {
  309.             "A Syntax Error Occurred!",
  310.             "You can only use the /tp command as follows:",
  311.             "/tp <targetplayer> - Teleports yourself to the target player.",
  312.             "/tp <player> <targetplayer> - Teleports the player to the target player.",
  313.             "/tp <x> <y> <z> - Teleports you to the set of coordinates.",
  314.             "/tp <player> <x> <y> <z> - Teleports the player to the set of coordinates."
  315.         },
  316.         SyntaxCommandTPL = {
  317.             "A Syntax Error Occurred!",
  318.             "You can only use the /tpl command as follows:",
  319.             "/tpl - Shows a list of saved locations.",
  320.             "/tpl <location name> - Teleports you to a saved location."
  321.         },
  322.         SyntaxCommandTPSave = {
  323.             "A Syntax Error Occurred!",
  324.             "You can only use the /tpsave command as follows:",
  325.             "/tpsave <location name> - Saves your current position as 'location name'."
  326.         },
  327.         SyntaxCommandTPRemove = {
  328.             "A Syntax Error Occurred!",
  329.             "You can only use the /tpremove command as follows:",
  330.             "/tpremove <location name> - Removes the location with the name 'location name'."
  331.         },
  332.         SyntaxCommandTPN = {
  333.             "A Syntax Error Occurred!",
  334.             "You can only use the /tpn command as follows:",
  335.             "/tpn <targetplayer> - Teleports yourself the default distance behind the target player.",
  336.             "/tpn <targetplayer> <distance> - Teleports you the specified distance behind the target player."
  337.         },
  338.  
  339.         -- Syntax Errors Home System:
  340.         SyntaxCommandSetHome = {
  341.             "A Syntax Error Occurred!",
  342.             "You can only use the /sethome command as follows:",
  343.             "/sethome <home name> - Saves the current location as your home with the name 'home name'."
  344.         },
  345.         SyntaxCommandRemoveHome = {
  346.             "A Syntax Error Occurred!",
  347.             "You can only use the /removehome command as follows:",
  348.             "/removehome <home name> - Removes the home location with the name 'location name'."
  349.         },
  350.         SyntaxCommandHome = {
  351.             "A Syntax Error Occurred!",
  352.             "You can only use the /home command as follows:",
  353.             "/home <home name> - Teleports yourself to your home with the name 'home name'."
  354.         },
  355.         SyntaxCommandListHomes = {
  356.             "A Syntax Error Occurred!",
  357.             "You can only use the /listhomes command as follows:",
  358.             "/listhomes - Shows you a list of all your saved home locations."
  359.         },
  360.  
  361.         -- Syntax Errors TPR System:
  362.         SyntaxCommandTPR = {
  363.             "A Syntax Error Occurred!",
  364.             "You can only use the /tpr command as follows:",
  365.             "/tpr <player name> - Sends out a teleport request to 'player name'."
  366.         },
  367.         SyntaxCommandTPA = {
  368.             "A Syntax Error Occurred!",
  369.             "You can only use the /tpa command as follows:",
  370.             "/tpa - Accepts an incoming teleport request."
  371.         },
  372.         SyntaxConsoleCommandToPos = {
  373.             "A Syntax Error Occurred!",
  374.             "You can only use the teleport.topos console command as follows:",
  375.             " > teleport.topos \"player\" x y z"
  376.         },
  377.         SyntaxConsoleCommandToPlayer = {
  378.             "A Syntax Error Occurred!",
  379.             "You can only use the teleport.toplayer console command as follows:",
  380.             " > teleport.toplayer \"player\" \"target player\""
  381.         }
  382.     }
  383. end
  384.  
  385. -- ----------------------------------------------------------------------------
  386. -- PLUGIN:UpdateConfig()
  387. -- ----------------------------------------------------------------------------
  388. -- Updates the configuration file when required.
  389. -- ----------------------------------------------------------------------------
  390. function PLUGIN:UpdateConfig()
  391.     if self.Config.Settings.ConfigVersion == "1.0.0" then
  392.         -- Change the config version.
  393.         self.Config.Settings.ConfigVersion = "1.1"
  394.  
  395.         -- Modify the changed config values.
  396.         self.Config.Messages.MultiplePlayersFound = "Found multiple players with that name!"
  397.  
  398.         -- Send a console message to notify the server owner of this change.
  399.         print( "m-Teleportation: Your config file was updated to config version 1.1, 1 new message was added to the configuration file!" )
  400.     end
  401.  
  402.     if self.Config.Settings.ConfigVersion == "1.1" then
  403.         -- Change the config version.
  404.         self.Config.Settings.ConfigVersion = "1.1.0"
  405.        
  406.         -- Modify the changed config values.
  407.         table.insert( self.Config.Messages.SyntaxCommandTP, "/tp <player> <x> <y> <z> - Teleports the player to the set of coordinates." )
  408.         self.Config.Messages.SyntaxConsoleCommandToPos      = { "A Syntax Error Occurred!", "You can only use the teleport.topos console command as follows:", " > teleport.topos \"player\" x y z" }
  409.         self.Config.Messages.SyntaxConsoleCommandToPlayer   = { "A Syntax Error Occurred!", "You can only use the teleport.toplayer console command as follows:", " > teleport.toplayer \"player\" \"target player\"" }
  410.         self.Config.Messages.AdminTPTargetCoordinates       = "You teleported {player} to {coordinates}!"
  411.         self.Config.Messages.AdminTPTargetCoordinatesTarget = "{admin} teleported you to {coordinates}!"
  412.         self.Config.Messages.AdminTPConsoleTP               = "You were teleported to {destination}"
  413.         self.Config.Messages.AdminTPConsoleTPPlayer         = "You were teleported to {player}"
  414.  
  415.         -- Send a console message to notify the server owner of this change.
  416.         print( "m-Teleportation: Your config file was updated to config version 1.1.0, 7 new messages were added to the configuration file!" )
  417.     end
  418.  
  419.     if self.Config.Settings.ConfigVersion == "1.1.0" then
  420.         -- Change the config version.
  421.         self.Config.Settings.ConfigVersion = "1.2.0"
  422.  
  423.         -- Modify the changed config values.
  424.         self.Config.Homes.UseFriendsAPI                    = true
  425.         self.Config.Messages.HomeFoundationNotFriendsOwned = "You need to be in your own or in a friend's house to set your home!"
  426.         self.Config.Messages.InvalidCharacter              = "You have used an invalid character, please limit yourself to the letters a to z and numbers.",
  427.  
  428.         -- Send a console message to notify the server owner of this change.
  429.         print( "m-Teleportation: Your config file was updated to config version 1.2.0, 1 new value and 2 new messages were added to the configuration file!" )
  430.     end
  431.  
  432.     if self.Config.Settings.ConfigVersion == "1.2.0" then
  433.         -- Change the config version.
  434.         self.Config.Settings.ConfigVersion = "1.2.1"
  435.        
  436.         -- Modify the changed config values.
  437.         self.Config.Messages.AdminTPBoundaries = "X and Z values need to be between -{boundary} and {boundary} while the Y value needs to be between -100 and 2000!"
  438.        
  439.         -- Send a console message to notify the server owner of this change.
  440.         print( "m-Teleportation: Your config file was updated to config version 1.2.1, 1 value was modified!" )
  441.     end
  442.    
  443.     if self.Config.Settings.ConfigVersion == "1.2.1" then
  444.         -- Change the config version.
  445.         self.Config.Settings.ConfigVersion = "1.3.0"
  446.  
  447.         -- Modify the changed config values.
  448.         self.Config.AdminTP.TeleportNearDefaultDistance = 30
  449.         self.Config.Messages.HomesListWiped = "You have wiped all the saved home locations!"
  450.         self.Config.Messages.SyntaxCommandTPN = {
  451.             "A Syntax Error Occurred!",
  452.             "You can only use the /tpn command as follows:",
  453.             "/tpn <targetplayer> - Teleports yourself the default distance behind the target player.",
  454.             "/tpn <targetplayer> <distance> - Teleports you the specified distance behind the target player."
  455.         }
  456.  
  457.         -- Send a console message to notify the server owner of this change.
  458.         print( "m-Teleportation: Your config file was updated to config version 1.3.0, 5 new values were added!" )
  459.     end
  460.    
  461.     if self.Config.Settings.ConfigVersion == "1.3.0" then
  462.         -- Change the config version.
  463.         self.Config.Settings.ConfigVersion = "1.4.0"
  464.  
  465.         -- Send a console message to notify the server owner of this change.
  466.         print( "m-Teleportation: Your config file was updated to config version 1.4.0, version indication was updated!" )
  467.     end
  468.    
  469.     if self.Config.Settings.ConfigVersion == "1.4.0" then
  470.         -- Change the config version.
  471.         self.Config.Settings.ConfigVersion = "1.4.1"
  472.  
  473.         -- Send a console message to notify the server owner of this change.
  474.         print( "m-Teleportation: Your config file was updated to config version 1.4.1, version indication was updated!" )
  475.     end
  476.    
  477.     if self.Config.Settings.ConfigVersion == "1.4.1" then
  478.         -- Change the config version.
  479.         self.Config.Settings.ConfigVersion = "1.4.2"
  480.  
  481.         -- Send a console message to notify the server owner of this change.
  482.         print( "m-Teleportation: Your config file was updated to config version 1.4.2, version indication was updated!" )
  483.     end
  484.    
  485.     if self.Config.Settings.ConfigVersion == "1.4.2" then
  486.         -- Change the config version.
  487.         self.Config.Settings.ConfigVersion = "1.4.3"
  488.  
  489.         -- Send a console message to notify the server owner of this change.
  490.         print( "m-Teleportation: Your config file was updated to config version 1.4.3, version indication was updated!" )
  491.     end
  492.    
  493.     if self.Config.Settings.ConfigVersion == "1.4.3" then
  494.         -- Change the config version.
  495.         self.Config.Settings.ConfigVersion = "1.4.4"
  496.  
  497.         -- Send a console message to notify the server owner of this change.
  498.         print( "m-Teleportation: Your config file was updated to config version 1.4.4, version indication was updated!" )
  499.     end
  500.    
  501.     if self.Config.Settings.ConfigVersion == "1.4.4" then
  502.         -- Change the config version.
  503.         self.Config.Settings.ConfigVersion = "1.4.5"
  504.  
  505.         -- Send a console message to notify the server owner of this change.
  506.         print( "m-Teleportation: Your config file was updated to config version 1.4.5, version indication was updated!" )
  507.     end
  508.    
  509.     if self.Config.Settings.ConfigVersion == "1.4.5" then
  510.         -- Change the config version.
  511.         self.Config.Settings.ConfigVersion = "1.4.6"
  512.  
  513.         -- Send a console message to notify the server owner of this change.
  514.         print( "m-Teleportation: Your config file was updated to config version 1.4.6, version indication was updated!" )
  515.     end
  516.    
  517.     if self.Config.Settings.ConfigVersion == "1.4.6" then
  518.         -- Change the config version.
  519.         self.Config.Settings.ConfigVersion = "1.4.7"
  520.  
  521.         -- Send a console message to notify the server owner of this change.
  522.         print( "m-Teleportation: Your config file was updated to config version 1.4.7, version indication was updated!" )
  523.     end
  524.    
  525.     if self.Config.Settings.ConfigVersion == "1.4.7" then
  526.         -- Change the config version.
  527.         self.Config.Settings.ConfigVersion = "1.4.8"
  528.  
  529.         -- Send a console message to notify the server owner of this change.
  530.         print( "m-Teleportation: Your config file was updated to config version 1.4.8, version indication was updated!" )
  531.     end
  532.    
  533.     if self.Config.Settings.ConfigVersion == "1.4.8" then
  534.         -- Change the config version.
  535.         self.Config.Settings.ConfigVersion = "1.4.9"
  536.  
  537.         -- Send a console message to notify the server owner of this change.
  538.         print( "m-Teleportation: Your config file was updated to config version 1.4.9, version indication was updated!" )
  539.     end
  540.    
  541.     if self.Config.Settings.ConfigVersion == "1.4.9" then
  542.         -- Change the config version.
  543.         self.Config.Settings.ConfigVersion = "1.4.12"
  544.  
  545.         -- Send a console message to notify the server owner of this change.
  546.         print( "m-Teleportation: Your config file was updated to config version 1.4.12, version indication was updated!" )
  547.     end
  548.    
  549.     if self.Config.Settings.ConfigVersion == "1.4.12" then
  550.         -- Change the config version.
  551.         self.Config.Settings.ConfigVersion = "1.4.13"
  552.  
  553.         -- Send a console message to notify the server owner of this change.
  554.         print( "m-Teleportation: Your config file was updated to config version 1.4.13, version indication was updated!" )
  555.     end
  556.    
  557.     if self.Config.Settings.ConfigVersion == "1.4.13" then
  558.         -- Change the config version.
  559.         self.Config.Settings.ConfigVersion = "1.4.14"
  560.  
  561.         -- Send a console message to notify the server owner of this change.
  562.         print( "m-Teleportation: Your config file was updated to config version 1.4.14, version indication was updated!" )
  563.     end
  564.    
  565.     if self.Config.Settings.ConfigVersion == "1.4.14" then
  566.         -- Change the config version.
  567.         self.Config.Settings.ConfigVersion = "1.4.15"
  568.  
  569.         -- Send a console message to notify the server owner of this change.
  570.         print( "m-Teleportation: Your config file was updated to config version 1.4.15, version indication was updated!" )
  571.     end
  572.  
  573.     -- Save the config.
  574.     self:SaveConfig()
  575. end
  576.  
  577. -- ----------------------------------------------------------------------------
  578. -- PLUGIN:LoadSavedData()
  579. -- ----------------------------------------------------------------------------
  580. -- Load the DataTable file into a table or create a new table when the file
  581. -- doesn't exist yet.
  582. -- ----------------------------------------------------------------------------
  583. function PLUGIN:LoadSavedData()
  584.     -- Open the datafile if it exists, otherwise we'll create a new one.
  585.     TeleportData           = datafile.GetDataTable( "m-Teleportation" )
  586.     TeleportData           = TeleportData or {}
  587.     TeleportData.AdminData = TeleportData.AdminData or {}
  588.     TeleportData.HomeData  = TeleportData.HomeData or {}
  589.     TeleportData.TPRData   = TeleportData.TPRData or {}
  590. end
  591.  
  592. -- ----------------------------------------------------------------------------
  593. -- PLUGIN:SaveData()
  594. -- ----------------------------------------------------------------------------
  595. -- Saves the table with all the teleportdata to a DataTable file.
  596. -- ----------------------------------------------------------------------------
  597. function PLUGIN:SaveData()  
  598.     -- Save the DataTable
  599.     datafile.SaveDataTable( "m-Teleportation" )
  600. end
  601.  
  602. -- ----------------------------------------------------------------------------
  603. -- PLUGIN:cmdTeleport( player, cmd, args )                        Admin Command
  604. -- ----------------------------------------------------------------------------
  605. -- In-game '/tp' command for server admins to be able to teleport to players,
  606. -- teleport players to other players and to teleport to a set of coordinates on
  607. -- the map.
  608. -- ----------------------------------------------------------------------------
  609. function PLUGIN: cmdTeleport( player, cmd, args )
  610.     -- Check if the player is allowed to run the command.
  611.     if not self:IsAllowed( player ) then return end
  612.  
  613.     -- Determine what the player is trying to do depending on the amount of
  614.     -- arguments that the player has supplied.
  615.     if args.Length == 1 then
  616.         -- The player supplied one argument, assuming that the player is
  617.         -- attempting to teleport himself/herself to another online player.
  618.  
  619.         -- Search for the BasePlayer for the given (partial) name.
  620.         local targetPlayer = self:FindPlayerByName( args[0] )
  621.  
  622.         -- Check if we found the targetted player.
  623.         if #targetPlayer == 0 then
  624.             -- The targetted player couldn't be found, send a message to the
  625.             -- player.
  626.             self:SendMessage( player, self.Config.Messages.PlayerNotFound )
  627.  
  628.             return
  629.         end
  630.  
  631.         -- Check if we found multiple players with that partial name.
  632.         if #targetPlayer > 1 then
  633.             -- Multiple players were found, send a message to the player.
  634.             self:SendMessage( player, self.Config.Messages.MultiplePlayersFound )
  635.  
  636.             return
  637.         else
  638.             -- Only one player was found, modify the targetPlayer variable
  639.             -- value.
  640.             targetPlayer = targetPlayer[1]
  641.         end
  642.  
  643.         -- Check if the targetted player isn't the player that is running the
  644.         -- command.
  645.         if player == targetPlayer then
  646.             -- The player and the targetted player are the same, send a message
  647.             -- to the player.
  648.             self:SendMessage( player, self.Config.Messages.CantTeleportToSelf )
  649.            
  650.             return
  651.         end
  652.  
  653.         -- The targetted player was found and is a valid target. Save the
  654.         -- player his current location for the '/tpb' command and initiate a
  655.         -- teleport to the target.
  656.         self:SaveLocation( player )
  657.         self:TeleportToPlayer( player, targetPlayer )
  658.  
  659.         -- Show a message to the player.
  660.         self:SendMessage( player, self:Parse( self.Config.Messages.AdminTP, { player = targetPlayer.displayName } ) )
  661.  
  662.         -- Check the settings if we're supposed to send a message to the
  663.         -- targetted player or not.
  664.         if self.Config.AdminTP.AnnounceTeleportToTarget then
  665.             -- Send the message to the targetted player.
  666.             self:SendMessage( targetPlayer, self:Parse( self.Config.Messages.AdminTPTarget, { player = player.displayName } ) )
  667.         end
  668.     elseif args.Length == 2 then
  669.         -- The player supplied two arguments, assuming that the player is
  670.         -- attempting to teleport a different player to another player.
  671.  
  672.         -- Search for the BasePlayer for the given (partial) names.
  673.         local originPlayer = self:FindPlayerByName( args[0] )
  674.         local targetPlayer = self:FindPlayerByName( args[1] )
  675.  
  676.         -- Check if we found the targetted player.
  677.         if #originPlayer == 0 or #targetPlayer == 0 then
  678.             -- One or both players couldn't be found, send a message to the
  679.             -- player.
  680.             self:SendMessage( player, self.Config.Messages.PlayerNotFound )
  681.  
  682.             return
  683.         end
  684.  
  685.         -- Check if we found multiple players with that partial name.
  686.         if #originPlayer > 1 or #targetPlayer > 1 then
  687.             -- Multiple players were found, send a message to the player.
  688.             self:SendMessage( player, self.Config.Messages.MultiplePlayersFound )
  689.  
  690.             return
  691.         else
  692.             -- Only one player was found, modify the targetPlayer variable
  693.             -- value.
  694.             originPlayer = originPlayer[1]
  695.             targetPlayer = targetPlayer[1]
  696.         end
  697.  
  698.         -- Check if the origin player is different from the targetted player.
  699.         if originPlayer == targetPlayer then
  700.             -- Both players are the same, send a message to the player.
  701.             self:SendMessage( player, self.Config.Messages.CantTeleportPlayerToSelf )
  702.  
  703.             return
  704.         end
  705.  
  706.         -- Check if the player is teleporting himself.
  707.         if self:IsAllowed( originPlayer ) then
  708.             -- The player is teleporting himself so we need to save his current
  709.             -- location.
  710.             self:SaveLocation( player )
  711.         end
  712.  
  713.         -- Both players were found and are valid. Initiate a teleport for the
  714.         -- origin player to the targetted player.
  715.         self:TeleportToPlayer( originPlayer, targetPlayer )
  716.  
  717.         -- Show a message to the player, origin player and targetted player.
  718.         self:SendMessage( player, self:Parse( self.Config.Messages.AdminTPPlayers, { player = originPlayer.displayName, target = targetPlayer.displayName } ) )
  719.         self:SendMessage( originPlayer, self:Parse( self.Config.Messages.AdminTPPlayer, { admin = player.displayName, player = targetPlayer.displayName } ) )
  720.         self:SendMessage( targetPlayer, self:Parse( self.Config.Messages.AdminTPPlayerTarget, { admin = player.displayName, player = originPlayer.displayName } ) )
  721.     elseif args.Length == 3 then
  722.         -- The player supplied three arguments, assuming that the player is
  723.         -- attempting to teleport himself/herself to a set of coordinates.
  724.  
  725.         -- Store the coordinates as numbers into variables.
  726.         local x = tonumber( args[0] )
  727.         local y = tonumber( args[1] )
  728.         local z = tonumber( args[2] )
  729.  
  730.         -- Validate the three coordinates, first check if all three are numbers
  731.         -- and then check if the coordinates are within the map boundaries.
  732.         if x and y and z then
  733.             -- The three supplied axis values are numbers, check if they are
  734.             -- within the boundaries of the map.
  735.             local boundary = global.TerrainMeta.get_Size().x / 2
  736.  
  737.             if ( x <= boundary and x >= -boundary ) and ( y < 2000 and y >= -100 ) and ( z <= boundary and z >= -boundary ) then
  738.                 -- A valid location was specified, save the player his current
  739.                 -- location for the '/tpb' command and initiate a teleport.
  740.                 self:SaveLocation( player )
  741.                 self:TeleportToPosition( player, x, y, z )
  742.  
  743.                 -- Show a message to the player.
  744.                 self:SendMessage(player, self:Parse( self.Config.Messages.AdminTPCoordinates, { coordinates = x .. " " .. y .. " " .. z } ) )
  745.             else
  746.                 -- One or more axis values are out of bounds, show a message to
  747.                 -- the player.
  748.                 self:SendMessage( player, self.Config.Messages.AdminTPOutOfBounds )
  749.                 self:SendMessage( player, self:Parse( self.Config.Messages.AdminTPBoundaries, { boundary = boundary } ) )
  750.             end
  751.         else
  752.             -- One or more axis values are not a number and are invalid, show a
  753.             -- a message to the player.
  754.             self:SendMessage( player, self.Config.Messages.InvalidCoordinates )
  755.         end
  756.     elseif args.Length == 4 then
  757.         -- The player supplied four arguments, assuming that the player is
  758.         -- attempting to teleport a player to a set of coordinates.
  759.        
  760.         -- Search for the BasePlayer for the given (partial) name.
  761.         local targetPlayer = self:FindPlayerByName( args[0] )
  762.  
  763.         -- Check if we found the targetted player.
  764.         if #targetPlayer == 0 then
  765.             -- The targetted player couldn't be found, send a message to the
  766.             -- player.
  767.             self:SendMessage( player, self.Config.Messages.PlayerNotFound )
  768.  
  769.             return
  770.         end
  771.  
  772.         -- Check if we found multiple players with that partial name.
  773.         if #targetPlayer > 1 then
  774.             -- Multiple players were found, send a message to the player.
  775.             self:SendMessage( player, self.Config.Messages.MultiplePlayersFound )
  776.  
  777.             return
  778.         else
  779.             -- Only one player was found, modify the targetPlayer variable
  780.             -- value.
  781.             targetPlayer = targetPlayer[1]
  782.         end
  783.  
  784.         -- Store the coordinates as numbers into variables.
  785.         local x = tonumber( args[1] )
  786.         local y = tonumber( args[2] )
  787.         local z = tonumber( args[3] )
  788.  
  789.         -- Validate the three coordinates, first check if all three are numbers
  790.         -- and then check if the coordinates are within the map boundaries.
  791.         if x and y and z then
  792.             -- The three supplied axis values are numbers, check if they are
  793.             -- within the boundaries of the map.
  794.             local boundary = global.TerrainMeta.get_Size().x / 2
  795.  
  796.             if ( x <= boundary and x >= -boundary ) and ( y < 2000 and y >= -100 ) and ( z <= boundary and z >= -boundary ) then
  797.                 -- A valid location was specified, save the player his/her
  798.                 -- current location for the '/tpb' command if necessary and
  799.                 -- initiate a teleport.
  800.                 if self:IsAllowed( targetPlayer ) then
  801.                     -- The player is an admin so we need to save his current
  802.                     -- location.
  803.                     self:SaveLocation( targetPlayer )
  804.                 end
  805.  
  806.                 self:TeleportToPosition( targetPlayer, x, y, z )
  807.  
  808.                 -- Show a message to the player.
  809.                 if player == targetPlayer then
  810.                     self:SendMessage(player, self:Parse( self.Config.Messages.AdminTPCoordinates, { coordinates = x .. " " .. y .. " " .. z } ) )
  811.                 else
  812.                     self:SendMessage(player, self:Parse( self.Config.Messages.AdminTPTargetCoordinates, { player = targetPlayer.displayName, coordinates = x .. " " .. y .. " " .. z } ) )
  813.                     self:SendMessage(targetPlayer, self:Parse( self.Config.Messages.AdminTPTargetCoordinatesTarget, { admin = player.displayName, coordinates = x .. " " .. y .. " " .. z } ) )
  814.                 end
  815.             else
  816.                 -- One or more axis values are out of bounds, show a message to
  817.                 -- the player.
  818.                 self:SendMessage( player, self.Config.Messages.AdminTPOutOfBounds )
  819.                 self:SendMessage( player, self:Parse( self.Config.Messages.AdminTPBoundaries, { boundary = boundary } ) )
  820.             end
  821.         else
  822.             -- One or more axis values are not a number and are invalid, show a
  823.             -- a message to the player.
  824.             self:SendMessage( player, self.Config.Messages.InvalidCoordinates )
  825.         end
  826.     else
  827.         -- No arguments or an invalid amount of arguments were supplied, send a
  828.         -- message to the player with the available command possibilities.
  829.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTP )
  830.     end
  831. end
  832.  
  833. -- ----------------------------------------------------------------------------
  834. -- PLUGIN:cmdTeleportNear( player, cmd, args )                    Admin Command
  835. -- ----------------------------------------------------------------------------
  836. -- In-game '/tpn' command for server admins to be able to teleport near a
  837. -- player.
  838. -- ----------------------------------------------------------------------------
  839. function PLUGIN: cmdTeleportNear( player, cmd, args )
  840.     -- Check if the player is allowed to run the command.
  841.     if not self:IsAllowed( player ) then return end
  842.  
  843.     -- Determine what the player is trying to do depending on the amount of
  844.     -- arguments that the player has supplied.
  845.     if args.Length == 1 or args.Length == 2 then
  846.         -- The player supplied one argument, assuming that the player is
  847.         -- attempting to teleport himself/herself to another online player.
  848.  
  849.         -- Search for the BasePlayer for the given (partial) name.
  850.         local targetPlayer = self:FindPlayerByName( args[0] )
  851.  
  852.         -- Check if we found the targetted player.
  853.         if #targetPlayer == 0 then
  854.             -- The targetted player couldn't be found, send a message to the
  855.             -- player.
  856.             self:SendMessage( player, self.Config.Messages.PlayerNotFound )
  857.  
  858.             return
  859.         end
  860.  
  861.         -- Check if we found multiple players with that partial name.
  862.         if #targetPlayer > 1 then
  863.             -- Multiple players were found, send a message to the player.
  864.             self:SendMessage( player, self.Config.Messages.MultiplePlayersFound )
  865.  
  866.             return
  867.         else
  868.             -- Only one player was found, modify the targetPlayer variable
  869.             -- value.
  870.             targetPlayer = targetPlayer[1]
  871.         end
  872.  
  873.         -- Check if the targetted player isn't the player that is running the
  874.         -- command.
  875.         if player == targetPlayer then
  876.             -- The player and the targetted player are the same, send a message
  877.             -- to the player.
  878.             self:SendMessage( player, self.Config.Messages.CantTeleportToSelf )
  879.            
  880.             return
  881.         end
  882.  
  883.         -- Determine the distance behind the player.
  884.         local distance = tonumber( self.Config.AdminTP.TeleportNearDefaultDistance )
  885.  
  886.         -- Check if a different distance was supplied.
  887.         if args.Length == 2 then
  888.             if tonumber( args[1] ) then
  889.                 distance = tonumber( args[1] )
  890.             end
  891.         end
  892.  
  893.         -- Generate a random x value between 0 and the distance required.
  894.         local targetX = math.random( -distance, distance )
  895.         local targetZ = math.sqrt( math.pow( distance, 2 ) - math.pow( targetX, 2 ) )
  896.  
  897.         local destination = targetPlayer.transform.position
  898.         destination.x = destination.x - targetX
  899.         destination.y = 5000
  900.         destination.z = destination.z - targetZ
  901.  
  902.         -- Calculate the height at the new coordinates.
  903.         destination = self:GetGround( destination )
  904.  
  905.         -- The targetted player was found and is a valid target. Save the
  906.         -- player his/her current location for the '/tpb' command and initiate
  907.         -- a teleport to the target.
  908.         self:SaveLocation( player )
  909.         self:TeleportToPosition( player, destination.x, destination.y, destination.z )
  910.        
  911.         -- Show a message to the player.
  912.         self:SendMessage( player, self:Parse( self.Config.Messages.AdminTP, { player = targetPlayer.displayName } ) )
  913.  
  914.         -- Check the settings if we're supposed to send a message to the
  915.         -- targetted player or not.
  916.         if self.Config.AdminTP.AnnounceTeleportToTarget then
  917.             -- Send the message to the targetted player.
  918.             self:SendMessage( targetPlayer, self:Parse( self.Config.Messages.AdminTPTarget, { player = player.displayName } ) )
  919.         end
  920.     else
  921.         -- No arguments or an invalid amount of arguments were supplied, send a
  922.         -- message to the player with the available command possibilities.
  923.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTPN )
  924.     end
  925. end
  926.  
  927. -- ----------------------------------------------------------------------------
  928. -- PLUGIN:cmdTeleportLocation( player, cmd, args )                Admin Command
  929. -- ----------------------------------------------------------------------------
  930. -- In-game '/tpl' command that allows a server admin to teleport to a
  931. -- previously saved location or to get a list of all saved locations.
  932. -- ----------------------------------------------------------------------------
  933. function PLUGIN:cmdTeleportLocation( player, cmd, args )
  934.     -- Check if the player is allowed to run the command.
  935.     if not self:IsAllowed( player ) then return end
  936.  
  937.     -- Grab the player his/her SteamID.
  938.     local playerID = rust.UserIDFromPlayer( player )
  939.  
  940.     -- Determine what the player is trying to do depending on the amount of
  941.     -- arguments that the player has supplied.
  942.     if args.Length == 0 then
  943.         -- The player didn't supply any arguments, assuming that the player
  944.         -- wants to get a list of all his available teleport locations.
  945.  
  946.         -- Check if there is data saved for the player, after that check if the
  947.         -- data contains any saved locations for the player.
  948.         if TeleportData.AdminData[playerID] then
  949.             if self:Count( TeleportData.AdminData[playerID].SavedLocations ) > 0 then
  950.                 -- The player has one or more save locations available, show a
  951.                 -- message to the player and show him/her all the available
  952.                 -- saved locations.
  953.                 self:SendMessage( player, self.Config.Messages.AdminLocationList )
  954.  
  955.                 -- Loop through all the saved locations and print them one by
  956.                 -- one.
  957.                 for location, coordinates in pairs( TeleportData.AdminData[playerID].SavedLocations ) do
  958.                     self:SendMessage( player, location .. ": " .. math.floor( coordinates.x ) .. " " .. math.floor( coordinates.y ) .. " " .. math.floor( coordinates.z ) )
  959.                 end
  960.  
  961.                 return
  962.             end
  963.         end
  964.  
  965.         -- The player has no saved locations available, show a message to
  966.         -- him/her.
  967.         self:SendMessage( player, self.Config.Messages.AdminLocationListEmpty )
  968.     elseif args.Length == 1 then
  969.         -- The player supplied one argument, assuming that the player is
  970.         -- attempting to teleport himself/herself to a saved location.
  971.  
  972.         -- Check if there is data saved for the player, after that check if the
  973.         -- data contains any saved locations for the player.
  974.         if TeleportData.AdminData[playerID] then
  975.             if self:Count( TeleportData.AdminData[playerID].SavedLocations ) > 0 then
  976.                 -- The player has one or more save locations available, check
  977.                 -- if the location that the player specified is a saved
  978.                 -- location.
  979.  
  980.                 -- Set some variables to store the location in when we find it.
  981.                 local locationFound       = false
  982.                 local locationCoordinates = nil
  983.  
  984.                 -- Loop through all the saved locations for the player and
  985.                 -- check for a match against the entered location.
  986.                 for location, coordinates in pairs( TeleportData.AdminData[playerID].SavedLocations ) do
  987.                     if string.lower( args[0] ) == string.lower( location ) then
  988.                         -- We found a match for the entered location.
  989.                         locationFound       = true
  990.                         locationCoordinates = coordinates
  991.  
  992.                         -- Exit the loop.
  993.                         break
  994.                     end
  995.                 end
  996.                
  997.                 if not locationFound then
  998.                     self:SendMessage( player, self.Config.Messages.LocationNotFound )
  999.  
  1000.                     return
  1001.                 end
  1002.                 -- A valid location was specified, save the player his current
  1003.                 -- location for the '/tpb' command and initiate a teleport.
  1004.                 self:SaveLocation( player )
  1005.                 self:TeleportToPosition( player, locationCoordinates.x, locationCoordinates.y, locationCoordinates.z )
  1006.  
  1007.                 -- Send a message to the player.
  1008.                 self:SendMessage( player, self:Parse( self.Config.Messages.AdminTPLocation, { location = args[0] } ) )
  1009.  
  1010.                 return
  1011.             end
  1012.         end
  1013.  
  1014.         -- The player has no saved locations available, show a message to
  1015.         -- him/her.
  1016.         self:SendMessage( player, self.Config.Messages.AdminLocationListEmpty )
  1017.     else
  1018.         -- An invalid amount of arguments were supplied, send a message to the
  1019.         -- player with the available command possibilities.
  1020.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTPL )
  1021.     end
  1022. end
  1023.  
  1024. -- ----------------------------------------------------------------------------
  1025. -- PLUGIN:cmdSaveTeleportLocation( player, cmd, args )            Admin command
  1026. -- ----------------------------------------------------------------------------
  1027. -- In-game '/tpsave' command that allows a server admin to save his current
  1028. -- location to be able to teleport to it later.
  1029. -- ----------------------------------------------------------------------------
  1030. function PLUGIN:cmdSaveTeleportLocation( player, cmd, args )
  1031.      -- Check if the player is allowed to run the command.
  1032.     if not self:IsAllowed( player ) then return end
  1033.  
  1034.     -- Grab the player his/her SteamID.
  1035.     local playerID = rust.UserIDFromPlayer( player )
  1036.  
  1037.     -- Determine what the player is trying to do depending on the amount of
  1038.     -- arguments that the player has supplied.
  1039.     if args.Length == 1 then
  1040.         -- The player supplied one argument, assuming that the player is
  1041.         -- attempting to save his/her current location.
  1042.        
  1043.         -- Check if the tables to save the location to exist, if they don't we
  1044.         -- have to create them first or an error will occur.
  1045.         TeleportData.AdminData[playerID]                = TeleportData.AdminData[playerID] or {}
  1046.         TeleportData.AdminData[playerID].SavedLocations = TeleportData.AdminData[playerID].SavedLocations or {}
  1047.  
  1048.         -- Set some variables that we'll use to check if there is already a
  1049.         -- location saved near the current position or with the same name.
  1050.         local locationFound             = false
  1051.         local locationFoundNearby       = false
  1052.         local locationName              = nil
  1053.         local positionCoordinates       = player.transform.position
  1054.         local locationCoordinates       = new( UnityEngine.Vector3._type, nil )
  1055.         local locationCoordinatesString = nil
  1056.  
  1057.         -- Loop through all the saved locations for the player to check if a
  1058.         -- location with the same name or near that position already exists.
  1059.         for location, coordinates in pairs( TeleportData.AdminData[playerID].SavedLocations ) do
  1060.             locationName          = location
  1061.             locationCoordinates.x = coordinates.x
  1062.             locationCoordinates.y = coordinates.y
  1063.             locationCoordinates.z = coordinates.z
  1064.  
  1065.             -- Check if the player already has a location with the same name.
  1066.             if args[0] == locationName then
  1067.                 -- A location with this name already exists.
  1068.                 locationFound = true
  1069.  
  1070.                 -- Exit the loop.
  1071.                 break
  1072.             end
  1073.  
  1074.             -- Check if the player already has a location nearby this position
  1075.             -- with a different name.
  1076.             if UnityEngine.Vector3.Distance( positionCoordinates, locationCoordinates ) < self.Config.AdminTP.LocationRadius then
  1077.                 -- A location was found near the current position.
  1078.                 locationFound = true
  1079.  
  1080.                 -- Exit the loop.
  1081.                 break
  1082.             end
  1083.         end
  1084.  
  1085.         -- If the location can't be created because a location with the same
  1086.         -- name or near the current position already exist we'll setup a string
  1087.         -- with the coordinates of that location to show to the player.
  1088.         if locationFound or locationFoundNearby then
  1089.             locationCoordinatesString = math.floor( locationCoordinates.x ) .. " " .. math.floor( locationCoordinates.y ) .. " " .. math.floor( locationCoordinates.z )
  1090.         end
  1091.  
  1092.         -- Determine the next step depending on the existance of the location.
  1093.         if not locationFound and not locationFoundNearby then
  1094.             -- No saved locations found near this position or with the same
  1095.             -- name, so this position can be saved with the supplied name.
  1096.  
  1097.             -- Set the data and save it.
  1098.             TeleportData.AdminData[playerID].SavedLocations[args[0]] = { x = positionCoordinates.x, y = positionCoordinates.y, z = positionCoordinates.z }
  1099.             self:SaveData()
  1100.  
  1101.             -- Show a message to the player.
  1102.             self:SendMessage( player, self.Config.Messages.AdminTPLocationSave )
  1103.         elseif locationFound and not locationFoundNearby then
  1104.             -- A saved location was found with the same name, send a message to
  1105.             -- the player with the coordinates of the location.
  1106.             self:SendMessage( player, self:Parse( self.Config.Messages.LocationExists, { location = locationCoordinatesString } ) )
  1107.         elseif not locationFound and locationFoundNearby then
  1108.             -- A saved location was found near the current position, send a
  1109.             -- message to the player with the name of the location.
  1110.             self:SendMessage( player, self:Parse( self.Config.Messages.LocationExistsNearby, { name = locationName } ) )
  1111.         end
  1112.     else
  1113.         -- No arguments or an invalid amount of arguments were supplied, send a
  1114.         -- message to the player with the available command possibilities.
  1115.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTPSave )
  1116.     end
  1117. end
  1118.  
  1119. -- ----------------------------------------------------------------------------
  1120. -- PLUGIN:cmdRemoveTeleportLocation( player, cmd, args )          Admin Command
  1121. -- ----------------------------------------------------------------------------
  1122. -- In-game '/tpremove' command that allows a server admin to remove a saved
  1123. -- location.
  1124. -- ----------------------------------------------------------------------------
  1125. function PLUGIN:cmdRemoveTeleportLocation( player, cmd, args )
  1126.      -- Check if the player is allowed to run the command.
  1127.     if not self:IsAllowed( player ) then return end
  1128.  
  1129.     -- Grab the player his/her SteamID.
  1130.     local playerID = rust.UserIDFromPlayer( player )
  1131.  
  1132.     -- Determine what the player is trying to do depending on the amount of
  1133.     -- arguments that the player has supplied.
  1134.     if args.Length == 1 then
  1135.         -- The player supplied one argument, assuming that the player is
  1136.         -- attempting to remove the specified location from his/her saved
  1137.         -- locations list.
  1138.        
  1139.         -- Check if there is data saved for the player, after that check if the
  1140.         -- data contains any saved locations for the player.
  1141.         if TeleportData.AdminData[playerID] then
  1142.             if self:Count( TeleportData.AdminData[playerID].SavedLocations ) > 0 then
  1143.                 -- The player has one or more save locations available, check
  1144.                 -- if the location that the player specified is a saved
  1145.                 -- location.
  1146.  
  1147.                 -- Set some variables to store the location in when we find it.
  1148.                 local locationFound       = false
  1149.  
  1150.                 -- Loop through all the saved locations for the player and
  1151.                 -- check for a match against the entered location.
  1152.                 for location, coordinates in pairs( TeleportData.AdminData[playerID].SavedLocations ) do
  1153.                     if args[0] == location then
  1154.                         -- We found a match for the entered location.
  1155.                         locationFound       = true
  1156.  
  1157.                         -- Exit the loop.
  1158.                         break
  1159.                     end
  1160.                 end
  1161.  
  1162.                 -- Check if we found a match while comparing the specified
  1163.                 -- location to the list of saved locations.    
  1164.                 if locationFound then
  1165.                     -- We have found a location with the specified name so we
  1166.                     -- can now remove this from the DataTable and save it.
  1167.                     TeleportData.AdminData[playerID].SavedLocations[args[0]] = nil
  1168.                     self:SaveData()
  1169.  
  1170.                     -- Show a message to the player.
  1171.                     self:SendMessage( player, self:Parse( self.Config.Messages.AdminTPLocationRemove, { location = args[0] } ) )
  1172.  
  1173.                 else
  1174.                     -- We haven't found a location with the specified name,
  1175.                     -- send a message to the player.
  1176.                     self:SendMessage( player, self.Config.Messages.LocationNotFound )
  1177.                 end
  1178.  
  1179.                 return
  1180.             end
  1181.         end
  1182.  
  1183.         -- The player has no saved locations available, show a message to the
  1184.         -- player.
  1185.         self:SendMessage( player, self.Config.Messages.AdminLocationListEmpty )
  1186.     else
  1187.         -- No arguments or an invalid amount of arguments were supplied, send a
  1188.         -- message to the player with the available command possibilities.
  1189.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTPRemove )
  1190.     end
  1191. end
  1192.  
  1193. -- ----------------------------------------------------------------------------
  1194. -- PLUGIN:cmdTeleportBack( player, cmd, args )                    Admin Command
  1195. -- ----------------------------------------------------------------------------
  1196. -- In-game '/tpb' command that allows a server admin to teleport back to his
  1197. -- previous location after teleporting.
  1198. -- ----------------------------------------------------------------------------
  1199. function PLUGIN:cmdTeleportBack( player, cmd, args )
  1200.      -- Check if the player is allowed to run the command.
  1201.     if not self:IsAllowed( player ) then return end
  1202.  
  1203.     -- Grab the player his/her SteamID.
  1204.     local playerID = rust.UserIDFromPlayer( player )
  1205.  
  1206.     -- Determine what the player is trying to do depending on the amount of
  1207.     -- arguments that the player has supplied.
  1208.     if args.Length == 0 then
  1209.         -- The player supplied no arguments, assuming that the player is
  1210.         -- attempting to teleport back to his previous location.
  1211.        
  1212.         -- Check if there is data saved for the player, after that check if the
  1213.         -- data contains a previous location for the player.
  1214.         if TeleportData.AdminData[playerID] then
  1215.             if TeleportData.AdminData[playerID].PreviousLocation then
  1216.                 -- A previous location was found, teleport the player back to
  1217.                 -- that
  1218.                 -- position.
  1219.                 self:TeleportToPosition( player, TeleportData.AdminData[playerID].PreviousLocation.x, TeleportData.AdminData[playerID].PreviousLocation.y, TeleportData.AdminData[playerID].PreviousLocation.z )
  1220.  
  1221.                 -- Remove the saved location from the DataTable and save it.
  1222.                 TeleportData.AdminData[playerID].PreviousLocation = nil
  1223.                 self:SaveData()
  1224.  
  1225.                 -- Show a message to the player.
  1226.                 self:SendMessage( player, self.Config.Messages.AdminTPBack )
  1227.             end
  1228.         end
  1229.  
  1230.         -- There is no previously saved position available, show a message to
  1231.         -- the player.
  1232.         self:SendMessage( player, self.Config.Messages.NoPreviousLocationSaved )
  1233.     else
  1234.         -- An invalid amount of arguments was supplied, send a message to the
  1235.         -- player with the available command possibilities.
  1236.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTPB )
  1237.     end
  1238. end
  1239.  
  1240. -- ----------------------------------------------------------------------------
  1241. -- PLUGIN:cmdSetHome( player, cmd, args )
  1242. -- ----------------------------------------------------------------------------
  1243. -- In-game '/sethome' command that allows any player to save his/her current
  1244. -- position as a home that can be used to teleport back to.
  1245. -- ----------------------------------------------------------------------------
  1246. function PLUGIN:cmdSetHome( player, cmd, args )
  1247.     -- Check if the Home module is enabled.
  1248.     if not self.Config.Settings.HomesEnabled then return end
  1249.  
  1250.     -- Check if the player is allowed to use the command.
  1251.     canTeleport, err = self:CanPlayerTeleport( player )
  1252.     if not canTeleport then
  1253.         -- The player isn't allowed to teleport right now, send him a message
  1254.         -- from the plugin that is blocking the teleport and cancel the
  1255.         -- teleport process.
  1256.         self:SendMessage( player, err )
  1257.  
  1258.         return
  1259.     end
  1260.  
  1261.     -- Grab the player his/her SteamID.
  1262.     local playerID = rust.UserIDFromPlayer( player )
  1263.  
  1264.     -- Determine what the player is trying to do depending on the amount of
  1265.     -- arguments that the player has supplied.
  1266.     if args.Length == 1 then
  1267.         -- The player supplied one arguments, assuming that the player is
  1268.         -- attempting to save his/her current position as a home location.
  1269.        
  1270.         -- Check if the tables to save the location to exist, if they don't we
  1271.         -- have to create them first or an error will occur.
  1272.         TeleportData.HomeData[playerID]               = TeleportData.HomeData[playerID] or {}
  1273.         TeleportData.HomeData[playerID].HomeLocations = TeleportData.HomeData[playerID].HomeLocations or {}
  1274.  
  1275.         -- Set some variables that we'll use to check if there is already a
  1276.         -- location saved near the current position or with the same name.
  1277.         local locationFound             = false
  1278.         local locationFoundNearby       = false
  1279.         local locationName              = nil
  1280.         local positionCoordinates       = player.transform.position
  1281.         local locationCoordinates       = new( UnityEngine.Vector3._type, nil )
  1282.         local locationCoordinatesString = nil
  1283.  
  1284.         -- Check if the player already has saved home locations before.
  1285.         if self:Count( TeleportData.HomeData[playerID].HomeLocations ) > 0 then
  1286.             -- Check if the amount of homes is limited and if it is then check
  1287.             -- if the amount of saved homes will not go over the limit.
  1288.             if self.Config.Homes.HomesLimit > 0 and self:Count( TeleportData.HomeData[playerID].HomeLocations ) >= self.Config.Homes.HomesLimit then
  1289.                 -- The player has reached the maximum amount of saved homes,
  1290.                 -- show a message to the player.
  1291.                 self:SendMessage( player, self:Parse( self.Config.Messages.HomeMaxLocations, { amount = self.Config.Homes.HomesLimit } ) )
  1292.  
  1293.                 return
  1294.             end
  1295.  
  1296.             -- Loop through all the saved locations for the player to check if
  1297.             -- a location with the same name or near that position already
  1298.             -- exists.
  1299.             for location, coordinates in pairs( TeleportData.HomeData[playerID].HomeLocations ) do
  1300.                 locationName          = location
  1301.                 locationCoordinates.x = coordinates.x
  1302.                 locationCoordinates.y = coordinates.y
  1303.                 locationCoordinates.z = coordinates.z
  1304.  
  1305.                 -- Check if the player already has a location with the same
  1306.                 -- name.
  1307.                 if args[0] == locationName then
  1308.                     -- A location with this name already exists.
  1309.                     locationFound = true
  1310.  
  1311.                     -- Exit the loop.
  1312.                     break
  1313.                 end
  1314.  
  1315.                 -- Check if the player already has a location nearby this
  1316.                 -- position with a different name.
  1317.                 if UnityEngine.Vector3.Distance( positionCoordinates, locationCoordinates ) < self.Config.Homes.LocationRadius then
  1318.                     -- A location was found near the current position.
  1319.                     locationFoundNearby = true
  1320.  
  1321.                     -- Exit the loop.
  1322.                     break
  1323.                 end
  1324.             end
  1325.         end
  1326.  
  1327.         -- If the location can't be created because a location with the same
  1328.         -- name or near the current position already exist we'll setup a string
  1329.         -- with the coordinates of that location to show to the player.
  1330.         if locationFound or locationFoundNearby then
  1331.             locationCoordinatesString = math.floor( locationCoordinates.x ) .. " " .. math.floor( locationCoordinates.y ) .. " " .. math.floor( locationCoordinates.z )
  1332.         end
  1333.  
  1334.         -- Determine the next step depending on the existance of the location.
  1335.         if not locationFound and not locationFoundNearby then
  1336.             -- No saved locations found near this position or with the same
  1337.             -- name, so this position can be saved with the supplied name.
  1338.  
  1339.             -- Check if the player is standing on a foundation if required.
  1340.             if self.Config.Homes.ForceOnTopOfFoundation then
  1341.                 -- Modify the local position, add 2 to the y coordinate in case
  1342.                 -- the terrain (grass) goes through the foundation.
  1343.                 local position       = player.transform.position
  1344.                 position.y = position.y + 2
  1345.  
  1346.                 -- Setup an array to invoke RaycastAll with two Vector3
  1347.                 -- arguments, the position and the direction down and invoke.
  1348.                 local arr   = util.TableToArray( { position , UnityEngine.Vector3.get_down() } )
  1349.                 local hits  = RaycastAll:Invoke( nil, arr )
  1350.  
  1351.                 -- Create a local variable to store the BuildingBlock.
  1352.                 local block = nil
  1353.  
  1354.                 -- Create an iterator to loop through all the Raycast Hits.
  1355.                 local it = hits:GetEnumerator()
  1356.  
  1357.                 -- Iterate through all the Raycast Hits.
  1358.                 while ( it:MoveNext() ) do
  1359.                     -- Check if the hit is a deployed item.
  1360.                     if it.Current.collider:GetComponentInParent( global.BuildingBlock._type ) then
  1361.                         local buildingBlock = it.Current.collider:GetComponentInParent( global.BuildingBlock._type )
  1362.  
  1363.                         if buildingBlock.name:find( "foundation", 1, true ) then
  1364.                             -- The deployed item is a foundation, store it in
  1365.                             -- a variable.
  1366.                             block = buildingBlock
  1367.  
  1368.                             break
  1369.                         else
  1370.                             -- Exit the loop when the first BuildingBlock hit
  1371.                             -- isn't a foundation.
  1372.                             break
  1373.                         end
  1374.                     end
  1375.                 end
  1376.  
  1377.                 -- Check if we have a BuildingBlock for the player.
  1378.                 if not block then
  1379.                     -- The player is not standing on a foundation, send
  1380.                     -- the player a message.
  1381.                     self:SendMessage( player, self.Config.Messages.HomeSaveFoundationOnly )
  1382.  
  1383.                     return
  1384.                 end
  1385.  
  1386.                 -- Check if a player is on top of a door.
  1387.                 if UnityEngine.Vector3.Distance( player.transform.position, block.transform.position ) > 2 then
  1388.                     -- The player is not standing on a foundation, send
  1389.                     -- the player a message.
  1390.                     self:SendMessage( player, self.Config.Messages.HomeSaveFoundationOnly )
  1391.  
  1392.                     return
  1393.                 end
  1394.  
  1395.                 -- Check if the player owns the foundation if required.
  1396.                 if self.Config.Homes.CheckFoundationForOwner then
  1397.                     if playerID ~= self:GetOwner( block ) then
  1398.                         -- The player is not standing on a owned foundation,
  1399.                         -- send the player a message if the foundation is also
  1400.                         -- not owned by a friend if this is enabled in the
  1401.                         -- settings.
  1402.                         if self.Config.Homes.UseFriendsAPI and not FriendsAPI.Object:areFriends( self:GetOwner( block ), playerID ) then
  1403.                             -- The player is not standing on a foundation owned
  1404.                             -- by a friend.
  1405.                             self:SendMessage( player, self.Config.Messages.HomeFoundationNotFriendsOwned )
  1406.  
  1407.                             return
  1408.                         end
  1409.  
  1410.                         if not self.Config.Homes.UseFriendsAPI then
  1411.                             self:SendMessage( player, self.Config.Messages.HomeFoundationNotOwned )
  1412.  
  1413.                             return
  1414.                         end                      
  1415.                     end
  1416.                 end
  1417.  
  1418.             end
  1419.  
  1420.             -- Check the location name for invalid characters.
  1421.             if args[0]:match("%W") then
  1422.                 -- Send the player a message.
  1423.                 self:SendMessage( player, self.Config.Messages.InvalidCharacter )
  1424.  
  1425.                 return
  1426.             end
  1427.  
  1428.             -- Set the data and save it.
  1429.             TeleportData.HomeData[playerID].HomeLocations[args[0]] = { x = positionCoordinates.x, y = positionCoordinates.y, z = positionCoordinates.z }
  1430.             self:SaveData()
  1431.  
  1432.             -- Show a message to the player.
  1433.             self:SendMessage( player, self.Config.Messages.HomeSave )
  1434.         elseif locationFound and not locationFoundNearby then
  1435.             -- A saved location was found with the same name, send a message to
  1436.             -- the player with the coordinates of the location.
  1437.             self:SendMessage( player, self.Config.Messages.HomeExists )
  1438.         elseif not locationFound and locationFoundNearby then
  1439.             -- A saved location was found near the current position, send a
  1440.             -- message to the player with the name of the location.
  1441.             self:SendMessage( player, self:Parse( self.Config.Messages.HomeExistsNearby, { name = locationName } ) )
  1442.         end
  1443.     else
  1444.         -- An invalid amount of arguments was supplied, send a message to the
  1445.         -- player with the available command possibilities.
  1446.         self:SendMessage( player, self.Config.Messages.SyntaxCommandSetHome)
  1447.     end
  1448. end
  1449.  
  1450. -- ----------------------------------------------------------------------------
  1451. -- PLUGIN:cmdRemoveHome( player, cmd, args )
  1452. -- ----------------------------------------------------------------------------
  1453. -- In-game '/removehome' command that allows a player to remove a previously
  1454. -- saved home location.
  1455. -- ----------------------------------------------------------------------------
  1456. function PLUGIN:cmdRemoveHome( player, cmd, args )
  1457.     -- Check if the Home module is enabled.
  1458.     if not self.Config.Settings.HomesEnabled then return end
  1459.  
  1460.     -- Grab the player his/her SteamID.
  1461.     local playerID = rust.UserIDFromPlayer( player )
  1462.  
  1463.     -- Determine what the player is trying to do depending on the amount of
  1464.     -- arguments that the player has supplied.
  1465.     if args.Length == 1 then
  1466.         -- The player supplied one arguments, assuming that the player is
  1467.         -- attempting to save his/her current position as a home location.
  1468.         -- Check if there is data saved for the player, after that check if the
  1469.         -- data contains any saved locations for the player.
  1470.         if TeleportData.HomeData[playerID] then
  1471.             if self:Count( TeleportData.HomeData[playerID].HomeLocations ) > 0 then
  1472.                 -- The player has one or more save locations available, check
  1473.                 -- if the location that the player specified is a saved
  1474.                 -- location.
  1475.  
  1476.                 -- Set some variables to store the location in when we find it.
  1477.                 local locationFound       = false
  1478.  
  1479.                 -- Loop through all the saved locations for the player and
  1480.                 -- check for a match against the entered location.
  1481.                 for location, coordinates in pairs( TeleportData.HomeData[playerID].HomeLocations ) do
  1482.                     if args[0] == location then
  1483.                         -- We found a match for the entered location.
  1484.                         locationFound       = true
  1485.  
  1486.                         -- Exit the loop.
  1487.                         break
  1488.                     end
  1489.                 end
  1490.  
  1491.                 -- Check if we found a match while comparing the specified
  1492.                 -- location to the list of saved locations.    
  1493.                 if locationFound then
  1494.                     -- We have found a location with the specified name so we
  1495.                     -- can now remove this from the DataTable and save it.
  1496.                     TeleportData.HomeData[playerID].HomeLocations[args[0]] = nil
  1497.                     self:SaveData()
  1498.  
  1499.                     -- Show a message to the player.
  1500.                     self:SendMessage( player, self:Parse( self.Config.Messages.HomeRemove, { home = args[0] } ) )
  1501.  
  1502.                 else
  1503.                     -- We haven't found a location with the specified name,
  1504.                     -- send a message to the player.
  1505.                     self:SendMessage( player, self.Config.Messages.HomeNotFound )
  1506.                 end
  1507.  
  1508.                 return
  1509.             end
  1510.         end
  1511.  
  1512.         -- The player has no saved locations available, show a message to the
  1513.         -- player.
  1514.         self:SendMessage( player, self.Config.Messages.HomeListEmpty )
  1515.     else
  1516.         -- An invalid amount of arguments was supplied, send a message to the
  1517.         -- player with the available command possibilities.
  1518.         self:SendMessage( player, self.Config.Messages.SyntaxCommandRemoveHome)
  1519.     end
  1520. end
  1521.  
  1522. -- ----------------------------------------------------------------------------
  1523. -- PLUGIN:cmdTeleportHome( player, cmd, args )
  1524. -- ----------------------------------------------------------------------------
  1525. -- In-game '/home' command that allows a player to a previously saved home
  1526. -- location.
  1527. -- ----------------------------------------------------------------------------
  1528. function PLUGIN:cmdTeleportHome( player, cmd, args )
  1529.     -- Check if the Home module is enabled.
  1530.     if not self.Config.Settings.HomesEnabled then return end
  1531.  
  1532.     -- Check if the player is allowed to use the command.
  1533.     canTeleport, err = self:CanPlayerTeleport( player )
  1534.     if not canTeleport then
  1535.         -- The player isn't allowed to teleport right now, send him a message
  1536.         -- from the plugin that is blocking the teleport and cancel the
  1537.         -- teleport proces.
  1538.         self:SendMessage( player, err )
  1539.  
  1540.         return
  1541.     end
  1542.  
  1543.     -- Grab the player his/her SteamID.
  1544.     local playerID = rust.UserIDFromPlayer( player )
  1545.  
  1546.     -- Determine what the player is trying to do depending on the amount of
  1547.     -- arguments that the player has supplied.
  1548.     if args.Length == 1 then
  1549.         -- The player supplied one argument, assuming that the player is
  1550.         -- attempting to teleport himself/herself to a saved home location.
  1551.  
  1552.         -- Check if there is data saved for the player, after that check if the
  1553.         -- data contains any saved locations for the player.
  1554.         if TeleportData.HomeData[playerID] then
  1555.             if self:Count( TeleportData.HomeData[playerID].HomeLocations ) > 0 then
  1556.                 -- The player has one or more save locations available, check
  1557.                 -- if the location that the player specified is a saved
  1558.                 -- location.
  1559.  
  1560.                 -- Setup variables with todays date and the current timestamp.
  1561.                 local timestamp   = time.GetUnixTimestamp()
  1562.                 local currentDate = tostring( time.GetCurrentTime():ToString("d") )
  1563.  
  1564.                 -- Check if there is saved teleport data available for the
  1565.                 -- player.
  1566.                 if TeleportData.HomeData[playerID].Teleports then
  1567.                     if TeleportData.HomeData[playerID].Teleports.date ~= currentDate then
  1568.                         TeleportData.HomeData[playerID].Teleports = nil
  1569.                     end
  1570.                 end
  1571.  
  1572.                 -- Grab the user his/her teleport data.
  1573.                 TeleportData.HomeData[playerID].Teleports = TeleportData.HomeData[playerID].Teleports or {}
  1574.                 TeleportData.HomeData[playerID].Teleports.amount = TeleportData.HomeData[playerID].Teleports.amount or 0
  1575.                 TeleportData.HomeData[playerID].Teleports.date = currentDate
  1576.                 TeleportData.HomeData[playerID].Teleports.timestamp = TeleportData.HomeData[playerID].Teleports.timestamp or 0
  1577.  
  1578.                 -- Check if the cooldown option is enabled and if it is make
  1579.                 -- sure that the cooldown time has passed.
  1580.                 if self.Config.Homes.Cooldown > 0 and ( timestamp - TeleportData.HomeData[playerID].Teleports.timestamp ) < self.Config.Homes.Cooldown then
  1581.                     -- Get the remaining time.
  1582.                     local remainingTime = self:ParseRemainingTime( self.Config.Homes.Cooldown - ( timestamp - TeleportData.HomeData[playerID].Teleports.timestamp ) )
  1583.                     -- Teleport is on cooldown, show a message to the player.
  1584.                     self:SendMessage( player, self:Parse( self.Config.Messages.HomeTPCooldown, { time = remainingTime } ) )
  1585.  
  1586.                     return
  1587.                 end
  1588.  
  1589.                 -- Check if the teleports daily limit is enabled and make sure
  1590.                 -- that the player has not yet reached the limit.
  1591.                 if self.Config.Homes.DailyLimit > 0 and TeleportData.HomeData[playerID].Teleports.amount >= self.Config.Homes.DailyLimit then
  1592.                     -- The player has reached the limit, show a message to the
  1593.                     -- player.
  1594.                     self:SendMessage( player, self:Parse( self.Config.Messages.HomeTPLimitReached, { limit = self.Config.Homes.DailyLimit } ) )
  1595.  
  1596.                     return
  1597.                 end
  1598.  
  1599.                 -- Check if the player already has a teleport pending.
  1600.                 if TeleportTimers[playerID] then
  1601.                     -- Send a message to the player.
  1602.                     self:SendMessage( player, self.Config.Messages.TeleportPending )
  1603.  
  1604.                     return
  1605.                 end
  1606.  
  1607.                 -- Set some variables to store the location in when we find it.
  1608.                 local locationFound       = false
  1609.                 local locationCoordinates = nil
  1610.  
  1611.                 -- Loop through all the saved locations for the player and
  1612.                 -- check for a match against the entered location.
  1613.                 for location, coordinates in pairs( TeleportData.HomeData[playerID].HomeLocations ) do
  1614.                     if args[0] == location then
  1615.                         -- We found a match for the entered location.
  1616.                         locationFound       = true
  1617.                         locationCoordinates = coordinates
  1618.  
  1619.                         -- Exit the loop.
  1620.                         break
  1621.                     end
  1622.                 end
  1623.  
  1624.                 -- Check if we found a match while comparing the specified
  1625.                 -- location to the list of saved locations.    
  1626.                 if locationFound then
  1627.  
  1628.                     -- Location was found and no limits were reached so we ca
  1629.                     -- teleport the player to his home after a short delay.
  1630.                     TeleportTimers[playerID]              = {}
  1631.                     TeleportTimers[playerID].originPlayer = player
  1632.                     TeleportTimers[playerID].timer        = timer.Once ( self.Config.Homes.Countdown,
  1633.                         function()
  1634.                             -- Teleport the player to his home location.
  1635.                             self:TeleportToPosition( player, locationCoordinates.x, locationCoordinates.y + 1, locationCoordinates.z )
  1636.                            
  1637.                             -- Modify the teleport amount and last teleport
  1638.                             -- timestamp.
  1639.                             TeleportData.HomeData[playerID].Teleports.amount = TeleportData.HomeData[playerID].Teleports.amount + 1
  1640.                             TeleportData.HomeData[playerID].Teleports.timestamp = timestamp
  1641.                             self:SaveData()
  1642.  
  1643.                             -- Show a message to the player.
  1644.                             self:SendMessage( player, self:Parse( self.Config.Messages.HomeTP, { home = args[0] } ) )
  1645.  
  1646.                             -- Remove the pending timer info.
  1647.                             TeleportTimers[playerID] = nil
  1648.                         end )
  1649.  
  1650.                     -- Send a message to the player.
  1651.                     self:SendMessage( player, self:Parse( self.Config.Messages.HomeTPStarted, { home = args[0], countdown = self.Config.Homes.Countdown } ) )
  1652.  
  1653.                     return
  1654.                 else
  1655.                     -- Couldn't find a home location with the specified name.
  1656.                     self:SendMessage( player, self.Config.Messages.HomeNotFound )
  1657.  
  1658.                     return
  1659.                 end
  1660.             end
  1661.         end
  1662.  
  1663.         -- The player has no saved locations available, show a message to
  1664.         -- him/her.
  1665.         self:SendMessage( player, self.Config.Messages.HomeListEmpty )
  1666.     else
  1667.         -- An invalid amount of arguments were supplied, send a message to the
  1668.         -- player with the available command possibilities.
  1669.         self:SendMessage( player, self.Config.Messages.SyntaxCommandHome )
  1670.     end
  1671. end
  1672.  
  1673. -- ----------------------------------------------------------------------------
  1674. -- PLUGIN:cmdListHomes( player, cmd, args )
  1675. -- ----------------------------------------------------------------------------
  1676. -- In-game '/listhomes' command that allows a player to look at his saved home
  1677. -- locations.
  1678. -- ----------------------------------------------------------------------------
  1679. function PLUGIN:cmdListHomes( player, cmd, args )
  1680.     -- Check if the Home module is enabled.
  1681.     if not self.Config.Settings.HomesEnabled then return end
  1682.  
  1683.     -- Grab the player his/her SteamID.
  1684.     local playerID = rust.UserIDFromPlayer( player )
  1685.  
  1686.     -- Determine what the player is trying to do depending on the amount of
  1687.     -- arguments that the player has supplied.
  1688.     if args.Length == 0 then
  1689.         -- The player didn't supply any arguments, assuming that the player
  1690.         -- wants to get a list of all his available home locations.
  1691.  
  1692.         -- Check if there is data saved for the player, after that check if the
  1693.         -- data contains any saved locations for the player.
  1694.         if TeleportData.HomeData[playerID] then
  1695.             if self:Count( TeleportData.HomeData[playerID].HomeLocations ) > 0 then
  1696.                 -- The player has one or more save locations available, show a
  1697.                 -- message to the player and show him/her all the available
  1698.                 -- saved locations.
  1699.                 self:SendMessage( player, self.Config.Messages.HomeList )
  1700.  
  1701.                 -- Loop through all the saved locations and print them one by
  1702.                 -- one.
  1703.                 for location, coordinates in pairs( TeleportData.HomeData[playerID].HomeLocations ) do
  1704.                     self:SendMessage( player, location .. ": " .. math.floor( coordinates.x ) .. " " .. math.floor( coordinates.y ) .. " " .. math.floor( coordinates.z ) )
  1705.                 end
  1706.  
  1707.                 return
  1708.             end
  1709.         end
  1710.  
  1711.         -- The player has no saved locations available, show a message to
  1712.         -- him/her.
  1713.         self:SendMessage( player, self.Config.Messages.HomeListEmpty )
  1714.     else
  1715.         -- An invalid amount of arguments were supplied, send a message to the
  1716.         -- player with the available command possibilities.
  1717.         self:SendMessage( player, self.Config.Messages.SyntaxCommandListHomes)
  1718.     end
  1719. end
  1720.  
  1721. -- ----------------------------------------------------------------------------
  1722. -- PLUGIN:cmdTeleportRequest( player, cmd, args )
  1723. -- ----------------------------------------------------------------------------
  1724. -- In-game '/tpr' command that allows a player to send a teleport request to
  1725. -- another online player.
  1726. -- ----------------------------------------------------------------------------
  1727. function PLUGIN:cmdTeleportRequest( player, cmd, args )
  1728.     -- Check if the TPR module is enabled.
  1729.     if not self.Config.Settings.TPREnabled then return end
  1730.  
  1731.     -- Check if the player is allowed to use the command.
  1732.     canTeleport, err = self:CanPlayerTeleport( player )
  1733.     if not canTeleport then
  1734.         -- The player isn't allowed to teleport right now, send him a message
  1735.         -- from the plugin that is blocking the teleport and cancel the
  1736.         -- teleport proces.
  1737.         self:SendMessage( player, err )
  1738.  
  1739.         return
  1740.     end
  1741.  
  1742.     -- Determine what the player is trying to do depending on the amount of
  1743.     -- arguments that the player has supplied.
  1744.     if args.Length == 1 then
  1745.         -- The player supplied one argument, assuming that the player is
  1746.         -- attempting to request a teleport to another player.
  1747.  
  1748.         -- Search for the BasePlayer for the given (partial) name.
  1749.         local targetPlayer = self:FindPlayerByName( args[0] )
  1750.  
  1751.         -- Check if we found the targetted player.
  1752.         if #targetPlayer == 0 then
  1753.             -- The targetted player couldn't be found, send a message to the
  1754.             -- player.
  1755.             self:SendMessage( player, self.Config.Messages.PlayerNotFound )
  1756.  
  1757.             return
  1758.         end
  1759.  
  1760.         -- Check if we found multiple players with that partial name.
  1761.         if #targetPlayer > 1 then
  1762.             -- Multiple players were found, send a message to the player.
  1763.             self:SendMessage( player, self.Config.Messages.MultiplePlayersFound )
  1764.  
  1765.             return
  1766.         else
  1767.             -- Only one player was found, modify the targetPlayer variable
  1768.             -- value.
  1769.             targetPlayer = targetPlayer[1]
  1770.         end
  1771.  
  1772.         -- Check if the targetted player isn't the player that is running the
  1773.         -- command.
  1774.         if player == targetPlayer then
  1775.             -- The player and the targetted player are the same, send a message
  1776.             -- to the player.
  1777.             self:SendMessage( player, self.Config.Messages.CantTeleportToSelf )
  1778.            
  1779.             return
  1780.         end
  1781.  
  1782.         -- Grab the Steam ID of both players.
  1783.         originPlayerID = rust.UserIDFromPlayer( player )
  1784.         targetPlayerID = rust.UserIDFromPlayer( targetPlayer )
  1785.  
  1786.         -- Check if the player has not reached the limit yet and check if it's
  1787.         -- not on cooldown.
  1788.  
  1789.         -- Setup variables with todays date and the current timestamp.
  1790.         local timestamp   = time.GetUnixTimestamp()
  1791.         local currentDate = time.GetCurrentTime():ToString("d")
  1792.  
  1793.         -- Setup the player his/her TPRData table if it doesn't exist yet.
  1794.         TeleportData.TPRData[originPlayerID] = TeleportData.TPRData[originPlayerID] or {}
  1795.  
  1796.         -- Check if there is saved teleport data available for the player.
  1797.         if TeleportData.TPRData[originPlayerID].Teleports then
  1798.             if TeleportData.TPRData[originPlayerID].Teleports.date ~= currentDate then
  1799.                 TeleportData.TPRData[originPlayerID].Teleports = nil
  1800.             end
  1801.         end
  1802.  
  1803.         -- Grab the user his/her teleport data.
  1804.         TeleportData.TPRData[originPlayerID].Teleports = TeleportData.TPRData[originPlayerID].Teleports or {}
  1805.         TeleportData.TPRData[originPlayerID].Teleports.amount = TeleportData.TPRData[originPlayerID].Teleports.amount or 0
  1806.         TeleportData.TPRData[originPlayerID].Teleports.date = currentDate
  1807.         TeleportData.TPRData[originPlayerID].Teleports.timestamp = TeleportData.TPRData[originPlayerID].Teleports.timestamp or 0
  1808.  
  1809.         -- Check if the cooldown option is enabled and if it is make sure
  1810.         -- that the cooldown time has passed.
  1811.         if self.Config.TPR.Cooldown > 0 and ( timestamp - TeleportData.TPRData[originPlayerID].Teleports.timestamp ) < self.Config.TPR.Cooldown then
  1812.             -- Get the remaining time.
  1813.             local remainingTime = self:ParseRemainingTime( self.Config.TPR.Cooldown - ( timestamp - TeleportData.TPRData[originPlayerID].Teleports.timestamp ) )
  1814.             -- Teleport is on cooldown, show a message to the player.
  1815.             self:SendMessage( player, self:Parse( self.Config.Messages.TPRCooldown, { time = remainingTime } ) )
  1816.  
  1817.             return
  1818.         end
  1819.  
  1820.         -- Check if the teleports daily limit is enabled and make sure that
  1821.         -- the player has not yet reached the limit.
  1822.         if self.Config.TPR.DailyLimit > 0 and TeleportData.TPRData[originPlayerID].Teleports.amount >= self.Config.TPR.DailyLimit then
  1823.             -- The player has reached the limit, show a message to the
  1824.             -- player.
  1825.             self:SendMessage( player, self:Parse( self.Config.Messages.TPRLimitReached, { limit = self.Config.TPR.DailyLimit } ) )
  1826.  
  1827.             return
  1828.         end
  1829.  
  1830.         -- Check if the player already has a teleport pending.
  1831.         if TeleportTimers[originPlayerID] then
  1832.             -- Send a message to the player.
  1833.             self:SendMessage( player, self.Config.Messages.TeleportPending )
  1834.  
  1835.             return
  1836.         end
  1837.  
  1838.         -- Check if the player his/her target already has a teleport pending.
  1839.         if TeleportTimers[targetPlayerID] then
  1840.             -- Send a message to the player.
  1841.             self:SendMessage( player, self.Config.Messages.TeleportPendingTarget )
  1842.  
  1843.             return
  1844.         end
  1845.  
  1846.         -- Check if the player or the targetted player already has a request
  1847.         -- pending.
  1848.         if PlayersRequests[originPlayerID] or PlayersRequests[targetPlayerID] then
  1849.             -- Show a message to the players.
  1850.             self:SendMessage( player, self.Config.Messages.PendingRequest )
  1851.             self:SendMessage( originPlayer, self.Config.Messages.PendingRequestTarget )
  1852.  
  1853.             return
  1854.         end
  1855.  
  1856.         -- Start a pending request for both the players.
  1857.         PlayersRequests[originPlayerID] = targetPlayer
  1858.         PlayersRequests[targetPlayerID] = player
  1859.  
  1860.         -- Start the teleport request timer.
  1861.         PendingRequests[targetPlayerID] = timer.Once( self.Config.TPR.RequestDuration,
  1862.             function()
  1863.                 self:RequestTimedOut( player, targetPlayer )
  1864.             end )
  1865.  
  1866.         -- Send a message to both players.
  1867.         self:SendMessage( player, self:Parse( self.Config.Messages.Request, { player = targetPlayer.displayName } ) )
  1868.         self:SendMessage( targetPlayer, self:Parse( self.Config.Messages.RequestTarget, { player = player.displayName } ) )
  1869.     else
  1870.         -- An invalid amount of arguments were supplied, send a message to the
  1871.         -- player with the available command possibilities.
  1872.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTPR)
  1873.     end
  1874. end
  1875.  
  1876. -- ----------------------------------------------------------------------------
  1877. -- PLUGIN:cmdTeleportAccept( player, cmd, args )
  1878. -- ----------------------------------------------------------------------------
  1879. -- In-game '/tpa' command that allows a player to accept a teleport request
  1880. -- from another player.
  1881. -- ----------------------------------------------------------------------------
  1882. function PLUGIN:cmdTeleportAccept( player, cmd, args )
  1883.     -- Check if the TPR module is enabled.
  1884.     if not self.Config.Settings.TPREnabled then return end
  1885.  
  1886.     -- Check if the player is allowed to use the command.
  1887.     canTeleport, err = self:CanPlayerTeleport( player )
  1888.     if not canTeleport then
  1889.         -- The player isn't allowed to teleport right now, send him a message
  1890.         -- from the plugin that is blocking the teleport and cancel the
  1891.         -- teleport proces.
  1892.         self:SendMessage( player, err )
  1893.  
  1894.         return
  1895.     end
  1896.  
  1897.     -- Determine what the player is trying to do depending on the amount of
  1898.     -- arguments that the player has supplied.
  1899.     if args.Length == 0 then
  1900.         -- The player supplied no arguments, assuming that the player is
  1901.         -- attempting to accept a teleport request from another player.
  1902.  
  1903.         -- Grab the player his/her Steam ID.
  1904.         local playerID = rust.UserIDFromPlayer( player )
  1905.  
  1906.         -- Check if the player has a pending teleport request.
  1907.         if PendingRequests[playerID] then
  1908.             -- Grab the other player.
  1909.             local originPlayer   = PlayersRequests[playerID]
  1910.             local originPlayerID = rust.UserIDFromPlayer( originPlayer )
  1911.            
  1912.             -- Setup variables with todays date and the current timestamp.
  1913.             local timestamp   = time.GetUnixTimestamp()
  1914.             local currentDate = time.GetCurrentTime():ToString("d")
  1915.  
  1916.             -- Perform a ceiling check if enabled.
  1917.             if self.Config.TPR.BlockTPAOnCeiling then                
  1918.                 -- Modify the local position, add 2 to the y coordinate.
  1919.                 local position = player.transform.position
  1920.                 position.y = position.y + 1
  1921.  
  1922.                 -- Setup an array to invoke RaycastAll with two Vector3
  1923.                 -- arguments, the position and the direction down and invoke.
  1924.                 local arr   = util.TableToArray( { position , UnityEngine.Vector3.get_down() } )
  1925.                 local hits  = RaycastAll:Invoke( nil, arr )
  1926.  
  1927.                 -- Create a local variable to store the BuildingBlock.
  1928.                 local ceiling = false
  1929.                 local firstHit = true
  1930.  
  1931.                 -- Create an iterator to loop through all the Raycast Hits.
  1932.                 local it = hits:GetEnumerator()
  1933.  
  1934.                 -- Iterate through all the Raycast Hits.
  1935.                  while ( it:MoveNext() ) do
  1936.                     -- Check the distance between the player and the first
  1937.                     -- "hit".
  1938.                     if firstHit then
  1939.                         firstHit = false
  1940.  
  1941.                         -- If the distance is longer than 2m then the
  1942.                         -- player is most likely attempting to stand on a
  1943.                         -- ledge to bug the teleport.
  1944.                         if it.Current.distance > 2 then
  1945.                             ceiling = true
  1946.  
  1947.                             break
  1948.                         end
  1949.                     end
  1950.  
  1951.                     -- Check if the hit is a deployed item.
  1952.                     if it.Current.collider:GetComponentInParent( global.BuildingBlock._type ) then
  1953.                         local buildingBlock = it.Current.collider:GetComponentInParent( global.BuildingBlock._type )
  1954.                        
  1955.                         if buildingBlock.name:find( "floor", 1, true ) then
  1956.                             -- The deployed item is a ceiling, set the boolean
  1957.                             -- `ceiling` to true
  1958.                             ceiling = true
  1959.  
  1960.                             break
  1961.                         end
  1962.  
  1963.                         -- Check the distance between the player and the first
  1964.                         -- "hit".
  1965.                         if firstHit then
  1966.                             firstHit = false
  1967.  
  1968.                             -- If the distance is longer than 2m then the
  1969.                             -- player is most likely attempting to stand on a
  1970.                             -- ledge to bug the teleport.
  1971.                             if it.Current.distance > 2 then
  1972.                                 ceiling = true
  1973.  
  1974.                                 break
  1975.                             end
  1976.  
  1977.                             if not buildingBlock.name:find( "foundation", 1, true ) then
  1978.                                 ceiling = true
  1979.  
  1980.                                 break
  1981.                             end
  1982.                         end
  1983.                     end
  1984.                 end
  1985.  
  1986.                 if ceiling then
  1987.                     -- The player is trying to accept a teleport on top of a
  1988.                     -- ceiling, show the player a message.
  1989.                     self:SendMessage( player, self.Config.Messages.AcceptOnRoof )
  1990.  
  1991.                     return
  1992.                 end
  1993.             end
  1994.            
  1995.             -- The teleport request is valid and can be accepted, send a
  1996.             -- message to both the players.
  1997.             self:SendMessage( originPlayer, self:Parse( self.Config.Messages.Accept, { player = player.displayName, countdown = self.Config.TPR.Countdown } ) )
  1998.             self:SendMessage( player, self:Parse( self.Config.Messages.AcceptTarget, { player = originPlayer.displayName } ) )
  1999.            
  2000.             -- Initiate the teleport timer.
  2001.             TeleportTimers[originPlayerID] = {}
  2002.             TeleportTimers[originPlayerID].originPlayer = originPlayer
  2003.             TeleportTimers[originPlayerID].targetPlayer = player
  2004.             TeleportTimers[originPlayerID].timer = timer.Once( self.Config.TPR.Countdown,
  2005.                 function()
  2006.                     -- Check if the player is allowed to use the command.
  2007.                     canTeleport, err = self:CanPlayerTeleport( originPlayer )
  2008.                     if not canTeleport then
  2009.                         -- The player isn't allowed to teleport right now, send
  2010.                         -- both players a message from the plugin that is
  2011.                         -- blocking the teleport and cancel the teleport.
  2012.                         self:SendMessage( originPlayer, err )
  2013.                         self:SendMessage( player, err )
  2014.  
  2015.                         return
  2016.                     end
  2017.  
  2018.                     -- Check if the target player is allowed to use this
  2019.                     -- command.
  2020.                     canTeleport, err = self:CanPlayerTeleport( player )
  2021.                     if not canTeleport then
  2022.                         -- The player isn't allowed to teleport right now, send
  2023.                         -- both players a message from the plugin that is
  2024.                         -- blocking the teleport and cancel the teleport.
  2025.                         self:SendMessage( originPlayer, err )
  2026.                         self:SendMessage( player, err )
  2027.  
  2028.                         return
  2029.                     end
  2030.  
  2031.                     -- Teleport the player.
  2032.                     local destination = self:CheckPosition( player.transform.position, originPlayer )
  2033.                     self:Teleport( originPlayer, destination )
  2034.  
  2035.                     -- Modify the teleport amount and last teleport timestamp.
  2036.                     TeleportData.TPRData[originPlayerID].Teleports.amount = TeleportData.TPRData[originPlayerID].Teleports.amount + 1
  2037.                     TeleportData.TPRData[originPlayerID].Teleports.timestamp = timestamp
  2038.                     self:SaveData()
  2039.  
  2040.                     -- Send a message to both players.
  2041.                     self:SendMessage( originPlayer, self:Parse( self.Config.Messages.Success, { player = player.displayName } ) )
  2042.                     self:SendMessage( player, self:Parse( self.Config.Messages.SuccessTarget, { player = originPlayer.displayName } ) )
  2043.                    
  2044.                     -- Remove the pending timer info.
  2045.                     TeleportTimers[originPlayerID] = nil
  2046.                 end )
  2047.  
  2048.             -- Destroy the pending request timer.
  2049.             PendingRequests[playerID]:Destroy()
  2050.  
  2051.             -- Remove the table entries
  2052.             PendingRequests[playerID]       = nil
  2053.             PlayersRequests[playerID]       = nil
  2054.             PlayersRequests[originPlayerID] = nil
  2055.         else
  2056.             -- The player doesn't have a pending request, show him/her a
  2057.             -- message.
  2058.             self:SendMessage( player, self.Config.Messages.NoPendingRequest )
  2059.         end
  2060.     else
  2061.         -- An invalid amount of arguments were supplied, send a message to the
  2062.         -- player with the available command possibilities.
  2063.         self:SendMessage( player, self.Config.Messages.SyntaxCommandTPA)
  2064.     end
  2065. end
  2066.  
  2067. -- ----------------------------------------------------------------------------
  2068. -- PLUGIN:cmdWipeHomes( player, cmd, args )
  2069. -- ----------------------------------------------------------------------------
  2070. -- In-game '/wipehomes' command to wipe all the saved homes.
  2071. -- ----------------------------------------------------------------------------
  2072. function PLUGIN:cmdWipeHomes( player, cmd, args )
  2073.     -- Check if the player is allowed to run the command.
  2074.     if not self:IsAllowed( player ) then return end
  2075.  
  2076.     -- Clear the data.
  2077.     TeleportData.HomeData = {}
  2078.  
  2079.     -- Save the data.
  2080.     self:SaveData()
  2081.  
  2082.     -- Send a message to the player.
  2083.     self:SendMessage( player, self.Config.Messages.HomesListWiped )
  2084. end
  2085.  
  2086. -- ----------------------------------------------------------------------------
  2087. -- PLUGIN:SendHelpText( player )
  2088. -- ----------------------------------------------------------------------------
  2089. -- HelpText plugin support for the command /help.
  2090. -- ----------------------------------------------------------------------------
  2091. function PLUGIN:SendHelpText(player)
  2092.     if self.Config.Settings.HomesEnabled or self.Config.Settings.TPREnabled then
  2093.         self:SendMessage( player, "Use \"/tphelp\" to see the available teleport commands." )
  2094.         self:SendMessage( player, "Use \"/tplimits\" to see the teleport limits." )
  2095.     end
  2096. end
  2097.  
  2098. -- ----------------------------------------------------------------------------
  2099. -- PLUGIN:cmdTeleportHelp( player, cmd, args )
  2100. -- ----------------------------------------------------------------------------
  2101. -- In-game '/tphelp' command that allows players to see all the available
  2102. -- teleport commands per module.
  2103. -- ----------------------------------------------------------------------------
  2104. function PLUGIN:cmdTeleportHelp( player, cmd, args )
  2105.     -- Check if there is a player module enabled and if the player is an admin.
  2106.     if not self.Config.Settings.TPREnabled and not self.Config.Settings.HomesEnabled and not self:IsAllowed( player ) then return end
  2107.  
  2108.     -- Determine what the player is trying to do depending on the amount of
  2109.     -- arguments that the player has supplied.
  2110.     if args.Length == 1 then
  2111.         -- The player supplied one argument, assuming the player wants to view
  2112.         -- the help for a specific module.
  2113.  
  2114.         -- Grab the request help module.
  2115.         local TPModule = string.lower( args[0] )
  2116.  
  2117.         -- Check if a valid module was supplied.
  2118.         if self.Config.Messages.TPHelp[TPModule] then
  2119.             -- The player supplied a valid help module, show the list of
  2120.             -- commands.
  2121.             self:SendMessage( player, self.Config.Messages.TPHelp[TPModule] )
  2122.         else
  2123.             -- The player supplied an invalid help module, show an error
  2124.             -- message to the player.
  2125.             self:SendMessage( player, self.Config.Messages.InvalidHelpModule )
  2126.         end
  2127.  
  2128.     else
  2129.         -- The player supplied no arguments or too much arguments, assuming
  2130.         -- that the player is attempting to view the available help modules.
  2131.  
  2132.         -- Send the player the general help message.
  2133.         self:SendMessage( player, self.Config.Messages.TPHelp.General )
  2134.  
  2135.         -- If the player is allowed to access the Admin Teleport System then
  2136.         -- he/she is allowed to see the help commands.
  2137.         if self:IsAllowed( player ) then
  2138.             self:SendMessage( player, "/tphelp AdminTP" )
  2139.         end
  2140.        
  2141.         if self.Config.Settings.HomesEnabled then
  2142.             self:SendMessage( player, "/tphelp Home" )
  2143.         end
  2144.        
  2145.         if self.Config.Settings.TPREnabled then
  2146.             self:SendMessage( player, "/tphelp TPR" )
  2147.         end
  2148.     end
  2149. end
  2150.  
  2151. -- ----------------------------------------------------------------------------
  2152. -- PLUGIN:cmdTeleportLimits( player, cmd, args )
  2153. -- ----------------------------------------------------------------------------
  2154. -- In-game '/tplimits' command that allows players to see all the available
  2155. -- teleport commands per module.
  2156. -- ----------------------------------------------------------------------------
  2157. function PLUGIN:cmdTeleportLimits( player, cmd, args )
  2158.     -- Check if there is a player module enabled.
  2159.     if not self.Config.Settings.TPREnabled and not self.Config.Settings.HomesEnabled then return end
  2160.  
  2161.     -- Determine what the player is trying to do depending on the amount of
  2162.     -- arguments that the player has supplied.
  2163.     if args.Length == 1 then
  2164.         -- The player supplied one argument, assuming the player wants to view
  2165.         -- the help for a specific module.
  2166.  
  2167.         -- Grab the request help module.
  2168.         local TPModule = string.lower( args[0] )
  2169.  
  2170.         -- Check if a valid module was supplied.
  2171.         if self.Config.Messages.TPSettings[TPModule] then
  2172.             -- The player supplied a valid help module, show the list of
  2173.             -- commands.
  2174.             if TPModule == "home" then
  2175.                 for _,message in pairs( self.Config.Messages.TPSettings[TPModule] ) do
  2176.                     self:SendMessage( player, self:Parse( message, { cooldown = self:ParseRemainingTime( self.Config.Homes.Cooldown ), limit = self.Config.Homes.DailyLimit, amount = self.Config.Homes.HomesLimit } ) )
  2177.                 end
  2178.             elseif TPModule == "tpr" then
  2179.                 for _,message in pairs( self.Config.Messages.TPSettings[TPModule] ) do
  2180.                     self:SendMessage( player, self:Parse( message, { cooldown = self:ParseRemainingTime( self.Config.TPR.Cooldown ), limit = self.Config.TPR.DailyLimit } ) )
  2181.                 end
  2182.             end
  2183.         else
  2184.             -- The player supplied an invalid help module, show an error
  2185.             -- message to the player.
  2186.             self:SendMessage( player, self.Config.Messages.InvalidHelpModule )
  2187.         end
  2188.  
  2189.     else
  2190.         -- The player supplied no arguments or too much arguments, assuming
  2191.         -- that the player is attempting to view the available help modules.
  2192.  
  2193.         -- Send the player the general help message.
  2194.         self:SendMessage( player, self.Config.Messages.TPSettings.General )
  2195.        
  2196.         if self.Config.Settings.HomesEnabled then
  2197.             self:SendMessage( player, "/tplimits Home" )
  2198.         end
  2199.        
  2200.         if self.Config.Settings.TPREnabled then
  2201.             self:SendMessage( player, "/tplimits TPR" )
  2202.         end
  2203.     end
  2204. end
  2205.  
  2206. -- ----------------------------------------------------------------------------
  2207. -- PLUGIN:ccmdTeleport( arg )
  2208. -- ----------------------------------------------------------------------------
  2209. -- Console commands to mimic the old Legacy console commands teleport.topos and
  2210. -- teleport.toplayer.
  2211. -- ----------------------------------------------------------------------------
  2212. function PLUGIN:ccmdTeleport( arg )
  2213.     local player = nil
  2214.     local command = arg.cmd.namefull
  2215.  
  2216.     if arg.connection then
  2217.         player = arg.connection.player
  2218.     end
  2219.  
  2220.     if player and not self:IsAllowed( player ) then
  2221.         return true
  2222.     end
  2223.    
  2224.     if command == "teleport.topos" then
  2225.         if not arg.Args or arg.Args.Length ~= 4 then
  2226.             local replyMessage = table.concat( self.Config.Messages.SyntaxConsoleCommandToPos, "\r\n" )
  2227.             arg:ReplyWith( replyMessage )
  2228.         else
  2229.             local playerName = arg:GetString( 0, nil )
  2230.             local x          = arg:GetFloat( 1, -10000 )
  2231.             local y          = arg:GetFloat( 2, -10000 )
  2232.             local z          = arg:GetFloat( 3, -10000 )
  2233.  
  2234.             -- Search for the BasePlayer for the given (partial) name.
  2235.             local targetPlayer = self:FindPlayerByName( playerName )
  2236.  
  2237.             -- Check if we found the targetted player.
  2238.             if #targetPlayer == 0 then
  2239.                 -- The targetted player couldn't be found, send a message to
  2240.                 -- the console.
  2241.                 arg:ReplyWith( self.Config.Messages.PlayerNotFound )
  2242.  
  2243.                 return
  2244.             end
  2245.  
  2246.             -- Check if we found multiple players with that partial name.
  2247.             if #targetPlayer > 1 then
  2248.                 -- Multiple players were found, send a message to the console.
  2249.                 arg:ReplyWith( player, self.Config.Messages.MultiplePlayersFound )
  2250.  
  2251.                 return
  2252.             else
  2253.                 -- Only one player was found, modify the targetPlayer variable
  2254.                 -- value.
  2255.                 targetPlayer = targetPlayer[1]
  2256.             end
  2257.  
  2258.             -- Validate the three coordinates, first check if all three are
  2259.             -- numbers and then check if the coordinates are within the map
  2260.             -- boundaries.
  2261.             if x and y and z then
  2262.                 -- The three supplied axis values are numbers, check if they
  2263.                 -- are within the boundaries of the map.
  2264.                 local boundary = global.TerrainMeta.get_Size().x / 2
  2265.  
  2266.                 if ( x <= boundary and x >= -boundary ) and ( y < 2000 and y >= -100 ) and ( z <= boundary and z >= -boundary ) then
  2267.                     -- A valid location was specified, save the player his/her
  2268.                     -- current location for the '/tpb' command if necessary and
  2269.                     -- initiate a teleport.
  2270.                     if self:IsAllowed( targetPlayer ) then
  2271.                         -- The player is an admin so we need to save his/her
  2272.                         -- current location.
  2273.                         self:SaveLocation( targetPlayer )
  2274.                     end
  2275.  
  2276.                     self:TeleportToPosition( targetPlayer, x, y, z )
  2277.  
  2278.                     -- Send a message to the player
  2279.                     self:SendMessage( targetPlayer, self:Parse( self.Config.Messages.AdminTPConsoleTP, { destination = x .. " " .. y .. " " .. z } ) )
  2280.                     -- Show a message in the console.
  2281.                     arg:ReplyWith( self:Parse( self.Config.Messages.AdminTPTargetCoordinates, { player = targetPlayer.displayName, coordinates = x .. " " .. y .. " " .. z } ) )
  2282.  
  2283.                     return
  2284.                 else
  2285.                     -- One or more axis values are out of bounds, show a
  2286.                     -- message to the player.
  2287.                     arg:ReplyWith( self.Config.Messages.AdminTPOutOfBounds .. "\r\n" .. self.Config.Messages.AdminTPBoundaries )
  2288.                    
  2289.                     return
  2290.                 end
  2291.             else
  2292.                 -- One or more axis values are not a number and are invalid,
  2293.                 -- show a message in the console.
  2294.                 arg:ReplyWith( self.Config.Messages.InvalidCoordinates )
  2295.  
  2296.                 return
  2297.             end
  2298.         end
  2299.     elseif command == "teleport.toplayer" then
  2300.         if not arg.Args or arg.Args.Length ~= 2 then
  2301.             local replyMessage = table.concat( self.Config.Messages.SyntaxConsoleCommandToPlayer, "\r\n" )
  2302.             arg:ReplyWith( replyMessage )
  2303.         else
  2304.             -- Search for the BasePlayer for the given (partial) names.
  2305.             local originPlayer = self:FindPlayerByName( arg:GetString( 0, nil ) )
  2306.             local targetPlayer = self:FindPlayerByName( arg:GetString( 1, nil ) )
  2307.  
  2308.             -- Check if we found both players.
  2309.             if #originPlayer == 0 or #targetPlayer == 0 then
  2310.                 -- One or both players couldn't be found, send a message to the
  2311.                 -- console.
  2312.                 arg:ReplyWith( self.Config.Messages.PlayerNotFound )
  2313.  
  2314.                 return
  2315.             end
  2316.  
  2317.             -- Check if we found multiple players with that partial names.
  2318.             if #originPlayer > 1 or #targetPlayer > 1 then
  2319.                 -- Multiple players were found, send a message to the console.
  2320.                 arg:ReplyWith( self.Config.Messages.MultiplePlayersFound )
  2321.  
  2322.                 return
  2323.             else
  2324.                 -- Only one player was found, modify the targetPlayer variable
  2325.                 -- value.
  2326.                 originPlayer = originPlayer[1]
  2327.                 targetPlayer = targetPlayer[1]
  2328.             end
  2329.  
  2330.             -- Check if the origin player is different from the targetted
  2331.             -- player.
  2332.             if originPlayer == targetPlayer then
  2333.                 -- Both players are the same, send a message to the console.
  2334.                 arg:ReplyWith( self.Config.Messages.CantTeleportPlayerToSelf )
  2335.  
  2336.                 return
  2337.             end
  2338.  
  2339.             -- Check if the player is an admin.
  2340.             if self:IsAllowed( originPlayer ) then
  2341.                 -- The player who's being teleported is an admin, save his/her
  2342.                 -- location for the '/tpb' command.
  2343.                 self:SaveLocation( originPlayer )
  2344.             end
  2345.  
  2346.             -- Both players were found and are valid. Initiate a teleport for
  2347.             -- the origin player to the targetted player.
  2348.             self:TeleportToPlayer( originPlayer, targetPlayer )
  2349.  
  2350.             -- Show a message to both the players.
  2351.             self:SendMessage( originPlayer, self:Parse( self.Config.Messages.AdminTPConsoleTPPlayer, { player = targetPlayer.displayName } ) )
  2352.             arg:ReplyWith( self:Parse( self.Config.Messages.AdminTPPlayers, { player = originPlayer.displayName, target = targetPlayer.displayName } ) )
  2353.         end
  2354.     end
  2355.  
  2356.     return
  2357. end
  2358.  
  2359. -- ----------------------------------------------------------------------------
  2360. -- PLUGIN:OnEntityAttacked( entity, hitinfo )
  2361. -- ----------------------------------------------------------------------------
  2362. -- OnEntityAttacked Oxide Hook. This hook is triggered when an entity
  2363. -- (BasePlayer or BaseNPC) is attacked. This hook is used to interrupt
  2364. -- a teleport when a player takes damage.
  2365. -- ----------------------------------------------------------------------------
  2366. function PLUGIN:OnEntityTakeDamage( entity, hitinfo )
  2367.     -- Check if the entity taking damage is a player.
  2368.     if entity:ToPlayer() then
  2369.         -- The entity taking damage is a player, grab his/her Steam ID.
  2370.         local playerID = rust.UserIDFromPlayer( entity )
  2371.  
  2372.         -- Check if the player has a teleport pending.
  2373.         if TeleportTimers[playerID] then
  2374.             -- Send a message to the players or to both players.
  2375.             self:SendMessage( TeleportTimers[playerID].originPlayer, self.Config.Messages.Interrupted )
  2376.  
  2377.             if TeleportTimers[playerID].targetPlayer then
  2378.                 self:SendMessage( TeleportTimers[playerID].targetPlayer, self:Parse( self.Config.Messages.InterruptedTarget, { player = TeleportTimers[playerID].originPlayer.displayName } ) )
  2379.             end
  2380.  
  2381.             -- Destroy the timer.
  2382.             TeleportTimers[playerID].timer:Destroy()
  2383.  
  2384.             -- Remove the table entry.
  2385.             TeleportTimers[playerID] = nil
  2386.         end
  2387.  
  2388.     end
  2389. end
  2390.  
  2391. -- ----------------------------------------------------------------------------
  2392. -- PLUGIN:OnPlayerDisconnected( player )
  2393. -- ----------------------------------------------------------------------------
  2394. -- OnPlayerDisconnected Oxide Hook. This hook is triggered when a player leaves
  2395. -- the server. This hook is used to cancel pending the teleport requests and
  2396. -- pending teleports for the disconnecting player.
  2397. -- ----------------------------------------------------------------------------
  2398. function PLUGIN:OnPlayerDisconnected( player )
  2399.     -- Grab the player his/her Steam ID.
  2400.     local playerID = rust.UserIDFromPlayer( player )
  2401.  
  2402.     -- Check if the player has any pending requests.
  2403.     if PendingRequests[playerID] then
  2404.         -- The player has a pending request, send a message to the player that
  2405.         -- send this request, kill the timer and remove the data.
  2406.  
  2407.         -- Grab the target player and his/her Steam ID.
  2408.         local originPlayer   = PlayersRequests[playerID]
  2409.         local originPlayerID = rust.UserIDFromPlayer( originPlayer )
  2410.  
  2411.         -- Send a message to the
  2412.         self:SendMessage( originPlayer, self.Config.Messages.RequestTargetOff )
  2413.  
  2414.         -- Destroy the timer and remove the table entries.
  2415.         PendingRequests[playerID]:Destroy()
  2416.         PendingRequests[playerID] = nil
  2417.         PlayersRequests[playerID] = nil
  2418.         PlayersRequests[originPlayerID] = nil
  2419.     end
  2420.  
  2421.     -- Check if the player has a teleport in progress.
  2422.     if TeleportTimers[playerID] then
  2423.         -- The player is about to be teleported, cancel the teleport and remove
  2424.         -- the table entry.
  2425.         TeleportTimers[playerID].timer:Destroy()
  2426.         TeleportTimers[playerID] = nil
  2427.     end
  2428. end
  2429.  
  2430. -- ----------------------------------------------------------------------------
  2431. -- PLUGIN:SaveLocation( player )
  2432. -- ----------------------------------------------------------------------------
  2433. -- Save the location of the player, this is used to save the location upon
  2434. -- teleporting an admin to be able to use the ingame command '/tpb'.
  2435. -- ----------------------------------------------------------------------------
  2436. function PLUGIN:SaveLocation( player )
  2437.     -- Get the player's UserID.
  2438.     local playerID = rust.UserIDFromPlayer( player )
  2439.  
  2440.     -- Check if we already have an entry in the saved data for the player.
  2441.     TeleportData.AdminData[playerID] = TeleportData.AdminData[playerID] or {}
  2442.  
  2443.     -- If the player already has a previous location saved we will preserve
  2444.     -- that one, otherwise we will save his current location to file.
  2445.     if ( not TeleportData.AdminData[playerID].PreviousLocation ) then
  2446.         local location = player.transform.position
  2447.         local x = location.x
  2448.         local y = location.y
  2449.         local z = location.z
  2450.  
  2451.         -- Set the data and save it.
  2452.         TeleportData.AdminData[playerID].PreviousLocation = { x = x, y = y, z = z }
  2453.         self:SaveData()
  2454.  
  2455.         -- Send a message to the player.
  2456.        self:SendMessage( player, self.Config.Messages.AdminTPBackSave )
  2457.     end
  2458. end
  2459.  
  2460. -- ----------------------------------------------------------------------------
  2461. -- PLUGIN:RequestTimedOut( player, target )
  2462. -- ----------------------------------------------------------------------------
  2463. -- Sends a message to both players when the teleport request timed out.
  2464. -- ----------------------------------------------------------------------------
  2465. function PLUGIN:RequestTimedOut( player, target )
  2466.     -- Grab the UserIDs for both players.
  2467.     originUserID = rust.UserIDFromPlayer( player )
  2468.     targetUserID = rust.UserIDFromPlayer( target )
  2469.  
  2470.     -- Remove the table entries
  2471.     PlayersRequests[targetUserID] = nil
  2472.     PlayersRequests[originUserID] = nil
  2473.     PendingRequests[targetUserID] = nil
  2474.  
  2475.     -- Send a message to the players.
  2476.     self:SendMessage( player, self:Parse( self.Config.Messages.TimedOut, { player = target.displayName } ) )
  2477.     self:SendMessage( target, self:Parse( self.Config.Messages.TimedOutTarget, { player = player.displayName } ) )
  2478. end
  2479.  
  2480. -- ----------------------------------------------------------------------------
  2481. -- PLUGIN:IsAllowed( player )
  2482. -- ----------------------------------------------------------------------------
  2483. -- Checks if the player is allowed to run an admin (or moderator) only command.
  2484. -- ----------------------------------------------------------------------------
  2485. function PLUGIN:IsAllowed( player )
  2486.     -- Grab the player his AuthLevel and set the required AuthLevel.
  2487.     local playerAuthLevel = player:GetComponent("BaseNetworkable").net.connection.authLevel
  2488.     local requiredAuthLevel = 2
  2489.    
  2490.     -- Check if Moderators are also allowed to use the commands.
  2491.     if self.Config.AdminTP.UseableByModerators then
  2492.         -- Moderators are allowed to run the commands, reduce the required
  2493.         -- AuthLevel to 1.
  2494.         requiredAuthLevel = 1  
  2495.     end
  2496.  
  2497.     -- Compare the AuthLevel with the required AuthLevel, if it's higher or
  2498.     -- equal then the user is allowed to run the command.
  2499.     if playerAuthLevel >= requiredAuthLevel then
  2500.         return true
  2501.     end
  2502.  
  2503.     return false
  2504. end
  2505.  
  2506. -- ----------------------------------------------------------------------------
  2507. -- PLUGIN:ParseRemainingTime( time )
  2508. -- ----------------------------------------------------------------------------
  2509. -- Returns an amount of seconds as a nice time string.
  2510. -- ----------------------------------------------------------------------------
  2511. function PLUGIN:ParseRemainingTime( time )
  2512.     local minutes  = nil
  2513.     local seconds  = nil
  2514.     local timeLeft = nil
  2515.  
  2516.     -- If the amount of seconds is higher than 60 we'll have minutes too, so
  2517.     -- start with grabbing the amount of minutes and then take the remainder as
  2518.     -- the seconds that are left on the timer.
  2519.     if time >= 60 then
  2520.         minutes = math.floor( time / 60 )
  2521.         seconds = time - ( minutes * 60 )
  2522.     else
  2523.         seconds = time
  2524.     end
  2525.  
  2526.     -- Build a nice string with the remaining time.
  2527.     if minutes and seconds > 0 then
  2528.         timeLeft = minutes .. " min " .. seconds .. " sec "
  2529.     elseif minutes and seconds == 0 then
  2530.         timeLeft = minutes .. " min "
  2531.     else    
  2532.         timeLeft = seconds .. " sec "
  2533.     end
  2534.  
  2535.     -- Return the time string.
  2536.     return timeLeft        
  2537. end
  2538.  
  2539. -- ----------------------------------------------------------------------------
  2540. -- PLUGIN:TeleportToPlayer( player, targetPlayer )
  2541. -- ----------------------------------------------------------------------------
  2542. -- Teleports a player to the target player.
  2543. -- ----------------------------------------------------------------------------
  2544. function PLUGIN:TeleportToPlayer( player, targetPlayer )
  2545.     -- Set the destination for the player.
  2546.     local destination = targetPlayer.transform.position
  2547.  
  2548.     -- Teleport the player to the destination.
  2549.     self:Teleport( player, destination )
  2550. end
  2551.  
  2552. -- ----------------------------------------------------------------------------
  2553. -- PLUGIN:TeleportToPosition( player, x, y, z )
  2554. -- ----------------------------------------------------------------------------
  2555. -- Teleports a player to a set of coordinates.
  2556. -- ----------------------------------------------------------------------------
  2557. function PLUGIN:TeleportToPosition( player, x, y, z )
  2558.     -- set the destination for the player.
  2559.     local destination = new( UnityEngine.Vector3._type, nil )
  2560.     destination.x = x
  2561.     destination.y = y
  2562.     destination.z = z
  2563.  
  2564.     -- Teleport the player to the destination.
  2565.     self:Teleport( player, destination )
  2566. end
  2567.  
  2568. -- ----------------------------------------------------------------------------
  2569. -- PLUGIN:Teleport( player, destination )
  2570. -- ----------------------------------------------------------------------------
  2571. -- Teleports a player to a specific location.
  2572. -- ----------------------------------------------------------------------------
  2573. function PLUGIN:Teleport( player, destination )
  2574.     -- Let the player sleep to prevent the player from falling through objects.
  2575.     player:StartSleeping()
  2576.  
  2577.     player.transform.position = destination
  2578.     player:ClientRPCPlayer(nil, player, "ForcePositionTo", destination)
  2579.  
  2580.     player:SetPlayerFlag(global.BasePlayer.PlayerFlags.ReceivingSnapshot, true);
  2581.     player:UpdateNetworkGroup();
  2582.     player:UpdatePlayerCollider(true, false);
  2583.     player:SendNetworkUpdateImmediate(false);
  2584.     player:ClientRPCPlayer(null, player, "StartLoading");
  2585.     player:SendFullSnapshot();
  2586.     player:SetPlayerFlag(global.BasePlayer.PlayerFlags.ReceivingSnapshot, false);
  2587.     player:ClientRPCPlayer(null, player, "FinishLoading" );
  2588. end
  2589.  
  2590. -- ----------------------------------------------------------------------------
  2591. -- PLUGIN:SendMessage( target, message )
  2592. -- ----------------------------------------------------------------------------
  2593. -- Sends a chatmessage to a player.
  2594. -- ----------------------------------------------------------------------------
  2595. function PLUGIN:SendMessage( target, message )
  2596.     -- Check if we have an existing target to send the message to.
  2597.     if not target then return end
  2598.     if not target:IsConnected() then return end
  2599.     if not message then return end
  2600.  
  2601.     -- Check if the message is a table with multiple messages.
  2602.     if type( message ) == "table" then
  2603.         -- The message is a table with multiple messages, send them one by one.
  2604.         for _, message in pairs( message ) do
  2605.             self:SendMessage( target, message )
  2606.         end
  2607.  
  2608.         return
  2609.     end
  2610.  
  2611.     -- "Build" the message to be able to show it correctly.
  2612.     message = UnityEngine.StringExtensions.QuoteSafe( message )
  2613.  
  2614.     -- Send the message to the targetted player.
  2615.     target:SendConsoleCommand( "chat.add \"" .. self.Config.Settings.ChatName .. "\""  .. message );
  2616. end
  2617.  
  2618. -- ----------------------------------------------------------------------------
  2619. -- PLUGIN:Parse( message, values )
  2620. -- ----------------------------------------------------------------------------
  2621. -- Replaces the parameters in a message with the corresponding values.
  2622. -- ----------------------------------------------------------------------------
  2623. function PLUGIN:Parse( message, values )
  2624.     for k, v in pairs( values ) do
  2625.         -- Replace the variable in the message with the specified value.
  2626.         tostring(v):gsub("(%%)", "%%%%")
  2627.         message = message:gsub( "{" .. k .. "}", v)
  2628.     end
  2629.  
  2630.     return message
  2631. end
  2632.  
  2633. -- ----------------------------------------------------------------------------
  2634. -- PLUGIN:Count( tbl )
  2635. -- ----------------------------------------------------------------------------
  2636. -- Counts the elements of a table.
  2637. -- ----------------------------------------------------------------------------
  2638. function PLUGIN:Count( tbl )
  2639.     local count = 0
  2640.  
  2641.     if type( tbl ) == "table" then
  2642.         for _ in pairs( tbl ) do
  2643.             count = count + 1
  2644.         end
  2645.     end
  2646.  
  2647.     return count
  2648. end
  2649.  
  2650. -- ----------------------------------------------------------------------------
  2651. -- PLUGIN:FindPlayerByName( playerName )
  2652. -- ----------------------------------------------------------------------------
  2653. -- Searches the online players for a specific name.
  2654. -- ----------------------------------------------------------------------------
  2655. function PLUGIN:FindPlayerByName( playerName )
  2656.     -- Check if a player name was supplied.
  2657.     if not playerName then return end
  2658.  
  2659.     -- Set the player name to lowercase to be able to search case insensitive.
  2660.     playerName = string.lower( playerName )
  2661.  
  2662.     -- Setup some variables to save the matching BasePlayers with that partial
  2663.     -- name.
  2664.     local matches = {}
  2665.     local itPlayerList = global.BasePlayer.activePlayerList:GetEnumerator()
  2666.    
  2667.     -- Iterate through the online player list and check for a match.
  2668.     while itPlayerList:MoveNext() do
  2669.         -- Get the player his/her display name and set it to lowercase.
  2670.         local displayName = string.lower( itPlayerList.Current.displayName )
  2671.        
  2672.         -- Look for a match.
  2673.         if string.find( displayName, playerName, 1, true ) then
  2674.             -- Match found, add the player to the list.
  2675.             table.insert( matches, itPlayerList.Current )
  2676.         end
  2677.  
  2678.         if string.len( playerName ) == 17 then
  2679.             if string.find( rust.UserIDFromPlayer( itPlayerList.Current ), playerName ) then
  2680.                 -- Match found, add the player to the list.
  2681.                 table.insert( matches, itPlayerList.Current )
  2682.             end
  2683.         end
  2684.     end
  2685.  
  2686.     -- Return all the matching players.
  2687.     return matches
  2688. end
  2689.  
  2690. -- ----------------------------------------------------------------------------
  2691. -- PLUGIN:GetGround( position )
  2692. -- ----------------------------------------------------------------------------
  2693. -- Searches for a valid height for the given position.
  2694. -- ----------------------------------------------------------------------------
  2695. function PLUGIN:GetGround( position )
  2696.     -- Setup a raycast from high up to the ground.
  2697.     local arr  = util.TableToArray( { position, UnityEngine.Vector3.get_down() } )
  2698.     local hits = RaycastAll:Invoke( nil, arr )
  2699.     local nearestDistance = 9999
  2700.     local nearestPoint    = nil
  2701.     local hitsIterator = hits:GetEnumerator()
  2702.  
  2703.     -- Loop through all the hit objects.
  2704.     while hitsIterator:MoveNext() do
  2705.         if hitsIterator.Current.distance < nearestDistance then
  2706.             nearestDistance = hitsIterator.Current.distance
  2707.             nearestPoint = hitsIterator.Current.point
  2708.         end
  2709.     end
  2710.  
  2711.     -- Return the highest point.
  2712.     return nearestPoint
  2713. end
  2714.  
  2715. -- ----------------------------------------------------------------------------
  2716. -- PLUGIN:CheckPosition( position )
  2717. -- ----------------------------------------------------------------------------
  2718. -- Checks and corrects a player's position when teleporting with tpr/tpa so
  2719. -- that the player can't glitch into a wall.
  2720. -- ----------------------------------------------------------------------------
  2721. function PLUGIN:CheckPosition( position, player )
  2722.     -- Setup an OverlapSphere to check for overlapping colliders within a 2m
  2723.     -- radius of the player.
  2724.     local arr = util.TableToArray( { position, 2 } )
  2725.     util.ConvertAndSetOnArray( arr, 1, 2, System.Int32._type )
  2726.     local hits = OverlapSphere:Invoke( nil, arr )
  2727.    
  2728.     -- Setup some variables to use to iterate over the collider hits.
  2729.     local colliderIterator = hits:GetEnumerator()
  2730.     local colliderDistance = 5
  2731.     local colliderPosition = nil
  2732.     local buildingBlock    = nil
  2733.  
  2734.     -- Loop through all the colliders overlapping with the player.
  2735.     while ( colliderIterator:MoveNext() ) do
  2736.         -- Check if the collider is a building block, if this isn't the case
  2737.         -- then we don't have to do anything.
  2738.         if colliderIterator.Current:GetComponentInParent( global.BuildingBlock._type ) then
  2739.             -- Temporarily  store the building block in a variable to work with
  2740.             -- it.
  2741.             local block = colliderIterator.Current:GetComponentInParent( global.BuildingBlock._type )
  2742.  
  2743.             -- The pushback shouldn't trigger on foundations and floors so we
  2744.             -- can exclude these.
  2745.             if not block.name:find( "foundation" ) and not block.name:find( "floor" ) and not block.name:find( "pillar" ) then
  2746.                 -- Check if this is the nearest building block and save the
  2747.                 -- values if this is the case.
  2748.                 if UnityEngine.Vector3.Distance( block.transform.position, position ) < colliderDistance then
  2749.                     buildingBlock    = block
  2750.                     colliderDistance = UnityEngine.Vector3.Distance( block.transform.position, position )
  2751.                     colliderPosition = block.transform.position
  2752.                 end
  2753.             end
  2754.         end
  2755.     end
  2756.    
  2757.     -- If a BuildingBlock was found within the specified radius we need to push
  2758.     -- the player back.
  2759.     if buildingBlock then
  2760.         -- Setup a few required variables to calculate the push-back location.
  2761.         local correctedLocations = {}
  2762.         local blockRotation      = nil
  2763.         local blockRotation      = buildingBlock.transform.rotation.eulerAngles.y
  2764.         local angles             = { 360 - blockRotation, 180 - blockRotation }
  2765.         local r                  = 1.9
  2766.         local location           = nil
  2767.         local locationDistance   = 100
  2768.  
  2769.         -- Calculate the two possible push-back locations.
  2770.         for _, angle in pairs( angles ) do
  2771.             local radians = math.rad( angle )
  2772.             local newX = r * math.cos( radians )
  2773.             local newZ = r * math.sin( radians )
  2774.             local newLoc = new( UnityEngine.Vector3._type, nil )
  2775.  
  2776.             newLoc.x = colliderPosition.x + newX
  2777.             newLoc.y = colliderPosition.y + 0.2
  2778.             newLoc.z = colliderPosition.z + newZ
  2779.  
  2780.             table.insert (correctedLocations, newLoc )
  2781.         end
  2782.  
  2783.         -- Check which position of the calculated positions should be used.
  2784.         for _, newPosition in pairs( correctedLocations ) do
  2785.             if UnityEngine.Vector3.Distance( position, newPosition ) < locationDistance then
  2786.                 location         = newPosition
  2787.                 locationDistance = UnityEngine.Vector3.Distance( position, newPosition )
  2788.             end
  2789.         end
  2790.        
  2791.         -- Return a new location a bit further away from the wall, at the
  2792.         -- same height.
  2793.         if position.y - location.y > 2.5 then
  2794.             location.y = position.y
  2795.         end
  2796.        
  2797.         return location
  2798.     end
  2799.  
  2800.     return position
  2801. end
  2802.  
  2803. -- ----------------------------------------------------------------------------
  2804. -- PLUGIN:GetOwner( buildingBlock )
  2805. -- ----------------------------------------------------------------------------
  2806. -- Checks the owner of a specific building block in the Building Owners plugin
  2807. -- data.
  2808. -- ----------------------------------------------------------------------------
  2809. function PLUGIN:GetOwner( buildingBlock )
  2810.     -- Setup the array to use to invoke the FindBlockData method from the
  2811.     -- BuildingOwners plugin.
  2812.     local arr = util.TableToArray( { buildingBlock } )
  2813.     util.ConvertAndSetOnArray( arr, 0, buildingBlock, UnityEngine.Object._type )
  2814.  
  2815.     -- Get the owner id.
  2816.     local ownerID = plugins.CallHook( "FindBlockData", arr )
  2817.  
  2818.     -- Return the owner id.
  2819.     return ownerID
  2820. end
  2821.  
  2822. -- ----------------------------------------------------------------------------
  2823. -- PLUGIN:CanPlayerTeleport( player )
  2824. -- ----------------------------------------------------------------------------
  2825. -- Function that checks all other plugins if the player is allowed to teleport,
  2826. -- this is required for the Zones plugin by Reneb:
  2827. -- http://forum.rustoxide.com/plugins/r-zones.739/
  2828. -- ----------------------------------------------------------------------------
  2829. function PLUGIN:CanPlayerTeleport( player )
  2830.     local arr = util.TableToArray( { player } )
  2831.     util.ConvertAndSetOnArray( arr, 0, player, UnityEngine.Object._type )
  2832.     local _return = plugins.CallHook( "canTeleport", arr )
  2833.  
  2834.     if not _return then
  2835.         return true
  2836.     end
  2837.  
  2838.     return false, tostring( _return )
  2839. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement