C#:
using Oxide.Core;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using ConVar;
using Newtonsoft.Json;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using Rust;
using UnityEngine;
using VLB;
using Color = UnityEngine.Color;
using Physics = UnityEngine.Physics;
using Time = UnityEngine.Time;
namespace Oxide.Plugins {
[Info("Teleportation", "BadMandarin", "1.1.4")]
[Description("Teleportation")]
class Teleportation : RustPlugin {
#region Classes
private class ParentPosition {
public static Vector3 GetOffsetPosition(Transform parent, Vector3 child) {
return parent.InverseTransformPoint(child);
}
public static Vector3 GetFinalPosition(Transform parent, Vector3 offset) {
return parent.TransformPoint(offset);
}
}
if (time.Days == 0) {
if (time.Seconds != 0 && b < maxSubstr) {
if (!string.IsNullOrEmpty(result)) result += " ";
result += $"{Format(time.Seconds, "s", "s", "s")}";
b++;
}
}
break;
}
return result;
}
private static string Format(int units, string form1, string form2, string form3) {
var tmp = units % 10;
if (units >= 5 && units <= 20 || tmp >= 5 && tmp <= 9) return $"{units}{form1}";
if (tmp >= 2 && tmp <= 4) return $"{units}{form2}";
return $"{units}{form3}";
}
private static DateTime Epoch = new DateTime(1970, 1, 1);
public static double GetTimeStamp() {
return DateTime.Now.Subtract(Epoch).TotalSeconds;
}
}
private static class PlayerHelper {
private static bool FindPlayerPredicate(BasePlayer player, string nameOrUserId) {
return player.displayName.IndexOf(nameOrUserId, StringComparison.OrdinalIgnoreCase) != -1 || player.UserIDString == nameOrUserId;
}
public static bool Find(string nameOrUserId, out BasePlayer target) {
nameOrUserId = nameOrUserId.ToLower();
foreach (BasePlayer activePlayer in BasePlayer.activePlayerList) {
if (FindPlayerPredicate(activePlayer, nameOrUserId)) {
target = activePlayer;
return true;
}
}
foreach (BasePlayer sleepingPlayer in BasePlayer.sleepingPlayerList) {
if (FindPlayerPredicate(sleepingPlayer, nameOrUserId)) {
target = sleepingPlayer;
return true;
}
}
target = (BasePlayer) null;
return false;
}
public static bool FindOnlineMultiple(string nameOrUserId, BasePlayer player, out BasePlayer target) {
if (nameOrUserId == string.Empty) {
_plugin.SendMessage(player, "PLAYER.NOT.FOUND");
target = (BasePlayer) null;
return false;
}
List<BasePlayer> activePlayers = new List<BasePlayer>();
nameOrUserId = nameOrUserId.ToLower();
foreach (BasePlayer activePlayer in BasePlayer.activePlayerList) {
if (FindPlayerPredicate(activePlayer, nameOrUserId)) {
activePlayers.Add(activePlayer);
}
}
switch (activePlayers.Count) {
case 0 : _plugin.SendMessage(player, $"PLAYER.NOT.FOUND.PARAM", nameOrUserId);
target = null;
return false;
case 1 : target = activePlayers[0];
return true;
default : var text = "";
foreach (var activePlayer in activePlayers) {
text += $" {activePlayer.displayName},";
}
_plugin.SendMessage(player, "PLAYER.FIND.MULTIPLE");
target = null;
return false;
}
}
public static bool FindOnlineAndOfflineMultiple(string nameOrUserId, BasePlayer player, out BasePlayer target) {
if (nameOrUserId == string.Empty) {
_plugin.SendMessage(player, "PLAYER.NOT.FOUND");
target = (BasePlayer) null;
return false;
}
List<BasePlayer> activePlayers = new List<BasePlayer>();
nameOrUserId = nameOrUserId.ToLower();
foreach (BasePlayer activePlayer in BasePlayer.activePlayerList) {
if (FindPlayerPredicate(activePlayer, nameOrUserId)) {
activePlayers.Add(activePlayer);
}
}
foreach (BasePlayer activePlayer in BasePlayer.sleepingPlayerList) {
if (FindPlayerPredicate(activePlayer, nameOrUserId)) {
activePlayers.Add(activePlayer);
}
}
switch (activePlayers.Count) {
case 0 : _plugin.SendMessage(player, $"PLAYER.NOT.FOUND.PARAM", nameOrUserId);
target = null;
return false;
case 1 : target = activePlayers[0];
return true;
default : var text = "";
foreach (var activePlayer in activePlayers) {
text += $" {activePlayer.displayName},";
}
_plugin.SendMessage(player, "PLAYER.FIND.MULTIPLE");
target = null;
return false;
}
}
public static bool FindOnline(string nameOrUserId, out BasePlayer target) {
if (nameOrUserId == string.Empty) {
target = (BasePlayer) null;
return false;
}
nameOrUserId = nameOrUserId.ToLower();
foreach (BasePlayer activePlayer in BasePlayer.activePlayerList) {
if (FindPlayerPredicate(activePlayer, nameOrUserId)) {
target = activePlayer;
return true;
}
}
target = (BasePlayer) null;
return false;
}
}
public class Request {
public bool IsHome = false;
public SettingMonument.AvailableMonument Monument;
public BasePlayer Target = null;
public BasePlayer Player = null;
public Vector3 Position = Vector3.zero;
public RealTimeSince RequestTimeout = 0;
public bool RequestConfirmed = false;
public Request(BasePlayer player, bool isHome, Vector3 position = default(Vector3), BasePlayer target = null, SettingMonument.AvailableMonument monument = null) {
this.IsHome = isHome;
this.Monument = monument;
this.Target = target;
this.Player = player;
this.Position = position;
}
}
#endregion
#region Variables
[PluginReference]
private Plugin IQChat, ImageLibrary, Friends, Clans;
private const string TeleportImage = "https://i.imgur.com/kTyCOMy.png";
private static Teleportation _plugin;
private const string Layer = "UI.Teleportation";
private const string LayerBlur = "UI.Teleportation.Layer";
private const string LayerNotification = "UI.Teleportation.Notification";
private const string AdminPermission = "teleportation.admin";
private const string EffectPrefab = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";
private readonly int triggerLayer = LayerMask.GetMask("Trigger");
private readonly int groundLayer = LayerMask.GetMask("Terrain", "World");
private readonly int buildingLayer = LayerMask.GetMask("Terrain", "World", "Construction", "Deployed");
private readonly int blockLayer = LayerMask.GetMask("Construction");
private readonly int deployedLayer = LayerMask.GetMask("Deployed");
#endregion
#region OxideHooks
void OnServerInitialized() {
_plugin = this;
PluginData.LoadData();
StartPluginLoad();
}
void OnNewSave(string fileName) {
if (_config.AutoWipe) {
PrintWarning("Wipe detected! wiping data file...");
_data.PlayersData = new Dictionary<ulong, PlayerData>();
PluginData.SaveData();
}
}
void OnServerSave() {
PluginData.SaveData();
}
void Unload() {
PluginData.SaveData();
for (var i = 0; i < MarkerBag.MarkerBags.Count; i++) UnityEngine.Object.Destroy(MarkerBag.MarkerBags[i]);
for (var i = 0; i < TeleportMgr.ManagersList.Count; i++) UnityEngine.Object.Destroy(TeleportMgr.ManagersList[i]);
for (var i = 0; i < _config.SettingsMonument.AvailableMonuments.Count; i++) {
var monument = _config.SettingsMonument.AvailableMonuments[i];
if(monument.CreatedBag != null) monument.CreatedBag.Kill();
}
}
void OnPlayerConnected(BasePlayer player) {
if (player == null) return;
if (player.HasPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot)) {
timer.Once(2f, () => OnPlayerConnected(player));
return;
}
if (!player.IsConnected) return;
player.GetOrAddComponent<TeleportMgr>();
}
object CanRenameBed(BasePlayer player, SleepingBag bed, string bedName) {
if (_config.SettingsMonument.AvailableMonuments.Exists(x => x.CreatedBag != null && x.CreatedBag == bed)) return false;
return null;
}
object OnSleepingBagValidCheck(SleepingBag bag, ulong targetPlayerID, bool ignoreTimers) {
if (_config.SettingsMonument.AvailableMonuments.Exists(x => x.CreatedBag != null && x.CreatedBag == bag)) {
var player = BasePlayer.FindByID(targetPlayerID);
if (player != null && player.IsHostile()) return false;
return true;
}
return null;
}
#endregion
#region Commands
#region ConsoleCommands
[ConsoleCommand("home")]
void ConsoleCmdHome(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
if (arg.HasArgs() == false) return;
ChatCommandHome(player, "", arg.Args);
}
[ConsoleCommand("tpc")]
void ConsoleCmdTpc(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
if (arg.HasArgs() == false) return;
ChatCommandTpc(player, "", arg.Args);
}
[ConsoleCommand("tp")]
void ConsoleCmdTp(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
if (arg.HasArgs() == false) return;
ChatCommandTp(player, "", arg.Args);
}
[ConsoleCommand("tpa")]
void ConsoleCmdTpa(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
if (arg.HasArgs() == false) return;
ChatCommandTpa(player, "", arg.Args);
}
[ConsoleCommand("tpr")]
void ConsoleCmdTpr(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
if (arg.HasArgs() == false) return;
ChatCommandTpr(player, "", arg.Args);
}
[ConsoleCommand("tpm")]
void ConsoleCmdTpm(ConsoleSystem.Arg arg) {
var player = arg.Player();
if (player == null) return;
if (arg.HasArgs() == false) return;
ChatCommandTpMonument(player, "", arg.Args);
}
#endregion
[ChatCommand("atp")]
private void ChatCommandAtp(BasePlayer player, string command, string[] args) {
var data = PluginData.GetForPlayer(player.userID);
if (data == null) return;
data.AutoAccept = !data.AutoAccept;
SendMessage(player, "ATP.MODE", GetMessage(player, data.AutoAccept ? "ENABLED" : "DISABLED"));
}
[ChatCommand("tpc")]
private void ChatCommandTpc(BasePlayer player, string command, string[] args) {
var teleportMgr = TeleportMgr.GetManager(player);
if (teleportMgr == null) return;
if (teleportMgr.Request != null) {
if (teleportMgr.Request.IsHome) {
teleportMgr.CancelTeleport();
SendMessage(player, "HOME.PLAYER.CANCEL");
return;
}
if (teleportMgr.Request.Monument != null) {
teleportMgr.CancelTeleport();
return;
}
if (teleportMgr.Request.Target != null) {
//var objTarget = TeleportMgr.GetManager(teleportMgr.Request.Target);
SendMessage(teleportMgr.Request.Target, "TPR.TARGET.CANCEL", player.displayName);
//objTarget.CancelTeleport();
}
SendMessage(player, "TPR.PLAYER.CANCEL", teleportMgr.Request.Target.displayName);
teleportMgr.CancelTeleport();
return;
}
var pendingRequest = teleportMgr.IncomingRequests.FirstOrDefault();
if (pendingRequest != null) {
if (pendingRequest.Player != null) {
var objTarget = TeleportMgr.GetManager(pendingRequest.Player);
SendMessage(player, "TPR.PLAYER.CANCEL", pendingRequest.Player.displayName);
SendMessage(pendingRequest.Player, "TPR.TARGET.CANCEL", player.displayName);
objTarget.CancelTeleport();
}
//teleportMgr.IncomingRequests.Remove(pendingRequest);
//teleportMgr.CancelTeleport();
return;
}
}
[ChatCommand("tp")]
private void ChatCommandTp(BasePlayer player, string command, string[] args) {
if(player.IsAdmin == false && permission.UserHasPermission(player.UserIDString, AdminPermission) == false) return;
switch (args.Length) {
case 0 : break;
case 1 : string name = args[0];
BasePlayer target = null;
if(!PlayerHelper.FindOnlineAndOfflineMultiple(name, player, out target)) {
return;
}
if (target == null) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "PLAYER.NOT.FOUND");
return;
}
Teleport(player, target);
break;
case 2 : string name1 = args[0];
string name2 = args[1];
BasePlayer target1 = null;
if(!PlayerHelper.FindOnlineAndOfflineMultiple(name1, player, out target1)) {
return;
}
BasePlayer target2 = null;
if(!PlayerHelper.FindOnlineAndOfflineMultiple(name2, player, out target2)) {
return;
}
if (target1 == null || target2 == null) {
SendMessage(player, "PLAYER.NOT.FOUND");
return;
}
Teleport(target1, target2);
break;
case 3 : float x = float.Parse(args[0]);
float y = float.Parse(args[1]);
float z = float.Parse(args[2]);
Teleport(player, x, y, z);
break;
}
}
[ChatCommand("tphome")]
private void ChatCommandTpHome(BasePlayer player, string command, string[] args) {
if(player.IsAdmin == false && permission.UserHasPermission(player.UserIDString, AdminPermission) == false) return;
string name = args[0];
BasePlayer target = null;
PlayerData data = null;
switch (args.Length) {
case 1 : if(!PlayerHelper.FindOnlineAndOfflineMultiple(name, player, out target)) {
return;
}
if (target == null) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "PLAYER.NOT.FOUND");
return;
}
data = PluginData.GetForPlayer(target.userID);
if (data == null) break;
if (data.HomesList.Count < 1) {
SendMessage(player, "TP.HOMELIST.ZERO");
return;
}
string homes = "";
for (var i = data.HomesList.Count - 1; i >= 0; i--) {
var home = data.HomesList[i];
homes += $"{home.HomeName}";
if (i != 0) homes += ", ";
}
SendMessage(player, "TP.HOMELIST.FOUND", homes);
break;
case 2 : if(!PlayerHelper.FindOnlineAndOfflineMultiple(name, player, out target)) {
return;
}
if (target == null) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "PLAYER.NOT.FOUND");
return;
}
data = PluginData.GetForPlayer(target.userID);
if (data == null) break;
if (data.HomesList.Count < 1) {
SendMessage(player, "TP.HOMELIST.ZERO");
return;
}
var playerHome = data.HomesList.Find(x => x.HomeName.Contains(string.Join(" ", args.Skip(1))));
if (playerHome == null) break;
Teleport(player, playerHome.HomePos);
break;
case 3 : break;
}
}
[ConsoleCommand("UI_Teleportation")]
private void ConsoleCommandTeleportation(ConsoleSystem.Arg arg) {
var player = arg?.Connection?.player as BasePlayer;
if (player == null) return;
switch (arg.GetString(0)) {
case "close" : CuiHelper.DestroyUi(player, Layer);
CuiHelper.DestroyUi(player, LayerBlur);
break;
}
}
[ChatCommand("tpa")]
private void ChatCommandTpa(BasePlayer player, string command, string[] args) {
var teleportMgr = TeleportMgr.GetManager(player);
if (teleportMgr == null) return;
if (teleportMgr.HasRequest()) {
SendMessage(player, "TPA.HAVE.REQUEST");
return;
}
var pendingRequest = teleportMgr.IncomingRequests.FirstOrDefault(x => x.RequestConfirmed == false);
if (pendingRequest == null) {
SendMessage(player, "TPA.ZERO.REQUEST");
return;
}
if (pendingRequest.RequestConfirmed) {
SendMessage(player, "TPA.REQUEST.CONFIRMED");
return;
}
var pendingPlayer = pendingRequest.Player;
var pendingTeleportMgr = TeleportMgr.GetManager(pendingPlayer);
if (pendingTeleportMgr == null) return;
if (player.IsWounded() && _config.SettingsResolution.CantTeleportWounded) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "TP.CANCEL.BLOOD.OR.WOUNDED");
return;
}
if (player.metabolism.bleeding.value > _config.SettingsResolution.SettingsBleeding.NeedBleedingAmount && _config.SettingsResolution.SettingsBleeding.CantTeleportBleeding) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "TP.CANCEL.BLOOD.OR.WOUNDED");
return;
}
if (_config.SettingsResolution.CantTeleportMounted && player.isMounted) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "CAN.TP.MOUNTED");
return;
}
if (_config.SettingsResolution.CantTeleportParent && player.HasParent()) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "CAN.TP.PARENT");
return;
}
if (_config.SettingsResolution.CantTeleportWater && player.IsSwimming()) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "CAN.TP.WATER");
return;
}
if (player.IsBuildingBlocked() && _config.SettingsResolution.CantTeleportInBuild) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "TP.CANCEL.BUILD.DONT.AUTH");
return;
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null) {
SendMessageWithoutLang(player, ret);
return;
}
SendMessage(player, "TPA.PLAYER.ACCEPT", pendingPlayer.displayName);
SendMessage(pendingPlayer, "TPA.TARGET.ACCEPT");
CuiHelper.DestroyUi(player, LayerNotification);
//teleportMgr.IncomingRequest = null;
pendingTeleportMgr.AcceptRequest();
}
[ChatCommand("tpr")]
private void ChatCommandTpr(BasePlayer player, string command, string[] args) {
if (GetTeleportTimeTpr(player.userID) <= 0) return;
if (args.Length < 1) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "TPR.HELP");
return;
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null) {
SendMessageWithoutLang(player, ret);
return;
}
var message = CanTeleportPlayer(player);
if (string.IsNullOrEmpty(message) == false) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessageWithoutLang(player, message);
return;
}
var data = PluginData.GetForPlayer(player.userID);
if (data == null) return;
if (data.CooldownTeleport >= GetCurrentTime()) {
SendMessage(player, "TPR.COOLDOWN", TimeHelper.FormatTime(TimeSpan.FromSeconds(data.CooldownTeleport - GetCurrentTime()), language : lang.GetLanguage(player.UserIDString)));
return;
}
BasePlayer target = null;
if(!PlayerHelper.FindOnlineMultiple(string.Join(" ", args), player, out target)) {
return;
}
if (target == null) return;
if (target == player) return;
var teleportMgr = TeleportMgr.GetManager(player);
if (teleportMgr == null) return;
if (teleportMgr.HasRequest()) {
SendMessage(player, "TPR.PLAYER.CANCEL.REQUEST");
return;
}
var targetTeleportMgr = TeleportMgr.GetManager(target);
if (targetTeleportMgr == null) return;
teleportMgr.InitRequest(target.transform.position, false, target);
targetTeleportMgr.IncomingRequests.Add(teleportMgr.Request);
SendMessage(player, "TPR.PLAYER.SEND", target.displayName);
SendMessage(target, "TPR.TARGET.SEND", player.displayName);
var targetData = PluginData.GetForPlayer(target.userID);
if (targetData?.AutoAccept == true && IsFriend(player.userID, target.userID)) {
ChatCommandTpa(target, "", new string[] {
""
}
);
return;
}
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
CursorEnabled = false, RectTransform = {
AnchorMin = "0.5 0", AnchorMax = "0.5 0", OffsetMax = "0 0"
}
, Image = {
Color = GetColor("#FFFFFF", 0.4f)
}
}
, "Hud", LayerNotification);
container.Add(new CuiElement() {
Parent = LayerNotification, Name = LayerNotification + ".Main", Components = {
new CuiRawImageComponent() {
Png = GetImage(TeleportImage)
}
, new CuiRectTransformComponent() {
AnchorMin = $"0 0", AnchorMax = $"1 1", OffsetMin = "-200 81", OffsetMax = "180 117.6"
}
,
}
}
);
container.Add(new CuiPanel() {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "-151 81", OffsetMax = "132 117.6"
}
, Image = {
Color = "0.9686275 0.9215686 0.8823529 0.13529412"
}
}
, LayerNotification);
container.Add(new CuiLabel() {
RectTransform = {
AnchorMin = "0 0", AnchorMax = "1 1", OffsetMin = "-151 81", OffsetMax = "132 117.6"
}
, Text = {
Text = GetMessage(player, "TPR.UI.REQUEST" , player.displayName), Font = "RobotoCondensed-Bold.ttf", Align = TextAnchor.MiddleCenter, FontSize = 16, Color = GetColor("#FFFFFFB2")
}
,
}
, LayerNotification);
container.Add(new CuiButton() {
RectTransform = {
AnchorMin = "0.02 0", AnchorMax = "0 1", OffsetMax = "49 0"
}
, Button = {
Color = "0 0 0 0", Command = "chat.say /tpc"
}
, Text = {
Text = GetMessage(player, "TPR.UI.REQUEST.NO"), Align = TextAnchor.MiddleCenter, Color = GetColor("#D12C2C"), FontSize = 16
}
}
, LayerNotification + ".Main");
container.Add(new CuiButton() {
RectTransform = {
AnchorMin = "0.98 0", AnchorMax = "1 1", OffsetMin = "-49 0"
}
, Button = {
Color = "0 0 0 0", Command = "chat.say /tpa"
}
, Text = {
Text = GetMessage(player, "TPR.UI.REQUEST.YES"), Align = TextAnchor.MiddleCenter, Color = GetColor("#C1FF9B"), FontSize = 16
}
}
, LayerNotification + ".Main");
CuiHelper.AddUi(target, container);
}
[ChatCommand("removehome")]
private void ChatCommandRemoveHome(BasePlayer player, string command, string[] args) {
if (args.Length < 1) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "REMOVE.HOME.HELP");
return;
}
string homeName = string.Join(" ", args);
var data = PluginData.GetForPlayer(player.userID);
var home = data.GetHome(homeName);
if (home == null) {
SendMessage(player, "REMOVE.HOME.NONE");
return;
}
if (home.SleepingBagId != 0) {
var bag = BaseNetworkable.serverEntities.Find(home.SleepingBagId);
if (bag != null) bag.Kill();
}
data.HomesList.Remove(home);
SendMessage(player, "REMOVE.HOME.SUCCESS", homeName);
}
[ChatCommand("homelist")]
private void ChatCommandHomeList(BasePlayer player, string command, string[] args) {
var data = PluginData.GetForPlayer(player.userID);
if (data == null) return;
if (data.HomesList.Count < 1) {
SendMessage(player, "HOMELIST.ZERO");
return;
}
string homes = "";
for (var i = data.HomesList.Count - 1; i >= 0; i--) {
var home = data.HomesList[i];
homes += $"{home.HomeName}";
if (i != 0) homes += ", ";
}
SendMessage(player, "HOMELIST.FOUND", homes);
}
[ChatCommand("sethome")]
private void ChatCommandSetHome(BasePlayer player, string command, string[] args) {
if (GetHomeLimit(player.userID) <= 0) return;
var foundationList = GetFoundation(player.ServerPosition);
if (foundationList == null || foundationList.Count == 0) {
SendMessage(player, "FOUNDATION.NOT.FOUND");
return;
}
var foundation = foundationList?.First();
if (foundation == null) {
SendMessage(player, "FOUNDATION.NOT.FOUND");
return;
}
string err = CheckFoundation(player.userID, player.ServerPosition);
if (err != null) {
SendMessage(player, err);
return;
}
err = CheckInsideBlock(player.ServerPosition);
if (err != null) {
SendMessage(player, err);
return;
}
if (player.GetBuildingPrivilege(player.WorldSpaceBounds()) != null && !player.GetBuildingPrivilege(player.WorldSpaceBounds()).authorizedPlayers.Select(p => p.userid).Contains(player.userID)) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "SETHOME.CANCEL.BUILD");
return;
}
if (args.Length != 1) {
SendMessage(player, "SETHOME.HELP");
return;
}
if (player.IsWounded() && _config.SettingsResolution.CantTeleportWounded || player.metabolism.bleeding.value > _config.SettingsResolution.SettingsBleeding.NeedBleedingAmount && _config.SettingsResolution.SettingsBleeding.CantTeleportBleeding) {
SendMessage(player, "BLOOD.OR.WOUNDED");
return;
}
SetHome(player, args[0]);
}
[ChatCommand("home")]
private void ChatCommandHome(BasePlayer player, string command, string[] args) {
if (args.Length != 1) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.HELP");
return;
}
if (GetTeleportTimeHome(player.userID) <= 0) return;
var data = PluginData.GetForPlayer(player.userID);
var homeName = string.Join(" ", args);
var home = data.GetHome(homeName);
if (home == null) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.NOT.FOUND.OR.REMOVED");
return;
}
var foundationList = GetFoundation(home.HomePos);
if (foundationList == null || foundationList.Count == 0) {
SendMessage(player, "FOUNDATION.NOT.FOUND");
return;
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null) {
SendMessageWithoutLang(player, ret);
return;
}
if (_config.SettingsHome.EnableSleepingBags) {
if (home.SleepingBagId == 0) {
data.HomesList.Remove(home);
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.NOT.FOUND.BAG");
return;
}
var bag = BaseNetworkable.serverEntities.Find(home.SleepingBagId);
if (bag == null) {
data.HomesList.Remove(home);
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.NOT.FOUND.BAG");
return;
}
}
if (data.CooldownHome > GetCurrentTime()) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.COOLDOWN", TimeHelper.FormatTime(TimeSpan.FromSeconds(data.CooldownHome - GetCurrentTime())));
return;
}
var message = CanTeleportPlayer(player);
if (!string.IsNullOrEmpty(message)) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessageWithoutLang(player, message);
return;
}
string err = CheckInsideBlock(home.HomePos);
if (err != null) {
SendMessage(player, "HOME.REMOVED.INSIDE.BLOCK", home.HomeName);
data.HomesList.Remove(home);
return;
}
var teleportMgr = TeleportMgr.GetManager(player);
if (teleportMgr == null) return;
if (teleportMgr.HasRequest()) {
SendMessage(player, "TPR.PLAYER.CANCEL.REQUEST");
return;
}
teleportMgr.InitRequest(home.HomePos, true);
SendMessage(player, "HOME.TELEPORTATION", TimeHelper.FormatTime(TimeSpan.FromSeconds(GetTeleportTimeHome(player.userID)), language : lang.GetLanguage(player.UserIDString)));
}
[ChatCommand("tpm")]
private void ChatCommandTpMonument(BasePlayer player, string command, string[] args) {
if (args.Length < 1) {
SendMessage(player, "TPM.HELP");
return;
}
switch (args[0]) {
case "add" : {
if (player.IsAdmin == false) break;
var closestMonument = FindClosestMonument(player.transform.position);
if (closestMonument == null) {
SendMessage(player, "TPM.ADMIN.CLOSEST.NOT.FOUND");
break;
}
var monumentInfo = _config.SettingsMonument.AvailableMonuments.Find(x => closestMonument.name.Contains(x.ShortPrefabName));
if (monumentInfo != null) {
SendMessage(player, "TPM.ADMIN.EXISTS");
break;
}
Vector3 positionOffset = ParentPosition.GetOffsetPosition(closestMonument.transform, player.transform.position);
string name = GetShortMonumentName(closestMonument.name);
SleepingBag bag = null;
if (_config.SettingsMonument.EnableSleepingBags) {
bag = CreateSleepingBag(null, ParentPosition.GetFinalPosition(closestMonument.transform, positionOffset) - new Vector3(0, 100f, 0), name);
bag.SetPublic(false);
bag.OwnerID = 0;
bag.deployerUserID = 0;
bag.spawnOffset += new Vector3(0, 100f, 0);
bag.unlockTime = Time.realtimeSinceStartup + 30f;
bag.secondsBetweenReuses = 30f;
}
monumentInfo = new SettingMonument.AvailableMonument() {
ShortPrefabName = name, CoolDown = 300f, CoolDownPublic = 30f, TeleportTime = 30f, Name = name, PositionOffset = positionOffset, ShortCutCommand = "", CreatedBag = bag, MonumentInfo = closestMonument,
}
;
_config.SettingsMonument.AvailableMonuments.Add(monumentInfo);
SaveConfig();
SendMessage(player, "TPM.ADMIN.SUCCESS");
break;
}
case "remove" : {
if (player.IsAdmin == false) break;
if (args.Length < 2) break;
string name = string.Join(" ", args.Skip(1));
var monumentInfo = _config.SettingsMonument.AvailableMonuments.Find(x => x.Name == name);
if (monumentInfo == null) {
SendMessage(player, "TPM.ADMIN.REMOVE.NOT.FOUND");
break;
}
_config.SettingsMonument.AvailableMonuments.Remove(monumentInfo);
SaveConfig();
SendMessage(player, "TPM.ADMIN.REMOVE.SUCCESS");
break;
}
case "list" : {
if (_config.SettingsMonument.AvailableMonuments.Count < 1) {
SendMessage(player, "TPM.NO.AVAILABLE.MONUMENTS");
break;
}
string monuments = "";
for (var i = _config.SettingsMonument.AvailableMonuments.Count - 1; i >= 0; i--) {
var availableMonument = _config.SettingsMonument.AvailableMonuments[i];
monuments += $"\n/tpm {availableMonument.Name}" + (string.IsNullOrEmpty(availableMonument.ShortCutCommand) ? "" : $" (/{availableMonument.ShortCutCommand})");
}
SendMessage(player, "TPM.LIST.FOUND", monuments);
break;
}
default : {
if (args.Length < 1) {
SendMessage(player, "TPM.HELP");
break;
}
if (player.IsHostile()) {
SendMessage(player, "TPM.HOSTILE");
break;
}
string name = string.Join(" ", args);
var monumentInfo = _config.SettingsMonument.AvailableMonuments.Find(x => x.Name == name);
if (monumentInfo == null) {
SendMessage(player, "TPM.NOT.FOUND");
break;
}
if (monumentInfo.MonumentInfo == null) {
SendMessage(player, "TPM.NOT.FOUND");
break;
}
var data = PluginData.GetForPlayer(player.userID);
if (data == null) break;
double cooldown = data.GetMonumentCooldown(monumentInfo.Name);
if (cooldown > GetCurrentTime()) {
SendMessage(player, "TPM.COOLDOWN", TimeHelper.FormatTime(TimeSpan.FromSeconds(cooldown - GetCurrentTime())));
break;
}
var teleportMgr = TeleportMgr.GetManager(player);
if (teleportMgr == null) break;
teleportMgr.InitRequest(ParentPosition.GetFinalPosition(monumentInfo.MonumentInfo.transform, monumentInfo.PositionOffset), false, null, monumentInfo);
SendMessage(player, "TPM.TP.SUCCESS", TimeHelper.FormatTime(TimeSpan.FromSeconds(monumentInfo.TeleportTime)));
break;
}
}
}
private MonumentInfo FindClosestMonument(Vector3 position) {
MonumentInfo info = null;
float minDistance = float.MaxValue;
var monuments = TerrainMeta.Path.Monuments;
foreach (var monument in monuments) {
float distance = Vector3.Distance(position, monument.transform.position);
if (distance > minDistance) continue;
minDistance = distance;
info = monument;
}
return info;
}
private MonumentInfo FindMonument(string shortPrefabName) {
return TerrainMeta.Path.Monuments.Find(x => x.name.Contains(shortPrefabName));
}
private string GetShortMonumentName(string fullName) {
var split = fullName.Split('/');
return split[split.Length - 1].Replace(".prefab", string.Empty);
}
#endregion
#region Utils
private string CanTeleportPlayer(BasePlayer player) {
if (player.IsSwimming() && _config.SettingsResolution.CantTeleportSwimming) return GetMessage(player, "CAN.TP.SWIMMING");
if (!player.IsAlive()) return GetMessage(player, "CAN.TP.ALIVE");
if (_config.SettingsResolution.CantTeleportMounted && player.isMounted) return GetMessage(player, "CAN.TP.MOUNTED");
if (_config.SettingsResolution.CantTeleportParent && player.HasParent()) return GetMessage(player, "CAN.TP.PARENT");
if (_config.SettingsResolution.CantTeleportWater && player.IsSwimming()) return GetMessage(player, "CAN.TP.WATER");
if (player.metabolism.radiation_poison.value > _config.SettingsResolution.SettingsRadiation.NeedRadiationAmount && _config.SettingsResolution.SettingsRadiation.CantTeleportRadiation) return GetMessage(player, "CAN.TP.RADIATION");
if (player.metabolism.bleeding.value > _config.SettingsResolution.SettingsBleeding.NeedBleedingAmount && _config.SettingsResolution.SettingsBleeding.CantTeleportBleeding) return GetMessage(player, "CAN.TP.BLEEDING");
if (player.IsWounded() && _config.SettingsResolution.CantTeleportWounded) return GetMessage(player, "CAN.TP.WOUNDED");
if (player.IsWounded() && _config.SettingsResolution.CantTeleportCrawling) return GetMessage(player, "CAN.TP.CRAWLING");
if (player.metabolism.temperature.value < _config.SettingsResolution.SettingsTemperature.MinNeedTemperature && _config.SettingsResolution.SettingsTemperature.CantTeleportTemperature) return GetMessage(player, "CAN.TP.TEMPERATURE");
var privilege = player.GetBuildingPrivilege(player.WorldSpaceBounds());
if (privilege != null && !player.IsBuildingAuthed() && _config.SettingsResolution.CantTeleportInBuild) return GetMessage(player, "CAN.TP.BUILDINGBLOCK");
return "";
}
private static void DrawMarker(BasePlayer player, Vector3 position, string text, int length = 1) {
if (player == null || player.IsNpc) return;
player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, true);
player.SendEntityUpdate();
player.SendConsoleCommand("ddraw.text", length, Color.white, position, text);
player.SendConsoleCommand("camspeed 0");
if (player.Connection.authLevel < 2) player.SetPlayerFlag(BasePlayer.PlayerFlags.IsAdmin, false);
player.SendEntityUpdate();
}
private static double GetCurrentTime() {
return new TimeSpan(DateTime.UtcNow.Ticks).TotalSeconds;
}
private static string GetColor(string hex, float alpha = 1f) {
if (hex.Length != 7) hex = "#FFFFFF";
if (alpha < 0 || alpha > 1f) alpha = 1f;
var color = ColorTranslator.FromHtml(hex);
var r = Convert.ToInt16(color.R) / 255f;
var g = Convert.ToInt16(color.G) / 255f;
var b = Convert.ToInt16(color.B) / 255f;
return $"{r} {g} {b} {alpha}";
}
private void RegisterPermissions() {
if(!permission.PermissionExists(AdminPermission)) permission.RegisterPermission(AdminPermission, this);
foreach (var perm in _config.SettingsHome.CooldownTeleportation) {
if(!permission.PermissionExists(perm.Key)) permission.RegisterPermission(perm.Key, this);
}
foreach (var perm in _config.SettingsHome.CountHome) {
if(!permission.PermissionExists(perm.Key)) permission.RegisterPermission(perm.Key, this);
}
foreach (var perm in _config.SettingsHome.TeleportationTime) {
if(!permission.PermissionExists(perm.Key)) permission.RegisterPermission(perm.Key, this);
}
foreach (var perm in _config.SettingsTeleport.CooldownTeleportation) {
if(!permission.PermissionExists(perm.Key)) permission.RegisterPermission(perm.Key, this);
}
foreach (var perm in _config.SettingsTeleport.TeleportationTime) {
if(!permission.PermissionExists(perm.Key)) permission.RegisterPermission(perm.Key, this);
}
}
private void SetHome(BasePlayer player, string name) {
var userId= player.userID;
var playerPosition = player.GetNetworkPosition();
var playerData = PluginData.GetForPlayer(player.userID);
if (playerData == null) return;
foreach (var home in playerData.HomesList) {
if (home.HomeName == name) {
SendMessage(player, "SETHOME.ALREADY.EXISTS");
return;
}
if (Vector3.Distance(playerPosition, home.HomePos) > 30) continue;
SendMessage(player, "SETHOME.CANCEL.RADIUS");
return;
}
if (GetHomeLimit(userId) == playerData.HomesList.Count) {
SendMessage(player, "SETHOME.CANCEL.MAXHOUSE");
return;
}
SleepingBag sleepingBag = null;
if (_config.SettingsHome.EnableSleepingBags) {
sleepingBag = CreateSleepingBag(player, playerPosition, $"{name}");
//List<BuildingBlock> foundations = new List<BuildingBlock>();
//Vis.Components(sleepingBag.transform.position,.3f, foundations);
var foundation = GetFoundation(sleepingBag.transform.position);
sleepingBag.buildingID = foundation[0].buildingID;
sleepingBag.gameObject.AddComponent<MarkerBag>();
sleepingBag.skinID = 214;
}
playerData.HomesList.Add(new PlayerData.Home(playerPosition, name, sleepingBag?.net.ID ?? 0));
SendMessage(player, "SETHOME.SUCCESS", name);
}
private SleepingBag CreateSleepingBag(BasePlayer player, Vector3 pos, string name) {
SleepingBag sleepingBag = GameManager.server.CreateEntity("assets/prefabs/deployable/sleeping bag/sleepingbag_leather_deployed.prefab", pos, Quaternion.identity) as SleepingBag;
if (sleepingBag == null) return null;
sleepingBag.deployerUserID = player?.userID ?? 0;
sleepingBag.niceName = name;
sleepingBag.OwnerID = player?.userID ?? 0;
sleepingBag.gameObject.AddComponent<DestroyOnGroundMissing>();
sleepingBag.gameObject.AddComponent<GroundWatch>();
sleepingBag.Spawn();
return sleepingBag;
}
private float GetTeleportTimeHome(ulong uid) {
float min = 9999f;
bool set = false;
foreach (var privilege in _config.SettingsHome.TeleportationTime) {
if (permission.UserHasPermission(uid.ToString(), privilege.Key)) {
min = Mathf.Min(min, privilege.Value);
set = true;
}
}
return set ? min : -1f;
}
private float GetTeleportTimeTpr(ulong uid) {
float min = 9999f;
bool set = false;
foreach (var privilege in _config.SettingsTeleport.TeleportationTime) {
if (permission.UserHasPermission(uid.ToString(), privilege.Key)) {
min = Mathf.Min(min, privilege.Value);
set = true;
}
}
return set ? min : -1f;
}
private float GetTeleportCooldownHome(ulong uid) {
float min = 9999f;
bool set = false;
foreach (var privilege in _config.SettingsHome.CooldownTeleportation) {
if (permission.UserHasPermission(uid.ToString(), privilege.Key)) {
min = Mathf.Min(min, privilege.Value);
set = true;
}
}
return set ? min : -1f;
}
private float GetTeleportCooldownTpr(ulong uid) {
float min = 9999f;
bool set = false;
foreach (var privilege in _config.SettingsTeleport.CooldownTeleportation) {
if (permission.UserHasPermission(uid.ToString(), privilege.Key)) {
min = Mathf.Min(min, privilege.Value);
set = true;
}
}
return set ? min : -1f;
}
private int GetHomeLimit(ulong uid) {
int max = -1;
foreach (var privilege in _config.SettingsHome.CountHome) if (permission.UserHasPermission(uid.ToString(), privilege.Key)) max = Mathf.Max(max, privilege.Value);
return max;
}
private string CheckInsideBlock(Vector3 targetLocation) {
List<BuildingBlock> blocks = Facepunch.Pool.GetList<BuildingBlock>();
Vis.Entities(targetLocation + new Vector3(0, 0.25f), 0.1f, blocks, blockLayer);
bool inside = blocks.Count > 0;
Facepunch.Pool.FreeList(ref blocks);
return inside ? "FOUNDATION.HOME.INSIDE.BLOCK" : null;
}
private string CheckFoundation(ulong userID, Vector3 position) {
if (CheckInsideBattery(position) != null) return "FOUNDATION.NOT.FOUND";
if (UnderneathFoundation(position)) return "FOUNDATION.NOT.FOUND";
#if DEBUG
Puts($"CheckFoundation() looking for foundation at {position}");
#endif
var entities = GetFoundation(position);
entities.RemoveAll(x => !x.IsValid() || x.IsDestroyed);
if (entities.Count == 0) return "FOUNDATION.NOT.FOUND";
if (!_config.SettingsHome.CheckFoundationForOwner) return null;
for (var i = 0; i < entities.Count; i++) {
if (IsFriend(userID, entities[i].OwnerID)) return null;
}
return "FOUNDATION.NOT.OWNED";
}
private List<BuildingBlock> GetFoundation(Vector3 position) {
RaycastHit hit;
var entities = new List<BuildingBlock>();
if (Physics.Raycast(position + new Vector3(0f, 0.2f, 0f), Vector3.down, out hit, 3f, blockLayer) && hit.GetEntity().IsValid()) {
var entity = hit.GetEntity();
if (_config.SettingsHome.AvailableFoundations.Contains(entity.PrefabName)) {
#if DEBUG
Puts($" GetFoundation() found {entity.PrefabName} at {entity.transform.position}");
#endif
entities.Add(entity as BuildingBlock);
}
}
else {
#if DEBUG
Puts(" GetFoundation() none found.");
#endif
}
return entities;
}
private bool UnderneathFoundation(Vector3 position) {
RaycastHit hit;
if (Physics.Raycast(position + new Vector3(0f, 3f, 0f), Vector3.down, out hit, 5f, Layers.Mask.Construction, QueryTriggerInteraction.Ignore)) {
var block = hit.GetEntity() as BuildingBlock;
if (block.IsValid() && (block.prefabID == 72949757 || block.prefabID == 3234260181)) {
return hit.point.y > position.y;
}
}
return false;
}
bool IsFriend(ulong playerid, ulong ownerid) {
if (playerid == ownerid) return true;
if (_config.UseFriends && Friends != null && Friends.IsLoaded) {
var fr = Friends?.CallHook("AreFriends", playerid, ownerid);
if (fr != null && fr is bool && (bool)fr) {
return true;
}
}
if (_config.UseClans && Clans != null && Clans.IsLoaded) {
string playerclan = (string)Clans?.CallHook("GetClanOf", playerid);
string ownerclan = (string)Clans?.CallHook("GetClanOf", ownerid);
if (playerclan != null && ownerclan != null && playerclan == ownerclan) {
return true;
}
}
if (_config.UseTeams) {
RelationshipManager.PlayerTeam playerTeam;
if (RelationshipManager.ServerInstance.playerToTeam.TryGetValue(playerid, out playerTeam)) {
if (playerTeam.members.Contains(ownerid)) {
return true;
}
}
}
return false;
}
private string CheckInsideBattery(Vector3 targetLocation) {
var batteries = new List<ElectricBattery>();
Vis.Entities(targetLocation, 0.35f, batteries, deployedLayer);
return batteries.Count > 0 ? "TPTargetInsideBlock" : null;
}
private void Teleport(BasePlayer player, BasePlayer target) {
//if (target.GetComponentInParent<Component>() != null ||
// target.GetComponentInParent<HotAirBalloon>() != null || target.GetComponentInParent<Spawnable>() != null || (target.GetParentEntity() != null && target.GetParentEntity().name.Contains("cave")) || (target.GetParentEntity() != null && target.GetParentEntity().name.Contains("junkpile_water")) || (target.GetParentEntity() != null && target.GetParentEntity().name.Contains("cargo")))
if(target.HasParent()) {
player.PauseFlyHackDetection(10f);
player.SetParent(target.GetParentEntity());
player.SendNetworkUpdateImmediate();
}
Teleport(player, target.transform.position, target);
}
private void Teleport(BasePlayer player, float x, float y, float z) => Teleport(player, new Vector3(x, y, z));
private void Teleport(BasePlayer player, Vector3 position, BasePlayer target = null) {
if (player.IsDead() && player.IsConnected) {
player.RespawnAt(position, Quaternion.identity);
return;
}
if (target == null) {
if (player.HasParent()) {
player.SetParent(null);
player.SendNetworkUpdate();
}
}
else {
if (target.HasParent()) {
player.SetParent(target.GetParentEntity());
player.SendNetworkUpdate();
}
}
var
// ... [Code preview truncated due to length. Full source in attached file] ...