C#:
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.2")]
[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<ulong, PlayerData> playerHomes = new Dictionary<ulong, PlayerData>();
private class PlayerData
{
public Dictionary<string, Vector3> homes = new Dictionary<string, Vector3>();
}
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<ConfigData>();
}
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<Dictionary<ulong, PlayerData>>();
}
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($"<color=#00FF00>Home: {home.Key}, Position: {home.Value}</color>");
}
}
else
{
player.ChatMessage("<color=#FF0000>You have no homes set!</color>");
}
}
[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("<color=#00FF00>SetHome plugin reloaded successfully!</color>");
PrintToConsole("<color=#00FF00>SetHome plugin reloaded successfully!</color>");
}
#endregion
#region Helper Methods
private bool HasBuildingPrivilege(BasePlayer player)
{
List<BuildingPrivlidge> buildingPrivlidges = new List<BuildingPrivlidge>();
Vis.Entities(player.transform.position, 3f, buildingPrivlidges);
foreach (var priv in buildingPrivlidges)
{
if (priv.authorizedPlayers != null && priv.authorizedPlayers.Contains(player.userID))
return true;
}
return false;
}
private bool HasBuildingPrivilegeAt(Vector3 position, BasePlayer player)
{
List<BuildingPrivlidge> buildingPrivlidges = new List<BuildingPrivlidge>();
Vis.Entities(position, 3f, buildingPrivlidges);
foreach (var priv in buildingPrivlidges)
{
if (priv.authorizedPlayers.Contains(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<string, string>
{
["InvalidHomeName"] = "<color=#FF0000>Invalid home name! Use /sethome <name></color>",
["HomeSet"] = "<color=#00FF00>Home '{0}' has been set!</color>",
["HomeNotFound"] = "<color=#FF0000>Home '{0}' not found!</color>",
["HomeDeleted"] = "<color=#00FF00>Home '{0}' has been deleted!</color>",
["MaxHomesReached"] = "<color=#FF0000>You have reached the maximum number of homes ({0})!</color>",
["NoPermission"] = "<color=#FF0000>You do not have permission to use this command!</color>",
["NoBuildingPrivilege"] = "<color=#FF0000>You do not have building privilege here!</color>",
["TeleportDelay"] = "<color=#FFFF00>Teleporting in {0} seconds...</color>",
["TeleportCancelled"] = "<color=#FF0000>Teleportation cancelled! To teleport you can't move!</color>",
["YouCannotTeleport"] = "<color=#FF0000>You cannot teleport to this location!</color>",
["BuildingBlocked"] = "<color=#FF0000>You are building blocked!</color>",
["TeleportedHome"] = "<color=#00FF00>You have been teleported to home '{0}'!</color>"
}, this);
}
#endregion
}
}