using Oxide.Core; using Oxide.Core.Plugins; using Oxide.Core.Configuration; using System.Collections.Generic; using UnityEngine; using System; using System.Linq; namespace Oxide.Plugins { [Info("SetHome", "Kalvi", "1.0.0")] [Description("Allows players to set, teleport to, and delete homes with permission control and configurable limits.")] public class SetHome : RustPlugin { private DynamicConfigFile dataFile = Interface.Oxide.DataFileSystem.GetFile("SetHomeData"); private Dictionary playerHomes = new Dictionary(); private class PlayerData { public Dictionary homes = new Dictionary(); } private class ConfigData { public int DefaultMaxHomes { get; set; } public int VipMaxHomes { get; set; } public int TeleportDelay { get; set; } public float CombatCooldown { get; set; } } private ConfigData configData; #region Initialization protected override void LoadDefaultConfig() { PrintWarning("Loading default configuration..."); configData = new ConfigData { DefaultMaxHomes = 2, VipMaxHomes = 5, TeleportDelay = 5, CombatCooldown = 10f }; SaveConfig(); } protected override void LoadConfig() { base.LoadConfig(); configData = Config.ReadObject(); } protected override void SaveConfig() => Config.WriteObject(configData); private void Init() { LoadConfig(); LoadData(); permission.RegisterPermission("sethome.default", this); permission.RegisterPermission("sethome.vip", this); permission.RegisterPermission("sethome.use", this); permission.RegisterPermission("sethome.admin", this); } private void LoadData() { playerHomes = dataFile.ReadObject>(); } private void SaveData() { dataFile.WriteObject(playerHomes); } #endregion #region Commands [ChatCommand("sethome")] private void SetHomeCommand(BasePlayer player, string command, string[] args) { if (!permission.UserHasPermission(player.UserIDString, "sethome.use")) { player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString)); return; } if (args.Length != 1) { player.ChatMessage(lang.GetMessage("InvalidHomeName", this, player.UserIDString)); return; } if (!HasBuildingPrivilege(player)) { player.ChatMessage(lang.GetMessage("NoBuildingPrivilege", this, player.UserIDString)); return; } var homeName = args[0]; if (!playerHomes.ContainsKey(player.userID)) { playerHomes[player.userID] = new PlayerData(); } var maxHomes = permission.UserHasPermission(player.UserIDString, "sethome.vip") ? configData.VipMaxHomes : configData.DefaultMaxHomes; if (playerHomes[player.userID].homes.Count >= maxHomes) { player.ChatMessage(string.Format(lang.GetMessage("MaxHomesReached", this, player.UserIDString), maxHomes)); return; } playerHomes[player.userID].homes[homeName] = player.transform.position; player.ChatMessage(string.Format(lang.GetMessage("HomeSet", this, player.UserIDString), homeName)); SaveData(); } [ChatCommand("home")] private void HomeCommand(BasePlayer player, string command, string[] args) { if (!permission.UserHasPermission(player.UserIDString, "sethome.use")) { player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString)); return; } if (args.Length != 1) { player.ChatMessage(lang.GetMessage("InvalidHomeName", this, player.UserIDString)); return; } var homeName = args[0]; if (playerHomes.ContainsKey(player.userID) && playerHomes[player.userID].homes.ContainsKey(homeName)) { var homePos = playerHomes[player.userID].homes[homeName]; if (!HasBuildingPrivilegeAt(homePos, player)) { player.ChatMessage(lang.GetMessage("YouCannotTeleport", this, player.UserIDString)); return; } if (player.IsBuildingBlocked()) { player.ChatMessage(lang.GetMessage("BuildingBlocked", this, player.UserIDString)); return; } player.ChatMessage(string.Format(lang.GetMessage("TeleportDelay", this, player.UserIDString), configData.TeleportDelay)); Vector3 originalPosition = player.transform.position; bool isTeleporting = true; timer.Once(configData.TeleportDelay, () => { if (!isTeleporting) return; if (player.IsBuildingBlocked() || IsInCombat(player)) { player.ChatMessage(lang.GetMessage("TeleportCancelled", this, player.UserIDString)); isTeleporting = false; return; } player.Teleport(homePos); player.ChatMessage(string.Format(lang.GetMessage("TeleportedHome", this, player.UserIDString), homeName)); isTeleporting = false; }); timer.Repeat(0.1f, 0, () => { if (isTeleporting && (player.transform.position != originalPosition && (Math.Abs(player.transform.position.x - originalPosition.x) > 0.01f || Math.Abs(player.transform.position.z - originalPosition.z) > 0.01f))) { player.ChatMessage(lang.GetMessage("TeleportCancelled", this, player.UserIDString)); isTeleporting = false; } }); } else { player.ChatMessage(string.Format(lang.GetMessage("HomeNotFound", this, player.UserIDString), homeName)); } } [ChatCommand("delhome")] private void DelHomeCommand(BasePlayer player, string command, string[] args) { if (!permission.UserHasPermission(player.UserIDString, "sethome.use")) { player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString)); return; } if (args.Length != 1) { player.ChatMessage(lang.GetMessage("InvalidHomeName", this, player.UserIDString)); return; } var homeName = args[0]; if (playerHomes.ContainsKey(player.userID) && playerHomes[player.userID].homes.ContainsKey(homeName)) { playerHomes[player.userID].homes.Remove(homeName); player.ChatMessage(string.Format(lang.GetMessage("HomeDeleted", this, player.UserIDString), homeName)); SaveData(); } else { player.ChatMessage(string.Format(lang.GetMessage("HomeNotFound", this, player.UserIDString), homeName)); } } [ChatCommand("listhome")] private void ListHomeCommand(BasePlayer player, string command, string[] args) { if (!permission.UserHasPermission(player.UserIDString, "sethome.use")) { player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString)); return; } if (playerHomes.ContainsKey(player.userID) && playerHomes[player.userID].homes.Count > 0) { foreach (var home in playerHomes[player.userID].homes) { player.ChatMessage($"Home: {home.Key}, Position: {home.Value}"); } } else { player.ChatMessage("You have no homes set!"); } } [ChatCommand("sethome-reload")] private void ReloadCommand(BasePlayer player, string command, string[] args) { if (!permission.UserHasPermission(player.UserIDString, "sethome.admin")) { player.ChatMessage(lang.GetMessage("NoPermission", this, player.UserIDString)); return; } LoadDefaultConfig(); LoadData(); player.ChatMessage("SetHome plugin reloaded successfully!"); PrintToConsole("SetHome plugin reloaded successfully!"); } #endregion #region Helper Methods private bool HasBuildingPrivilege(BasePlayer player) { List buildingPrivlidges = new List(); Vis.Entities(player.transform.position, 3f, buildingPrivlidges); foreach (var priv in buildingPrivlidges) { if (priv.authorizedPlayers.Any(auth => auth.userid == player.userID)) return true; } return false; } private bool HasBuildingPrivilegeAt(Vector3 position, BasePlayer player) { List buildingPrivlidges = new List(); Vis.Entities(position, 3f, buildingPrivlidges); foreach (var priv in buildingPrivlidges) { if (priv.authorizedPlayers.Any(auth => auth.userid == player.userID)) return true; } return false; } private bool IsInCombat(BasePlayer player) { return player.IsWounded(); } #endregion #region Language protected override void LoadDefaultMessages() { lang.RegisterMessages(new Dictionary { ["InvalidHomeName"] = "Invalid home name! Use /sethome ", ["HomeSet"] = "Home '{0}' has been set!", ["HomeNotFound"] = "Home '{0}' not found!", ["HomeDeleted"] = "Home '{0}' has been deleted!", ["MaxHomesReached"] = "You have reached the maximum number of homes ({0})!", ["NoPermission"] = "You do not have permission to use this command!", ["NoBuildingPrivilege"] = "You do not have building privilege here!", ["TeleportDelay"] = "Teleporting in {0} seconds...", ["TeleportCancelled"] = "Teleportation cancelled! To teleport you can't move!", ["YouCannotTeleport"] = "You cannot teleport to this location!", ["BuildingBlocked"] = "You are building blocked!", ["TeleportedHome"] = "You have been teleported to home '{0}'!" }, this); } #endregion } }