C#:
using Oxide.Core;
using System.Collections.Generic;
using System.Linq;
using System;
using System.Reflection;
using Facepunch;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using UnityEngine;
using Oxide.Core.Libraries;
using System.IO;
namespace Oxide.Plugins
{
[Info("Teleportation", "OxideBro", "1.1.1")]
class Teleportation : RustPlugin
{
[PluginReference]
Plugin Clans;
[PluginReference]
Plugin Friends;
readonly MethodInfo entitySnapshot = typeof(BasePlayer).GetMethod("SendEntitySnapshot", BindingFlags.Instance | BindingFlags.NonPublic);
Dictionary<ulong, Vector3> lastPositions = new Dictionary<ulong, Vector3>();
Dictionary<BasePlayer, int> spectatingPlayers = new Dictionary<BasePlayer, int>();
bool IsClanMember(ulong playerID, ulong targetID)
{
return (bool)(Clans?.Call("HasFriend", playerID, targetID) ?? false);
}
bool IsFriends(ulong playerID, ulong friendId)
{
return (bool)(Friends?.Call("AreFriends", playerID, friendId) ?? false);
}
#region CLASSES
class TP
{
public BasePlayer Player;
public BasePlayer Player2;
public Vector3 pos;
public int seconds;
public TP(BasePlayer player, Vector3 pos, int seconds, BasePlayer player2 = null)
{
this.Player = player;
this.pos = pos;
this.seconds = seconds;
this.Player2 = player2;
}
}
#endregion
#region CONFIGURATION
const string TPADMIN = "teleportation.admin";
int homelimitDefault;
Dictionary<string, int> homelimitPerms;
int tpkdDefault;
Dictionary<string, int> tpkdPerms;
int tpkdhomeDefault;
Dictionary<string, int> tpkdhomePerms;
int teleportSecsDefault;
int resetPendingTime;
bool restrictCupboard;
bool enabledTPR;
bool homecupboard;
bool adminsLogs;
bool foundationOwner;
bool foundationOwnerFC;
bool restrictTPRCupboard;
bool foundationEx;
bool wipedData;
bool createSleepingBug;
string EffectPrefab1;
string EffectPrefab;
static DynamicConfigFile config;
Dictionary<string, int> teleportSecsPerms;
void WipeData()
{
Interface.Oxide.DataFileSystem.WriteObject("Teleportation/Homes", new Dictionary<string, FileInfo>());
Interface.Oxide.DataFileSystem.WriteObject("Teleportation/AdminTpSave", new Dictionary<string, FileInfo>());
SaveData();
Interface.Oxide.ReloadPlugin(Title);
}
protected override void LoadDefaultConfig()
{
GetVariable(Config, "Запрещать отправлять запрос на телепортацию в зоне действия чужого шкафа", out homecupboard, true);
GetVariable(Config, "Звук уведомления при получение запроса на телепорт (пустое поле = звук отключен)", out EffectPrefab1, "assets/prefabs/locks/keypad/effects/lock.code.unlock.prefab");
GetVariable(Config, "Звук предупреждения (пустое поле = звук отключен)", out EffectPrefab, "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab");
GetVariable(Config, "Разрешать сохранять местоположение только на фундаменте", out foundationEx, true);
GetVariable(Config, "Создавать объект при сохранении местоположения в виде Sleeping Bag", out createSleepingBug, true);
GetVariable(Config, "Автоматический вайп данных при генерации новой карты", out wipedData, true);
GetVariable(Config, "Запрещать принимать запрос на телепортацию в зоне действия чужого шкафа", out restrictCupboard, true);
GetVariable(Config, "Запрещать сохранять местоположение если игрок не является владельцем фундамента", out foundationOwner, true);
GetVariable(Config, "Разрешать сохранять местоположение если игрок является другом или соклановцем владельца фундамента ", out foundationOwnerFC, true);
GetVariable(Config, "Логировать использование команд для администраторов", out adminsLogs, true);
GetVariable(Config, "Разрешить команду TPR игрокам (false = /tpr не будет работать)", out enabledTPR, true);
GetVariable(Config, "Запрещать отправлять запрос на телепортацию в зоне действия чужого шкафа", out restrictTPRCupboard, true);
GetVariable(Config, "Время ответа на запрос телепортации (в секундах)", out resetPendingTime, 15);
GetVariable(Config, "Ограничение на количество сохранённых местоположений", out homelimitDefault, 3);
Config["Ограничение на количество сохранённых местоположений с привилегией"] =
homelimitPerms =
GetConfig("Ограничение на количество сохранённых местоположений с привилегией",
new Dictionary<string, object>() { { "teleportation.vip", 5 } }).ToDictionary(p => p.Key, p => Convert.ToInt32(p.Value));
PermissionService.RegisterPermissions(this, homelimitPerms.Keys.ToList());
GetVariable(Config, "Длительность задержки перед телепортацией (в секундах)", out teleportSecsDefault, 15);
Config["Длительность задержки перед телепортацией с привилегией (в секундах)"] =
teleportSecsPerms =
GetConfig("Длительность задержки перед телепортацией с привилегией (в секундах)",
new Dictionary<string, object>() { { "teleportation.vip", 10 } }).ToDictionary(p => p.Key, p => Convert.ToInt32(p.Value));
PermissionService.RegisterPermissions(this, teleportSecsPerms.Keys.ToList());
GetVariable(Config, "Длительность перезарядки телепорта (в секундах)", out tpkdDefault, 300);
Config["Длительность перезарядки телепорта с привилегией (в секундах)"] =
tpkdPerms =
GetConfig("Длительность перезарядки телепорта с привилегией (в секундах)",
new Dictionary<string, object>() { { "teleportation.vip", 150 } }).ToDictionary(p => p.Key, p => Convert.ToInt32(p.Value));
PermissionService.RegisterPermissions(this, tpkdPerms.Keys.ToList());
GetVariable(Config, "Длительность перезарядки телепорта домой (в секундах)", out tpkdhomeDefault, 300);
Config["Длительность перезарядки телепорта домой с привилегией (в секундах)"] =
tpkdhomePerms =
GetConfig("Длительность перезарядки телепорта домой с привилегией (в секундах)",
new Dictionary<string, object>() { { "teleportation.vip", 150 } }).ToDictionary(p => p.Key, p => Convert.ToInt32(p.Value));
PermissionService.RegisterPermissions(this, tpkdhomePerms.Keys.ToList());
SaveConfig();
}
T GetConfig<T>(string name, T defaultValue)
=> Config[name] == null ? defaultValue : (T)Convert.ChangeType(Config[name], typeof(T));
public static void GetVariable<T>(DynamicConfigFile config, string name, out T value, T defaultValue)
{
config[name] = value = config[name] == null ? defaultValue : (T)Convert.ChangeType(config[name], typeof(T));
}
#endregion
#region Permissions
public static class PermissionService
{
public static Permission permission = Interface.GetMod().GetLibrary<Permission>();
public static bool HasPermission(ulong uid, string permissionName)
{
return !string.IsNullOrEmpty(permissionName) && permission.UserHasPermission(uid.ToString(), permissionName);
}
public static void RegisterPermissions(Plugin owner, List<string> permissions)
{
if (owner == null) throw new ArgumentNullException("owner");
if (permissions == null) throw new ArgumentNullException("commands");
foreach (var permissionName in permissions.Where(permissionName => !permission.PermissionExists(permissionName)))
{
permission.RegisterPermission(permissionName, owner);
}
}
}
#endregion
#region FIELDS
public BasePlayer FindBasePlayer(string nameOrUserId)
{
nameOrUserId = nameOrUserId.ToLower();
foreach (var player in BasePlayer.activePlayerList)
{
if (player.displayName.ToLower().Contains(nameOrUserId) || player.UserIDString == nameOrUserId)
return player;
}
foreach (var player in BasePlayer.sleepingPlayerList)
{
if (player.displayName.ToLower().Contains(nameOrUserId) || player.UserIDString == nameOrUserId)
return player;
}
return default(BasePlayer);
}
private FieldInfo SleepingBagUnlockTimeField = typeof(SleepingBag).GetField("unlockTime",
BindingFlags.Instance | BindingFlags.NonPublic);
private readonly int groundLayer = LayerMask.GetMask("Terrain", "World");
private readonly int buildingMask = Rust.Layers.Server.Buildings;
Dictionary<ulong, Dictionary<string, Vector3>> homes;
Dictionary<ulong, Dictionary<string, Vector3>> tpsave;
Dictionary<ulong, int> cooldownsTP = new Dictionary<ulong, int>();
Dictionary<ulong, int> cooldownsHOME = new Dictionary<ulong, int>();
List<TP> tpQueue = new List<TP>();
List<TP> pendings = new List<TP>();
List<ulong> sethomeBlock = new List<ulong>();
#endregion
#region COMMANDS
[ChatCommand("sethome")]
void cmdChatSetHome(BasePlayer player, string command, string[] args)
{
var uid = player.userID;
var pos = player.GetNetworkPosition();
var foundation = GetFoundation(pos);
var bulds = GetBuldings(pos);
if (foundationEx)
{
if (foundation == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["foundationmissing"]);
return;
}
}
if (!foundationEx)
{
if (bulds == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["foundationmissing"]);
return;
}
}
if (args.Length != 1)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["sethomeArgsError"]);
return;
}
if (player.IsWounded() || player.metabolism.bleeding.value > 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["woundedAction"]);
return;
}
if (sethomeBlock.Contains(player.userID))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["sethomeBlock"]);
return;
}
if (foundationOwnerFC && foundationOwner)
{
if (!foundationEx && bulds.OwnerID != uid)
{
if (!IsFriends(bulds.OwnerID, player.userID) && !IsClanMember(bulds.OwnerID, player.userID))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["foundationownerFC"]);
return;
}
}
if (foundationEx && foundation.OwnerID != uid)
{
if (!IsFriends(foundation.OwnerID, player.userID) && !IsClanMember(foundation.OwnerID, player.userID))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["foundationownerFC"]);
return;
}
}
}
if (foundationOwner)
{
if (foundationEx && foundation.OwnerID != uid && foundationOwnerFC == (!IsFriends(foundation.OwnerID, player.userID) && !IsClanMember(foundation.OwnerID, player.userID)))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["foundationowner"]);
return;
}
if (!foundationEx && bulds.OwnerID != uid && foundationOwnerFC == (!IsFriends(bulds.OwnerID, player.userID) && !IsClanMember(bulds.OwnerID, player.userID)))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["foundationowner"]);
return;
}
}
var name = args[0];
SetHome(player, name);
}
[ChatCommand("removehome")]
void cmdChatRemoveHome(BasePlayer player, string command, string[] args)
{
if (args.Length != 1)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["removehomeArgsError"]);
return;
}
if (!homes.ContainsKey(player.userID))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homesmissing"]);
return;
}
var name = args[0];
var playerHomes = homes[player.userID];
if (!playerHomes.ContainsKey(name))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homenotexist"]);
return;
}
foreach (var sleepingBag in SleepingBag.FindForPlayer(player.userID, true))
{
if (Vector3.Distance(sleepingBag.transform.position, playerHomes[name]) < 1)
{
sleepingBag.Kill();
break;
}
}
Effect.server.Run(EffectPrefab1, player, 0, Vector3.zero, Vector3.forward);
playerHomes.Remove(name);
SendReply(player, Messages["removehomesuccess"], name);
}
[ConsoleCommand("home")]
void cmdHome(ConsoleSystem.Arg arg)
{
var player = arg.Player();
if (player == null) return;
if (arg.Args == null || arg.Args.Length < 1) return;
cmdChatHome(player, "", new[] { arg.Args[0] });
}
[ChatCommand("homelist")]
private void cmdHomeList(BasePlayer player, string command, string[] args)
{
if (!homes.ContainsKey(player.userID) || homes[player.userID].Count == 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homesmissing"]);
return;
}
var playerHomes = homes[player.userID];
var time = (GetHomeLimit(player.userID) - playerHomes.Count);
var homelist = playerHomes.Select(x => GetSleepingBag(x.Key, x.Value) != null ? $"{x.Key} {x.Value}" : $"Дом: {x.Key} {x.Value}");
foreach (var home in playerHomes.ToList())
{
if (createSleepingBug)
{
if (!GetSleepingBag(home.Key, home.Value))
playerHomes.Remove(home.Key);
}
}
SendReply(player, Messages["homeslist"], time, string.Join("\n", homelist.ToArray()));
}
[ChatCommand("home")]
void cmdChatHome(BasePlayer player, string command, string[] args)
{
if (args.Length != 1)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homeArgsError"]);
return;
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null)
{
SendReply(player, ret);
return;
}
if (player.IsWounded() || player.metabolism.bleeding.value > 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["woundedAction"]);
return;
}
int seconds;
if (cooldownsHOME.TryGetValue(player.userID, out seconds) && seconds > 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, string.Format(Messages["tpkd"], TimeToString(seconds)));
return;
}
if (homecupboard)
{
var privilege = player.GetBuildingPrivilege(player.WorldSpaceBounds());
if (privilege != null && !player.IsBuildingAuthed())
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["tphomecupboard"]);
return;
}
}
if (!homes.ContainsKey(player.userID))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homesmissing"]);
return;
}
var name = args[0];
var playerHomes = homes[player.userID];
if (!playerHomes.ContainsKey(name))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homenotexist"]);
return;
}
var time = GetTeleportTime(player.userID);
var pos = playerHomes[name];
SleepingBag bag = GetSleepingBag(name, pos);
if (createSleepingBug)
{
if (bag == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["sleepingbagmissing"]);
playerHomes.Remove(name);
return;
}
}
if (!createSleepingBug)
{
var bulds = GetBuldings(pos);
if (bulds == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["foundationmissingR"]);
playerHomes.Remove(name);
return;
}
}
if (player.metabolism.temperature.value < 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["coldplayer"]);
return;
}
var lastTp = tpQueue.Find(p => p.Player == player);
if (lastTp != null)
{
tpQueue.Remove(lastTp);
}
tpQueue.Add(new TP(player, pos, time));
Effect.server.Run(EffectPrefab1, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, String.Format(Messages["homequeue"], name, TimeToString(time)));
SaveData();
}
[ChatCommand("tpr")]
void cmdChatTpr(BasePlayer player, string command, string[] args)
{
if (!enabledTPR) return;
if (args.Length != 1)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["tprArgsError"]);
return;
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null)
{
SendReply(player, ret);
return;
}
if (player.IsWounded() || player.metabolism.bleeding.value > 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["woundedAction"]);
return;
}
if (restrictTPRCupboard)
{
var privilege = player.GetBuildingPrivilege(player.WorldSpaceBounds());
if (privilege != null && !player.IsBuildingAuthed())
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["tpcupboard"]);
return;
}
}
var name = args[0];
var target = FindBasePlayer(name);
if (target == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["playermissing"]);
return;
}
if (target == player)
{
SendReply(player, Messages["playerisyou"]);
return;
}
int seconds = 0;
if (restrictCupboard && tpQueue.Any(p => p.Player == player && p.Player2 != null) &&
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);
SendReply(player, Messages["tpcupboard"]);
return;
}
if (cooldownsTP.TryGetValue(player.userID, out seconds) && seconds > 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, string.Format(Messages["tpkd"], TimeToString(seconds)));
return;
}
if (player.metabolism.temperature.value < 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["coldplayer"]);
return;
}
if (tpQueue.Any(p => p.Player == player) ||
pendings.Any(p => p.Player2 == player))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["tpError"]);
return;
}
SendReply(player, string.Format(Messages["tprrequestsuccess"], target.displayName));
SendReply(target, string.Format(Messages["tprpending"], player.displayName));
Effect.server.Run(EffectPrefab1, target, 0, Vector3.zero, Vector3.forward);
pendings.Add(new TP(target, Vector3.zero, 15, player));
}
[ChatCommand("tpa")]
void cmdChatTpa(BasePlayer player, string command, string[] args)
{
if (!enabledTPR) return;
var tp = pendings.Find(p => p.Player == player);
BasePlayer pendingPlayer = tp?.Player2;
if (pendingPlayer == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["tpanotexist"]);
return;
}
if (player.metabolism.temperature.value < 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["coldplayer"]);
return;
}
if (player.IsWounded() || player.metabolism.bleeding.value > 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["woundedAction"]);
return;
}
if (restrictCupboard && 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);
SendReply(player, Messages["tpacupboard"]); return;
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null)
{
SendReply(player, ret);
return;
}
var time = GetTeleportTime(pendingPlayer.userID);
pendings.Remove(tp);
var lastTp = tpQueue.Find(p => p.Player == pendingPlayer);
if (lastTp != null)
{
tpQueue.Remove(lastTp);
}
tpQueue.Add(new TP(pendingPlayer, player.GetNetworkPosition(), time, player));
Effect.server.Run(EffectPrefab1, player, 0, Vector3.zero, Vector3.forward);
SendReply(pendingPlayer, string.Format(Messages["tpqueue"], player.displayName, TimeToString(time)));
SendReply(player, String.Format(Messages["tpasuccess"], pendingPlayer.displayName, TimeToString(time)));
}
[ChatCommand("tpc")]
void cmdChatTpc(BasePlayer player, string command, string[] args)
{
var tp = pendings.Find(p => p.Player == player);
BasePlayer target = tp?.Player2;
if (target != null)
{
pendings.Remove(tp);
SendReply(player, Messages["tpc"]);
SendReply(target, string.Format(Messages["tpctarget"], player.displayName));
return;
}
if (player.IsWounded() || player.metabolism.bleeding.value > 0)
{
SendReply(player, Messages["woundedAction"]);
return;
}
if (player.metabolism.temperature.value < 0)
{
SendReply(player, Messages["coldplayer"]);
return;
}
foreach (var pend in pendings)
{
if (pend.Player2 == player)
{
SendReply(player, Messages["tpc"]);
SendReply(pend.Player, string.Format(Messages["tpctarget"], player.displayName));
pendings.Remove(pend);
return;
}
}
foreach (var tpQ in tpQueue)
{
if (tpQ.Player2 != null && tpQ.Player2 == player)
{
SendReply(player, Messages["tpc"]);
SendReply(tpQ.Player, string.Format(Messages["tpctarget"], player.displayName));
tpQueue.Remove(tpQ);
return;
}
if (tpQ.Player == player)
{
SendReply(player, Messages["tpc"]);
if (tpQ.Player2 != null)
SendReply(tpQ.Player2, string.Format(Messages["tpctarget"], player.displayName));
tpQueue.Remove(tpQ);
return;
}
}
}
#region ADMIN COMMANDS
void SpectateFinish(BasePlayer player)
{
player.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, false);
player.SetPlayerFlag(BasePlayer.PlayerFlags.ThirdPersonViewmode, false);
player.Command("camoffset", "0,1,0");
player.SetParent(null);
player.gameObject.SetLayerRecursive(17);
player.metabolism.Reset();
player.InvokeRepeating("InventoryUpdate", 1f, 0.1f * UnityEngine.Random.Range(0.99f, 1.01f));
var heldEntity = player.GetActiveItem()?.GetHeldEntity() as HeldEntity;
heldEntity?.SetHeld(true);
// Teleport to original location after spectating
if (lastPositions.ContainsKey(player.userID))
{
var lastPosition = lastPositions[player.userID];
Teleport(player, new Vector3(lastPosition.x, lastPosition.y, lastPosition.z));
lastPositions.Remove(player.userID);
}
player.StopSpectating();
SendReply(player, "Слежка закончена!");
}
[ChatCommand("tpl")]
void cmdChattpGo(BasePlayer player, string command, string[] args)
{
if (!player.IsAdmin && !PermissionService.HasPermission(player.userID, "teleportation.admin")) return;
if (args == null || args.Length == 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["tpArgsError"]);
return;
}
switch (args[0])
{
default:
if (!tpsave.ContainsKey(player.userID))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homesmissing"]);
return;
}
var nametp = args[0];
var playerTP = tpsave[player.userID];
if (!playerTP.ContainsKey(nametp))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homenotexist"]);
return;
}
var position = playerTP[nametp];
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null)
{
SendReply(player, ret);
return;
}
var lastTp = tpQueue.Find(p => p.Player == player);
if (lastTp != null)
{
tpQueue.Remove(lastTp);
}
tpQueue.Add(new TP(player, position, 0));
Effect.server.Run(EffectPrefab1, player, 0, Vector3.zero, Vector3.forward);
SaveData();
return;
case "add":
if (args == null || args.Length == 1)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["settpArgsError"]);
return;
}
var nameAdd = args[1];
SetTpSave(player, nameAdd);
return;
case "remove":
if (args == null || args.Length == 1)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["removetpArgsError"]);
return;
}
if (!tpsave.ContainsKey(player.userID))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homesmissing"]);
return;
}
var playertp = tpsave[player.userID];
var name = args[1];
if (!playertp.ContainsKey(name))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homenotexist"]);
return;
}
Effect.server.Run(EffectPrefab1, player, 0, Vector3.zero, Vector3.forward);
playertp.Remove(name);
SaveData();
SendReply(player, Messages["removehomesuccess"], name);
return;
case "list":
if (!tpsave.ContainsKey(player.userID) || tpsave[player.userID].Count == 0)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homesmissing"]);
return;
}
var playerTPList = tpsave[player.userID];
var tplist = playerTPList.Select(x => GetSleepingBag(x.Key, x.Value) != null ? $"{x.Key} ({x.Value})" : $"{x.Key} {x.Value}");
SendReply(player, Messages["tplist"], string.Join("\n", tplist.ToArray()));
return;
}
}
[ChatCommand("tpspec")]
void cmdTPSpec(BasePlayer player, string command, string[] args)
{
if (!player.IsAdmin && !PermissionService.HasPermission(player.userID, "teleportation.admin")) return;
if (args.Length == null || args.Length != 1)
{
SendReply(player, Messages["tpspecError"]);
return;
}
string name = args[0];
BasePlayer target = FindBasePlayer(name);
if (target == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["playermissing"]);
return;
}
if (!player.IsSpectating())
{
switch (args.Length)
{
case 1:
if (!target.IsConnected)
{
SendReply(player, Messages["playermissingOff"]);
return;
}
if (target.IsDead())
{
SendReply(player, Messages["playermissingOrDeath"]);
return;
}
if (ReferenceEquals(target, player))
{
SendReply(player, Messages["playerItsYou"]);
return;
}
if (target.IsSpectating())
{
SendReply(player, Messages["playerItsSpec"]);
return;
}
spectatingPlayers.Remove(target);
lastPositions[player.userID] = player.GetNetworkPosition();
var heldEntity = player.GetActiveItem()?.GetHeldEntity() as HeldEntity;
heldEntity?.SetHeld(false);
player.SetPlayerFlag(BasePlayer.PlayerFlags.Spectating, true);
player.gameObject.SetLayerRecursive(10);
player.CancelInvoke("MetabolismUpdate");
player.CancelInvoke("InventoryUpdate");
player.ClearEntityQueue();
entitySnapshot.Invoke(player, new object[] { target });
player.gameObject.Identity();
player.SetParent(target);
player.SetPlayerFlag(BasePlayer.PlayerFlags.ThirdPersonViewmode, true);
player.Command("camoffset 0,1.3,0");
SendReply(player, $"Вы наблюдаете за игроком {target}! Что бы переключаться между игроками, нажимайте: Пробел");
break;
}
}
else
{
SpectateFinish(player);
}
}
[ChatCommand("tp")]
void cmdTP(BasePlayer player, string command, string[] args)
{
if (!player.IsAdmin && !PermissionService.HasPermission(player.userID, "teleportation.admin")) return;
switch (args.Length)
{
case 1:
string name = args[0];
BasePlayer target = FindBasePlayer(name);
if (target == null)
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["playermissing"]);
return;
}
if (adminsLogs)
{
LogToFile("admin", $"[{DateTime.Now.ToShortTimeString()}] {player} телепортировался к {target}", this, true);
}
Teleport(player, target);
break;
case 2:
string name1 = args[0];
string name2 = args[1];
BasePlayer target1 = FindBasePlayer(name1);
BasePlayer target2 = FindBasePlayer(name2);
if (target1 == null || target2 == null)
{
SendReply(player, Messages["playermissing"]);
return;
}
if (adminsLogs)
{
LogToFile("admin", $"[{DateTime.Now.ToShortTimeString()}] Игрок {player} телепортировал {target1} к {target2}", this, true);
}
Teleport(target1, target2);
break;
case 3:
float x = float.Parse(args[0]);
float y = float.Parse(args[1]);
float z = float.Parse(args[2]);
if (adminsLogs)
{
LogToFile("admin", $"[{DateTime.Now.ToShortTimeString()}] Игрок {player} телепортировался на координаты: ({x} / {y} / {z})", this, true);
}
Teleport(player, x, y, z);
break;
}
}
[ConsoleCommand("home.wipe")]
private void CmdTest(ConsoleSystem.Arg arg)
{
if (arg.Connection != null) return;
WipeData();
}
#endregion
#endregion
#region OXIDE HOOKS
public string TimeToString(double time)
{
TimeSpan elapsedTime = TimeSpan.FromSeconds(time);
int hours = elapsedTime.Hours;
int minutes = elapsedTime.Minutes;
int seconds = elapsedTime.Seconds;
int days = Mathf.FloorToInt((float)elapsedTime.TotalDays);
string s = "";
if (days > 0) s += $"{days} дн.";
if (hours > 0) s += $"{hours} ч.";
if (minutes > 0) s += $"{minutes} мин.";
if (seconds > 0) s += $"{seconds} сек.";
else s = s.TrimEnd(' ');
return s;
}
void OnPlayerDisconnected(BasePlayer player)
{
pendings.RemoveAll(p => p.Player == player || p.Player2 == player);
tpQueue.RemoveAll(p => p.Player == player || p.Player2 == player);
}
void OnNewSave()
{
if (wipedData)
{
PrintWarning("Обнаружен вайп.Очищаем данные с data/Teleportation");
Interface.Oxide.DataFileSystem.WriteObject("Teleportation/Homes", new Dictionary<string, FileInfo>());
Interface.Oxide.DataFileSystem.WriteObject("Teleportation/AdminTpSave", new Dictionary<string, FileInfo>());
LoadData();
Interface.Oxide.ReloadPlugin(Title);
}
}
void OnServerInitialized()
{
LoadDefaultConfig();
lang.RegisterMessages(Messages, this, "en");
Messages = lang.GetMessages("en", this);
PermissionService.RegisterPermissions(this, new List<string>() { TPADMIN });
LoadData();
timer.Every(1f, TeleportationTimerHandle);
}
void Unload()
{
SaveData();
}
void OnEntityBuilt(Planner planner, GameObject gameobject)
{
if (planner == null || gameobject == null) return;
var player = planner.GetOwnerPlayer();
BaseEntity entity = gameobject.ToBaseEntity();
if (entity == null) return;
if (gameobject.name.Contains("foundation"))
{
var pos = gameobject.transform.position;
foreach (var pending in tpQueue)
{
if (Vector3.Distance(pending.pos, pos) < 3)
{
entity.Kill();
SendReply(planner.GetOwnerPlayer(), "Нельзя, тут телепортируется игрок!");
return;
}
}
}
}
#endregion
#region CORE
void TeleportationTimerHandle()
{
List<ulong> tpkdToRemove = new List<ulong>();
foreach (var uid in cooldownsTP.Keys.ToList())
{
if (--cooldownsTP[uid] <= 0)
{
tpkdToRemove.Add(uid);
}
}
tpkdToRemove.ForEach(p => cooldownsTP.Remove(p));
List<ulong> tpkdHomeToRemove = new List<ulong>();
foreach (var uid in cooldownsHOME.Keys.ToList())
{
if (--cooldownsHOME[uid] <= 0)
{
tpkdHomeToRemove.Add(uid);
}
}
tpkdHomeToRemove.ForEach(p => cooldownsHOME.Remove(p));
for (int i = pendings.Count - 1; i >= 0; i--)
{
var pend = pendings[i];
if (pend.Player2 != null && pend.Player2.IsConnected && pend.Player2.IsWounded())
{
SendReply(pend.Player2, Messages["tpwounded"]);
pendings.RemoveAt(i);
continue;
}
if (--pend.seconds <= 0)
{
pendings.RemoveAt(i);
if (pend.Player2 != null && pend.Player2.IsConnected) SendReply(pend.Player2, Messages["tppendingcanceled"]);
if (pend.Player != null && pend.Player.IsConnected) SendReply(pend.Player, Messages["tpacanceled"]);
}
}
for (int i = tpQueue.Count - 1; i >= 0; i--)
{
var reply = 229;
var tp = tpQueue[i];
if (tp.Player != null && tp.Player.IsConnected && (tp.Player.metabolism.bleeding.value > 0 || tp.Player.IsWounded()))
{
SendReply(tp.Player, Messages["tpwounded"]);
if (tp.Player2 != null && tp.Player.IsConnected)
SendReply(tp.Player2, Messages["tpWoundedTarget"]);
tpQueue.RemoveAt(i);
continue;
}
if (--tp.seconds <= 0)
{
tpQueue.RemoveAt(i);
var ret = Interface.CallHook("CanTeleport", tp.Player) as string;
if (ret != null)
{
SendReply(tp.Player, ret);
continue;
}
Teleport(tp.Player, tp.pos);
if (tp.Player2 != null && tp.Player != null && tp.Player.IsConnected && tp.Player2.IsConnected)
{
var seconds = GetKD(tp.Player.userID);
SetCooldown(tp.Player, "tp", seconds);
cooldownsTP[tp.Player.userID] = seconds;
SendReply(tp.Player, string.Format(Messages["tpplayersuccess"], tp.Player2.displayName));
}
else
if (tp.Player != null && tp.Player.IsConnected)
{
var seconds = GetKDHome(tp.Player.userID);
SetCooldown(tp.Player, "home", seconds);
cooldownsHOME[tp.Player.userID] = seconds;
SendReply(tp.Player, Messages["tphomesuccess"]);
}
NextTick(() => Interface.CallHook("OnPlayerTeleported", tp.Player));
}
}
}
void SetTpSave(BasePlayer player, string name)
{
var uid = player.userID;
var pos = player.GetNetworkPosition();
Dictionary<string, Vector3> adminTP;
if (!tpsave.TryGetValue(uid, out adminTP))
adminTP = (tpsave[uid] = new Dictionary<string, Vector3>());
if (adminTP.ContainsKey(name))
{
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homeexist"]);
return;
}
adminTP.Add(name, pos);
Effect.server.Run(EffectPrefab1, player, 0, Vector3.zero, Vector3.forward);
SendReply(player, Messages["homesucces"], name);
SaveData();
timer.Once(10f, () => sethomeBlock.Remove(player.userID));
}
void SetHome(BasePlayer player, string name)
{
var uid = player.userID;
var pos = player.GetNetworkPosition();
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);
SendReply(player, Messages["sethomecupboard"]);
return;
}
Dictionary<string, Vector3> playerHomes;
i
// ... [Code preview truncated due to length. Full source in attached file] ...