C#:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using ConVar;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Plugins;
using Oxide.Game.Rust.Cui;
using Rust.Ai;
using UnityEngine;
using UnityEngine.Serialization;
using WebSocketSharp;
using Console = System.Console;
using Physics = UnityEngine.Physics;
using Pool = Facepunch.Pool;
using Time = UnityEngine.Time;
namespace Oxide.Plugins {
[Info("Teleportation", "skyplugins", "1.0.3")]
public class Teleportation : RustPlugin {
#region Fields
[PluginReference]
private Plugin ImageLibrary;
public string Layer = "UI.Teleportation";
public string LayerBlur = "UI.Teleportation.Layer";
public string LayerNotification = "UI.Teleportation.Notification";
private static Teleportation ins = null;
private readonly int groundLayer = LayerMask.GetMask("Terrain", "World");
private readonly int buildingLayer = LayerMask.GetMask("Terrain", "World", "Construction", "Deployed");
private readonly int buildingMask = Rust.Layers.Server.Buildings;
private string EffectPrefab = "assets/prefabs/locks/keypad/effects/lock.code.denied.prefab";
private readonly int deployedLayer = LayerMask.GetMask("Deployed");
#endregion
#region Hooks
void OnServerInitialized() {
foreach (var privilege in _config.SettingsHome.teleportationTime.Keys) {
permission.RegisterPermission($"{privilege}".ToLower(), this);
PrintWarning($"{privilege}".ToLower());
}
LoadConfig();
LoadData();
LoadMessages();
foreach (var player in BasePlayer.activePlayerList) OnPlayerInit(player);
ins = this;
ImageLibrary.Call("AddImage", "http://pic.moscow.ovh/images/2020/03/10/ca489a7d8579254a1470e47d1d239166.png", "http://pic.moscow.ovh/images/2020/03/10/ca489a7d8579254a1470e47d1d239166.png");
//permission.GrantGroupPermission("default", "teleportation.XXX", this);
foreach (var bag in GameObject.FindObjectsOfType<SleepingBag>()) {
if (bag.skinID == 332211) {
var obj = bag.gameObject.AddComponent<MarkerBag>();
if (obj == null) return;
obj.Initialize();
}
}
}
void Unload() {
DestroyAll<MarkerBag>();
SaveData();
foreach (var player in BasePlayer.activePlayerList) {
CuiHelper.DestroyUi(player, LayerNotification);
CuiHelper.DestroyUi(player, Layer);
CuiHelper.DestroyUi(player, LayerBlur);
UnityEngine.Object.Destroy(player.GetComponent<PlayerChecker>());
}
}
void OnPlayerInit(BasePlayer player) {
if (!storedData.players.ContainsKey(player.userID)) {
storedData.players.Add(player.userID, new PlayerData());
}
if (player.GetComponent<PlayerChecker>() == null) {
player.gameObject.AddComponent<PlayerChecker>();
}
}
#endregion
#region Commands
[ChatCommand("tpc")]
void chatCommandTpc(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, "teleportation.default")) {
SendReply(player, "У вас нет прав");
return;
}
var obj = GetPlayerChecker(player);
if (obj?.Request != null && obj.Request.target != null) {
var objTarget = GetPlayerChecker(obj.Request.target);
SendMessage(player, "TPR.PLAYER.CANCEL", obj.Request.target.displayName);
SendMessage(obj.Request.target, "TPR.TARGET.CANCEL", player.displayName);
objTarget.CancelTeleport();
obj.CancelTeleport();
return;
}
if (obj != null && obj.Request?.requestConfirmed != null) {
obj.CancelTeleport();
SendMessage(player, "HOME.PLAYER.CANCEL");
}
}
/*
[ConsoleCommand("home")]
void cmdHome(ConsoleSystem.Arg arg)
{
var player = arg.Player();
if (player == null) return;
if (arg.Args == null || arg.Args.Length < 1) return;
chatCommandHome(player, "123", new[] { arg.Args[0] });
}
*/
[ChatCommand("tp")]
void chatCommandTP(BasePlayer player, string command, string[] args) {
switch (args.Length) {
case 0 : break;
case 1 : if (!player.IsAdmin) return;
string name = args[0];
BasePlayer target = null;
if (!PlayerHelper.FindOnlineMultiple(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 : if (!player.IsAdmin) return;
string name1 = args[0];
string name2 = args[1];
BasePlayer target1 = null;
if (!PlayerHelper.FindOnlineMultiple(name1, player, out target1)) {
return;
}
BasePlayer target2 = null;
if (!PlayerHelper.FindOnlineMultiple(name2, player, out target2)) {
return;
}
if (target1 == null || target2 == null) {
SendMessage(player, "PLAYER.NOT.FOUND");
return;
}
Teleport(target1, target2);
break;
case 3 : if (!player.IsAdmin) return;
float x = float.Parse(args[0]);
float y = float.Parse(args[1]);
float z = float.Parse(args[2]);
Teleport(player, x, y, z);
break;
}
}
[ConsoleCommand("UI_Teleportation")]
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")]
void chatCommandTpa(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, "teleportation.default")) {
SendReply(player, "У вас нет прав");
return;
}
var pendingPlayer = GetPlayerChecker(player)?.Request?.target;
if (pendingPlayer == null) {
SendMessage(player, "TPA.ZERO.REQUEST");
return;
}
if (player.IsWounded() && _config.SettingsResolution.canTeleportWounded || player.metabolism.bleeding.value > _config.SettingsResolution.SettingsBleeding.NeedBleedingAmount && _config.SettingsResolution.SettingsBleeding.canTeleportBleeding) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "TP.CANCEL.BLOOD.OR.WOUNDED");
return;
}
if (player.GetBuildingPrivilege(player.WorldSpaceBounds()) != null && !player.GetBuildingPrivilege(player.WorldSpaceBounds()).authorizedPlayers.Select(p => p.userid).Contains(player.userID) && _config.SettingsResolution.canTeleportInBuild) {
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);
GetPlayerChecker(pendingPlayer).StartTeleportation(player);
}
[ChatCommand("tpr")]
void chatCommandTpr(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, "teleportation.default")) {
SendReply(player, "У вас нет прав");
return;
}
if (permission.UserHasPermission(player.UserIDString, "teleportation.Вспышка_1ур")) {
SendReply(player, "У вас нет прав");
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, true);
if (!message.IsNullOrEmpty()) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessageWithoutLang(player, message);
return;
}
BasePlayer target = null;
if (storedData.players[player.userID].CooldownInfo.cooldownTeleport >= GetTimeStamp()) {
SendMessage(player, "TPR.COOLDOWN", TimeHelper.FormatTime(TimeSpan.FromSeconds(storedData.players[player.userID].CooldownInfo.cooldownTeleport - GetTimeStamp()), language : ins.lang.GetLanguage(player.UserIDString)));
return;
}
if (!PlayerHelper.FindOnlineMultiple(args[0], player, out target)) {
return;
}
if (target == null) return;
//if (target == player) return;
if (GetPlayerChecker(player).Request != null) {
SendMessage(player, "TPR.PLAYER.CANCEL.REQUEST");
return;
}
if (GetPlayerChecker(target).Request != null) {
SendMessage(player, "TPR.TARGET.CANCEL.REQUEST");
return;
}
SendMessage(player, "TPR.PLAYER.SEND", target.displayName);
SendMessage(target, "TPR.TARGET.SEND", player.displayName);
GetPlayerChecker(target).CreateTeleport(false, default(Vector3), player);
CuiElementContainer container = new CuiElementContainer();
container.Add(new CuiPanel {
CursorEnabled = false, RectTransform = {
AnchorMin = "0.5 0", AnchorMax = "0.5 0", OffsetMax = "0 0"
}
, Image = {
Color = HexToRGB("#FFFFFF20")
}
}
, "Hud", LayerNotification);
container.Add(new CuiElement() {
Parent = LayerNotification, Name = LayerNotification + ".Main", Components = {
new CuiRawImageComponent() {
Png = (string) ImageLibrary.Call("GetImage", "http://pic.moscow.ovh/images/2020/03/10/ca489a7d8579254a1470e47d1d239166.png")
}
, 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 = HexToRGB("#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 = HexToRGB("#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 = HexToRGB("#C1FF9B"), FontSize = 16
}
}
, LayerNotification + ".Main");
CuiHelper.AddUi(target, container);
if (target != player) {
GetPlayerChecker(player).CreateTeleport(false, default(Vector3), target);
}
}
[ChatCommand("removehome")]
void chatCommandRemoveHome(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, "teleportation.default")) {
SendReply(player, "У вас нет прав");
return;
}
if (args.Length != 1) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "REMOVE.HOME.HELP");
return;
}
var homeName = args[0];
if (!storedData.players[player.userID].Homes.ContainsKey(homeName)) {
SendMessage(player, "REMOVE.HOME.NONE");
return;
}
var bag = GetSleepingBag(storedData.players[player.userID].Homes[homeName][1].ToVector3());
if (bag != null) {
bag.Kill();
}
storedData.players[player.userID].Homes.Remove(homeName);
SendMessage(player, "REMOVE.HOME.SUCCESS", homeName);
}
bool CanBeWounded(BasePlayer player, HitInfo info) {
var obj = GetPlayerChecker(player);
if (obj?.Request != null && obj.Request.target != null) {
var objTarget = GetPlayerChecker(obj.Request.target);
objTarget.CancelTeleport();
obj.CancelTeleport();
return false;
}
if (obj != null && obj.Request?.requestConfirmed != null) {
obj.CancelTeleport();
}
return true;
}
[ChatCommand("sethome")]
void chatCommandSethome(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, "teleportation.default")) {
SendReply(player, "У вас нет прав");
return;
}
var foundationList = GetFoundation(player.ServerPosition);
if (!player.CanBuild()) {
SendMessage(player, "HomeTPBuildingBlocked");
return;
}
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;
}
if (args.Length != 1) {
SendMessage(player, "SETHOME.HELP");
return;
}
if (player.IsWounded() && _config.SettingsResolution.canTeleportWounded || player.metabolism.bleeding.value > _config.SettingsResolution.SettingsBleeding.NeedBleedingAmount && _config.SettingsResolution.SettingsBleeding.canTeleportBleeding) {
SendMessage(player, "BLOOD.OR.WOUNDED");
return;
}
SetHome(player, args[0]);
}
[ChatCommand("homelist")]
private void cmdChatListHome(BasePlayer player, string command, string[] args) {
var userId = player.userID;
var playerData = storedData.players[userId];
SendReply(player, "Список ваших домов:");
foreach (var location in playerData.Homes) SendReply(player, $"Название вашего дома - {location.Key}");
}
[ChatCommand("home")]
void chatCommandHome(BasePlayer player, string command, string[] args) {
if (!permission.UserHasPermission(player.UserIDString, "teleportation.default")) {
SendReply(player, "У вас нет прав");
return;
}
if (args.Length != 1) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.HELP");
return;
}
var homeName = args[0];
if (!storedData.players[player.userID].Homes.ContainsKey(homeName)) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.NOT.FOUND.OR.REMOVED");
return;
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null) {
SendMessageWithoutLang(player, ret);
return;
}
var bag = GetSleepingBag(storedData.players[player.userID].Homes[homeName].ElementAt(1).ToVector3());
if (bag == null) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.NOT.FOUND.BAG");
storedData.players[player.userID].Homes.Remove(homeName);
return;
}
if (bag.unlockTime > Time.realtimeSinceStartup) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessage(player, "HOME.COOLDOWN", TimeHelper.FormatTime(TimeSpan.FromSeconds(bag.unlockTime - Time.realtimeSinceStartup)));
return;
}
var message = CanTeleportPlayer(player, true);
if (!message.IsNullOrEmpty()) {
Effect.server.Run(EffectPrefab, player, 0, Vector3.zero, Vector3.forward);
SendMessageWithoutLang(player, message);
return;
}
var obj = GetPlayerChecker(player);
obj.CreateTeleport(true, storedData.players[player.userID].Homes[homeName].ElementAt(1).ToVector3());
}
#endregion
#region Methods
[PluginReference]
private Plugin IQChat;
private void SendMessage(BasePlayer player, string message, string arg1 = "", string arg2 = "", Chat.ChatChannel channel = Chat.ChatChannel.Global) {
if (IQChat) IQChat?.Call("API_ALERT_PLAYER", player, GetMessage(player, message, arg1, arg2), GetMessage(player, "TELEPORTATION.TITLE"));
else player.SendConsoleCommand("chat.add", channel, 0, GetMessage(player, message, arg1, arg2));
}
private void SendMessageWithoutLang(BasePlayer player, string message, Chat.ChatChannel channel = Chat.ChatChannel.Global) {
if (IQChat) IQChat?.Call("API_ALERT_PLAYER", player, message, GetMessage(player, "TELEPORTATION.TITLE"));
else player.SendConsoleCommand("chat.add", channel, 0, message);
}
private string GetMessage(BasePlayer player, string message, string arg1 = "", string arg2 = "") {
return string.Format(lang.GetMessage(message, this, player.UserIDString), arg1, arg2);
}
private void LoadMessages() {
lang.RegisterMessages(new Dictionary<string, string>() {
["TPR.PLAYER.CANCEL"]
= "You have successfully canceled teleportation to player {0}", ["TPR.TARGET.CANCEL"] = "Player {0} has canceled teleportation to you!", ["TPR.PLAYER.CANCEL.DAMAG"] = "Damaged, teleportation to player {0} canceled", ["TPR.TARGET.CANCEL.DAMAG"] = "Player {0} has taken damage, teleportation to you has been canceled!", ["HOME.PLAYER.CANCEL"] = "You canceled teleportation to your home!", ["HOME.PLAYER.CANCEL.DAMAG"] = "Damaged, teleportation home canceled!", ["PLAYER.NOT.FOUND"] = "Player not found", ["TPA.ZERO.REQUEST"] = "You have no pending teleport request!", ["TP.CANCEL.BLOOD.OR.WOUNDED"] = "Teleport canceled! You can't teleport while wounded!", ["TP.CANCEL.BUILD.DONT.AUTH"] = "You can't teleport while in a building blocked zone!", ["TPA.PLAYER.ACCEPT"] = "You've accepted the teleport request of {0}!", ["TPA.TARGET.ACCEPT"] = "Player has accepted your teleport request!! Teleportation has started!", ["TPR.HELP"] = "Use: /tpr nickname", ["TPR.COOLDOWN"] = "Your teleport requests are currently on cooldown.You'll have to wait {0} to send your next teleport request.", ["TELEPORTATION.TITLE"] = "[TELEPORTATION]", ["TPR.PLAYER.CANCEL.REQUEST"] = "You can't initiate another teleport while you have a teleport pending!", ["TPR.TARGET.CANCEL.REQUEST"] = "You can't request a teleport to someone who's about to teleport!", ["TPR.PLAYER.SEND"] = "Teleportation request to {0} was sent successfully", ["TPR.TARGET.SEND"] = "{0} sent you teleportation request\nTo accept type: /tpa\nTo refuse type: /tpc", ["REMOVE.HOME.HELP"] = "Use: /removehome name", ["REMOVE.HOME.NONE"] = "Couldn't find your home with that name!", ["REMOVE.HOME.SUCCESS"] = "You have removed your home {0}!", ["FOUNDATION.NOT.FOUND"] = "Foundation not found!", ["SETHOME.HELP"] = "Use: /sethome name", ["BLOOD.OR.WOUNDED"] = "You are bleeding or you wounded!", ["HOME.HELP"] = "Use: /home name", ["HOME.NOT.FOUND.OR.REMOVED"] = "Home location not found or has been deleted!", ["HOME.NOT.FOUND.BAG"] = "Teleportation is not possible! Sleeping bag not found!", ["HOME.COOLDOWN"] = "Teleportation has been canceled! Reason: cooldown {0}", ["CAN.TP.SWIMMING"] = "Teleportation in water is prohibited!", ["CAN.TP.ALIVE"] = "You can't teleport while being dead!", ["CAN.TP.RADIATION"] = "You are irradiated! Teleportation has been canceled!", ["CAN.TP.BLEEDING"] = "You are bleeding! Teleportation canceled!", ["CAN.TP.TEMPERATURE"] = "You're too cold to teleport!", ["CAN.TP.WOUNDED"] = "You can't teleport while wounded!", ["CAN.TP.BUILDINGBLOCK"] = "You can't teleport while in a building blocked zone!", ["SETHOME.ALREADY.EXISTS"] = "A location with this name already exists!", ["SETHOME.CANCEL.RADIUS"] = "You already have home location nearby!", ["SETHOME.CANCEL.MAXHOUSE"] = "Unable to set your home here, you have reached the maximum amount of homes!", ["SETHOME.SUCCESS"] = "You have saved the current location {0} as your home!", ["HOME.TELEPORTATION"] = "You successfully teleport to your home.Time before teleporting {0}", ["REQUEST.CHECK.DISCONNECT"] = "Teleport request has been canceled! Reason: player left server", ["REQUEST.CHECK.DEAD"] = "Teleport request has been canceled! Reason: player died!", ["REQUEST.CHECK.WOUNDED"] = "Teleport request has been canceled! Reason: player wounded!", ["REQUEST.CHECK.TIME.ENDED"] = "Teleport request has been canceled! Reason: time out!", ["TP.CHECK.BUILD"] = "Teleport request has been canceled! Reason: building blocked zone", ["TP.HOME.SUCCESS"] = "You teleported to your home!", ["TP.PLAYER.SUCCESS"] = "You have successfully teleported to {0}", ["TP.TARGET.SUCCESS"] = "Player {0} successfully teleported to you!", ["MARKER.BAG"] = "<size=24>{0}</size>\n<size=16>{1}</size>", ["MARKER.BAG.NAMEBAG"] = "{0}", ["MARKER.BAG.COOLDOWN"] = "COUNTDOWN: {0}", ["MARKER.BAG.NOTCOOLDOWN"] = "AVAILABLE FOR TELEPORTATION", ["TELEPORTATION.UI"] = "TIME LEFT BEFORE TELEPORT: {0}", ["PLAYER.NOT.FOUND.PARAM"] = "Player {0} not found", ["PLAYER.FIND.MULTIPLE"] = "Several players were found: {0}", ["TPR.UI.REQUEST"] = "REQUEST FROM PLAYER {0}", ["TPR.UI.REQUEST.YES"] = "YES", ["TPR.UI.REQUEST.NO"] = "NO", ["HomeTPBuildingBlocked"] = "Вы не можете установить свой дом, если вам не разрешено строить в этой зоне!"
}
, this);
lang.RegisterMessages(new Dictionary<string, string>() {
["TPR.PLAYER.CANCEL"]
= "Вы успешно отменили телепортацию к игроку {0}", ["TPR.TARGET.CANCEL"] = "Игрок {0} отменил телепортацию к Вам!", ["TPR.PLAYER.CANCEL.DAMAG"] = "Вы получили урон, телепортацию к игроку {0} отменена", ["TPR.TARGET.CANCEL.DAMAG"] = "Игрок {0} получил урон, телепортацию к Вам отменена!", ["HOME.PLAYER.CANCEL"] = "Вы отменили телепортацию домой!", ["HOME.PLAYER.CANCEL.DAMAG"] = "Вы получили урон, телепортацию домой отменина!", ["PLAYER.NOT.FOUND"] = "Игрок не найден", ["TPA.ZERO.REQUEST"] = "У вас нет входящих запросов на телепортацию!", ["TP.CANCEL.BLOOD.OR.WOUNDED"] = "Телепортация была отменена! Причина кровоток или вы упали!", ["TP.CANCEL.BUILD.DONT.AUTH"] = "В билдинг зоне телепортация запрещена!", ["TPA.PLAYER.ACCEPT"] = "Вы приняли запрос игрока {0}", ["TPA.TARGET.ACCEPT"] = "Игрок принял ваш запрос! Телепортация началась!", ["TPR.HELP"] = "Используйте: /tpr ник", ["TPR.COOLDOWN"] = "Телепортация невозможна! У вас кулдаун: {0}", ["TELEPORTATION.TITLE"] = "[TELEPORTATION]", ["TPR.PLAYER.CANCEL.REQUEST"] = "Телепортация невозможна! У Вас уже есть запрос!", ["TPR.TARGET.CANCEL.REQUEST"] = "Телепортация невозможна! У игрока уже есть запрос!", ["TPR.PLAYER.SEND"] = "Запрос к {0} был успешно отправлен", ["TPR.TARGET.SEND"] = "{0} отправил вам запрос на телепортацию\nЧтобы принять используйте /tpa\nЧтобы отказаться используйте /tpc", ["REMOVE.HOME.HELP"] = "Используйте: /removehome название", ["REMOVE.HOME.NONE"] = "Данного дома не существует", ["REMOVE.HOME.SUCCESS"] = "Вы удалили дом под названием {0}", ["FOUNDATION.NOT.FOUND"] = "Фундамент не найден!", ["SETHOME.HELP"] = "Используйте: /sethome название", ["BLOOD.OR.WOUNDED"] = "У вас кровотечение или вы упали!", ["HOME.HELP"] = "Используйте: /home название", ["HOME.NOT.FOUND.OR.REMOVED"] = "Точка телепортации ненайдена или была удалена!", ["HOME.NOT.FOUND.BAG"] = "Телепортация невозможна! Спальник не обнаружен!", ["HOME.COOLDOWN"] = "Телепортация была отменена! Причина: кулдаун {0}", ["CAN.TP.SWIMMING"] = "Телепортация в воде запрещена", ["CAN.TP.ALIVE"] = "Телепортация мертвым запрещена", ["CAN.TP.RADIATION"] = "Вы облучены! Телепортация была отменена!", ["CAN.TP.BLEEDING"] = "Вы истекаете кровью! Телепортация отменена!", ["CAN.TP.TEMPERATURE"] = "Вы замерзли! Телепортация отменена!", ["CAN.TP.WOUNDED"] = "Вы получили ранение! Телепортация отменена!", ["CAN.TP.BUILDINGBLOCK"] = "Вы находитесь в зоне действия шкафа! Телепортация отменена!", ["SETHOME.ALREADY.EXISTS"] = "Данный дом уже существует", ["SETHOME.CANCEL.RADIUS"] = "У вас уже установлен дом в этом месте!", ["SETHOME.CANCEL.MAXHOUSE"] = "Вы превысили максимальное количество сетхомов!", ["SETHOME.SUCCESS"] = "Вы успешно установили дом {0}", ["HOME.TELEPORTATION"] = "Вы успешно телепортируетесь на дом.До телепортации {0}", ["REQUEST.CHECK.DISCONNECT"] = "Запрос на телепортацию был отменён! Причина: цель покинула сервер", ["REQUEST.CHECK.DEAD"] = "Запрос на телепортацию был отменён! Причина: цель погибла!", ["REQUEST.CHECK.WOUNDED"] = "Запрос на телепортацию был отменён! Причина: цель упала!", ["REQUEST.CHECK.TIME.ENDED"] = "Запрос на телепортацию был отменён! Причина: окончилось время ожидания!", ["TP.CHECK.BUILD"] = "Телепортация была отменена! Причина: зона шкафа", ["TP.HOME.SUCCESS"] = "Вы успешно были телепортированы домой!", ["TP.PLAYER.SUCCESS"] = "Вы успешно телепортировались к {0}", ["TP.TARGET.SUCCESS"] = "Игрок {0} успешно телепортировался к Вам!", ["MARKER.BAG"] = "<size=24>{0}</size>\n<size=16>{1}</size>", ["MARKER.BAG.NAMEBAG"] = "{0}", ["MARKER.BAG.COOLDOWN"] = "ОТКАТ: {0}", ["MARKER.BAG.NOTCOOLDOWN"] = "ДОСТУПЕН ДЛЯ ТЕЛЕПОРТАЦИИ", ["TELEPORTATION.UI"] = "ДО КОНЦА ТЕЛЕПОРТАЦИИ ОСТАЛОСЬ: {0}", ["PLAYER.NOT.FOUND.PARAM"] = "Игрок {0} был не найден", ["PLAYER.FIND.MULTIPLE"] = "Было найдено несколько игроков: {0}", ["TPR.UI.REQUEST"] = "ЗАПРОС ОТ ИГРОКА {0}", ["TPR.UI.REQUEST.YES"] = "ДА", ["TPR.UI.REQUEST.NO"] = "НЕТ", ["HomeTPBuildingBlocked"] = "Вы не можете установить свой дом, если вам не разрешено строить в этой зоне!"
}
, this, "ru");
}
public string CanTeleportPlayer(BasePlayer player, bool isHome, BasePlayer target = null) {
if (player.IsSwimming() && _config.SettingsResolution.canTeleportSwimming) return GetMessage(player, "CAN.TP.SWIMMING");
if (!player.IsAlive()) return GetMessage(player, "CAN.TP.ALIVE");
if (player.metabolism.radiation_poison.value > _config.SettingsResolution.SettingsRadiation.NeedRadiationAmount && _config.SettingsResolution.SettingsRadiation.canTeleportRadiation) return GetMessage(player, "CAN.TP.RADIATION");
if (player.metabolism.bleeding.value > _config.SettingsResolution.SettingsBleeding.NeedBleedingAmount && _config.SettingsResolution.SettingsBleeding.canTeleportBleeding) return GetMessage(player, "CAN.TP.BLEEDING");
if (player.IsWounded() && _config.SettingsResolution.canTeleportWounded) return GetMessage(player, "CAN.TP.WOUNDED");
if (player.metabolism.temperature.value < _config.SettingsResolution.SettingsTemperature.MinNeedTemperature && _config.SettingsResolution.SettingsTemperature.canTeleportTemperature) return GetMessage(player, "CAN.TP.TEMPERATURE");
var privilege = player.GetBuildingPrivilege(player.WorldSpaceBounds());
if (privilege != null && !player.IsBuildingAuthed() && _config.SettingsResolution.canTeleportInBuild) return GetMessage(player, "CAN.TP.BUILDINGBLOCK");
return "";
}
void SetHome(BasePlayer player, string name) {
var userId = player.userID;
var pos = player.GetNetworkPosition();
var playerData = storedData.players[userId];
if (playerData.Homes.ContainsKey(name)) {
SendMessage(player, "SETHOME.ALREADY.EXISTS");
return;
}
foreach (var home in playerData.Homes) {
var position = home.Value[1].ToVector3();
if (Vector3.Distance(pos, position) < 30) {
SendMessage(player, "SETHOME.CANCEL.RADIUS");
return;
}
}
if (GetHomeLimit(userId) <= playerData.Homes.Count) {
SendMessage(player, "SETHOME.CANCEL.MAXHOUSE");
return;
}
if (!playerData.Homes.ContainsKey(name)) {
var bag = CreateSleepingBag(player, pos, name);
playerData.Homes.Add(name, new List<string>() {
bag.net.ID.ToString(), pos.ToString()
}
);
}
SendMessage(player, "SETHOME.SUCCESS", name);
}
float GetTeleportTimeHome(ulong uid) {
float min = uid;
foreach (var privilege in _config.SettingsHome.teleportationTime) if (permission.UserHasPermission(uid.ToString(), privilege.Key)) min = Mathf.Min(min, privilege.Value);
PrintError($" -TimeHome- {min}");
return min;
}
float GetTeleportTimeTPR(ulong uid) {
float min = uid;
foreach (var privilege in _config.SettingsTeleport.teleportationTime) if (permission.UserHasPermission(uid.ToString(), privilege.Key)) min = Mathf.Min(min, privilege.Value);
PrintError($" -TimeTPR- {min}");
return min;
}
float GetTeleportCooldownHome(ulong uid) {
float min = uid;
foreach (var privilege in _config.SettingsHome.cooldownTeleportation) if (permission.UserHasPermission(uid.ToString(), privilege.Key)) min = Mathf.Min(min, privilege.Value);
PrintError($" -CooldownHome- {min}");
return min;
}
float GetTeleportCooldownTPR(ulong uid) {
float min = uid;
foreach (var privilege in _config.SettingsTeleport.cooldownTeleportation) if (permission.UserHasPermission(uid.ToString(), privilege.Key)) min = Mathf.Min(min, privilege.Value);
PrintError($" -CooldownTPR- {min}");
return min;
}
int GetHomeLimit(ulong uid) {
int max = 2;
foreach (var privilege in _config.SettingsHome.countHome) if (permission.UserHasPermission(uid.ToString(), privilege.Key)) max = Mathf.Max(privilege.Value);
return max;
}
SleepingBag GetSleepingBag(Vector3 pos) {
List<SleepingBag> sleepingBags = new List<SleepingBag>();
Vis.Components(pos, .1f, sleepingBags);
return sleepingBags.Count > 0 ? sleepingBags[0] : null;
}
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.skinID = 332211;
sleepingBag.deployerUserID = player.userID;
sleepingBag.niceName = $"ДОМ {name}";
sleepingBag.OwnerID = player.userID;
sleepingBag.gameObject.AddComponent<DestroyOnGroundMissing>();
sleepingBag.gameObject.AddComponent<GroundWatch>();
List<BuildingBlock> foundations = new List<BuildingBlock>();
Vis.Components(pos, .3f, foundations);
var foundation = GetFoundation(pos);
sleepingBag.buildingID = foundation[0].buildingID;
sleepingBag.Spawn();
var obj = sleepingBag.gameObject.AddComponent<MarkerBag>();
obj.Initialize();
return sleepingBag;
}
BaseEntity GetBuldings(Vector3 pos) {
RaycastHit hit;
if (Physics.Raycast(new Ray(pos, Vector3.down), out hit, 0.1f)) {
var entity = hit.GetEntity();
if (entity != null && entity.ShortPrefabName.Contains("floor")) return entity;
if (entity != null && entity.ShortPrefabName.Contains("foundation")) return entity;
}
return null;
}
private List<BuildingBlock> GetFoundation(Vector3 positionCoordinates) {
var position = GetGround(positionCoordinates);
var entities = new List<BuildingBlock>();
var hits = Pool.GetList<BuildingBlock>();
Vis.Entities(position, 2.5f, hits, buildingLayer);
for (var i = 0; i < hits.Count; i++) {
var entity = hits[i];
if (!entity.PrefabName.Contains("foundation") || positionCoordinates.y < entity.WorldSpaceBounds().ToBounds().max.y) continue;
entities.Add(entity);
}
Pool.FreeList(ref hits);
return entities;
}
private Vector3 GetGround(Vector3 sourcePos) {
var newPos = sourcePos;
newPos.y = TerrainMeta.HeightMap.GetHeight(newPos);
RaycastHit hit;
if (Physics.Raycast(sourcePos, Vector3.down, out hit)) {
var entity = hit.GetEntity();
if (entity != null && entity.PrefabName.Contains("foundation")) {
newPos.y = sourcePos.y;
}
else {
if (entity == null) {
newPos.y = sourcePos.y;
}
}
}
sourcePos.y +=.5f;
RaycastHit hitinfo;
bool done = Physics.SphereCast(sourcePos, .1f, Vector3.up, out hitinfo, 250, groundLayer) && (hitinfo.collider.name.Contains("rock_") || hitinfo.collider.name.Contains("cave_") || hitinfo.collider.name.Contains("iceberg"));
if (Physics.SphereCast(sourcePos, .1f, Vector3.down, out hitinfo, 250, groundLayer)) {
if ((hitinfo.collider.name.Contains("iceberg")) || (hitinfo.collider.name.Contains("cave_"))) {
sourcePos.y = hitinfo.point.y;
done = true;
}
}
return done ? sourcePos : newPos;
}
private void DestroyAll<T>() {
var objects = UnityEngine.Object.FindObjectsOfType(typeof(T));
objects?.ToList().ForEach(UnityEngine.Object.Destroy);
}
public 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"))) {
player.SetParent(target.GetParentEntity());
player.SendNetworkUpdate();
}
Teleport(player, target.transform.position, target);
}
public void Teleport(BasePlayer player, float x, float y, float z) => Teleport(player, new Vector3(x, y, z));
public 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.GetComponentInParent<CargoShip>() != null || player.GetComponentInParent<HotAirBalloon>() != null || player.GetComponentInParent<Spawnable>() != null || (player.GetParentEntity() != null && player.GetParentEntity().name.Contains("cave")) || (player.GetParentEntity() != null && player.GetParentEntity().name.Contains("junkpile_water"))) {
player.SetParent(null);
player.SendNetworkUpdate();
}
}
else {
if (player.GetComponentInParent<CargoShip>() == null || player.GetComponentInParent<HotAirBalloon>() == null || player.GetComponentInParent<Spawnable>() || (player.GetParentEntity() != null && player.GetParentEntity().name.Contains("cave")) || (player.GetParentEntity() != null && player.GetParentEntity().name.Contains("junkpile_water"))) {
player.SetParent(target.GetParentEntity());
player.SendNetworkUpdate();
}
}
var ret = Interface.Call("CanTeleport", player) as string;
if (ret != null) {
SendMessageWithoutLang(player, ret);
return;
}
if (player.net?.connection != null) player.ClientRPCPlayer(null, player, "StartLoading");
player.StartSleeping();
player.MovePosition(position);
if (player.net?.connection != null) player.ClientRPCPlayer(null, player, "ForcePositionTo", position);
if (player.net?.connection != null) player.SetPlayerFlag(BasePlayer.PlayerFlags.ReceivingSnapshot, true);
player.UpdateNetworkGroup();
//player.UpdatePlayerCollider(true, false);
player.SendNetworkUpdateImmediate(false);
if (player.net?.connection == null) return;
//TODO temporary for potential rust bug
try {
player.ClearEntityQueue(null);
}
catch {
}
player.SendFullSnapshot();
}
public PlayerChecker GetPlayerChecker(BasePlayer player) {
if (player == null) return null;
if (player.gameObject.GetComponent<PlayerChecker>() == null) return player.gameObject.AddComponent<PlayerChecker>();
return player.gameObject.GetComponent<PlayerChecker>();
}
#endregion
#region Config
protected override void SaveConfig() {
Config.WriteObject(_config);
}
protected override void LoadConfig() {
base.LoadConfig();
_config = Config.ReadObject<Configuration>();
}
protected override void LoadDefaultConfig() {
_config = new Configuration() {
SettingsHome = new SettingsHome() {
countHome = {
["teleportation.XXX"]
= 3
}
, cooldownTeleportation = {
["teleportation.XXX"]
= 30f
}
, teleportationTime = {
["teleportation.XXX"]
= 10f
}
, Multiplier = 627f
}
, SettingsTeleport = {
cooldownTeleportation = {
["teleportation.XXX"]
= 30f
}
, teleportationTime = {
["teleportation.XXX"]
= 10f
}
, Multiplier = 627f
}
, SettingsResolution = new SettingsResolution() {
SettingsBleeding = new SettingsBleeding(), SettingsRadiation = new SettingsRadiation(), SettingsTemperature = new SettingsTemperature(), canTeleportSwimming = true, canTeleportWounded = true,
}
}
;
}
public Configuration _config;
public class Configuration {
[JsonProperty("Автоматически удалять DATA файл при вайпе? [Automatically delete DATA file when wipe?]")]
public bool AutoWipe = true;
[JsonProperty("Настройки дома[SETTINGS HOME]")]
public SettingsHome SettingsHome = new SettingsHome();
[JsonProperty("Настройки телепортации[SETTINGS TELEPORT]")]
public SettingsTeleport SettingsTeleport = new SettingsTeleport();
[JsonProperty("Настройки запретов[SETTINGS RESOLUTION]")]
public SettingsResolution SettingsResolution = new SettingsResolution();
}
public class SettingsHome {
[JsonProperty("Время на телепортацию ('Пермишен': Секунд) [Teleportation Time('Permission': seconds)]")]
public Dictionary<string, float> teleportationTime = new Dictionary<string, float>();
[JsonProperty("Учитывать дистанцию при телепортации? [Take into account the distance?]")]
public bool considerDistance = false;
[JsonProperty("КД на телепортацию('Пермишен': Секунд) [Cooldown Teleportation('Permission': seconds)]")]
public Dictionary<string, float> cooldownTeleportation = new Dictionary<string, float>();
[JsonProperty("Количество домов['Пермишен': Количество] [Count Home ('Permission': seconds)]")]
public Dictionary<string, int> countHome = new Dictionary<string, int>();
[JsonProperty("Множитель телепортации(для дистанции) [Multiplier teleportation for distance]")]
public double Multiplier = 0;
}
public class SettingsResolution {
[JsonProperty("Запретить телепортацию в воде? [Prohibit teleportation in water?]")]
public bool canTeleportSwimming = true;
[JsonProperty("Запретить телепортацию, если упал? [Prohibit teleportation if dropped?]")]
public bool canTeleportWounded = true;
[JsonProperty("Запретить телепортацию, если человек находится в билдинг зоне [Prohibit teleportation if a person is in the building zone]")]
public bool canTeleportInBuild = true;
[JsonProperty("Настройки радиации [Settings Radiation]")]
public SettingsRadiation SettingsRadiation = new SettingsRadiation();
[JsonProperty("Настройки кровотечения [Settings Bleeding]")]
public SettingsBleeding SettingsBleeding = new SettingsBleeding();
[JsonProperty("Настройки температуры [Settings Temperature]")]
public SettingsTemperature SettingsTemperature = new SettingsTemperature();
}
public class SettingsTemperature {
[JsonProperty("Минимальное кол-во температуры, для отмены тп [Minimum temperature, for canceling TP]")]
public float MinNeedTemperature = 3f;
[JsonProperty("Запретить телепортацию при низкой температуре? [Prohibit teleportation at low temperatures?]")]
public bool canTeleportTemperature = true;
}
public class SettingsBleeding {
[JsonProperty("Кол-во кровотечение, при котором будет вызываться запрет на телепортацию [The amount of bleeding that will trigger a ban on teleportation]")]
public float NeedBleedingAmount = 5f;
[JsonProperty("Запретить телепортацию при кровотечении? [Prohibit teleportation during bleeding?]")]
public bool canTeleportBleeding = true;
}
public class SettingsRadiation {
[JsonProperty("Кол-во радиации, при которой будет вызываться запрет на телепортацию [Amount of radiation that will cause a ban on teleportation]")]
public float NeedRadiationAmount = 5f;
[JsonProperty("Запретить телепортацию при радиации? [Prohibit teleportation during radiation?]")]
public bool canTeleportRadiation = true;
}
public class SettingsTeleport {
[JsonProperty("Время на телепортацию ('Пермишен': Секунд) [Teleportation Time('Permission': seconds)]")]
public Dictionary<string, float> teleportationTime = new Dictionary<string, float>();
[JsonProperty("Учитывать дистанцию при телепортации? [Take into account the distance?]")]
public bool considerDistance = false;
[JsonProperty("КД на телепортацию('Пермишен': Секунд) [Cooldown Teleportation('Permission': seconds)]")]
public Dictionary
// ... [Code preview truncated due to length. Full source in attached file] ...