C#:
using Newtonsoft.Json.Converters;
using Oxide.Core.Plugins;
using Oxide.Core;
using System.Linq;
using ProtoBuf;
using System.Collections;
using Object = System.Object;
using Vector3 = UnityEngine.Vector3;
using Pool = Facepunch.Pool;
using System.Text;
using Rust;
using Physics = UnityEngine.Physics;
using Newtonsoft.Json;
using System;
using UnityEngine;
using UnityEngine.Networking;
using Oxide.Game.Rust.Cui;
using System.Collections.Generic;
using ConVar;
namespace Oxide.Plugins {
[Info("IQTeleportation", "Mercury", "1.28.36")]
[Description("IQTeleportation")]
class IQTeleportation : RustPlugin {
private static StringBuilder sb = new StringBuilder();
[ConsoleCommand("tpa")]
private void TpaConsoleCMD(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player == null) return;
AcceptRequestTeleportation(player);
}
private void AutoClearData(Boolean isNewSave = false) {
Int32 settingClear = default;
List<UInt64> keysPlayersSetting = Pool.Get<List<UInt64>>();
keysPlayersSetting.AddRange(playerSettings.Keys);
DateTime currentDate = DateTime.Now;
foreach (UInt64 keyPlayer in keysPlayersSetting) {
SettingPlayer playerSetting = playerSettings[keyPlayer];
Int32 leftDays = (currentDate - playerSetting.firstConnection).Days;
if (leftDays < 7) continue;
playerSettings.Remove(keyPlayer);
if (playerLimitController.playersLimits.ContainsKey(keyPlayer)) playerLimitController.playersLimits.Remove(keyPlayer);
if (playerLastHomes.ContainsKey(keyPlayer)) playerLastHomes.Remove(keyPlayer);
settingClear++;
}
Pool.FreeUnmanaged(ref keysPlayersSetting);
if(settingClear != default) Puts(LanguageEn ? $"Automatic cleaning of user settings. {settingClear} users and their settings were deleted due to absence from the server for more than 7 days" : $"Автоматическая очистка настроек пользоваталей. Было удалено {settingClear} пользователей и их настройки из-за отсутствия более 7 дней на сервере");
if (isNewSave) {
playerHomes.Clear();
playerLimitController.playersLimits.Clear();
playerLimitController.homeTime = 0;
playerLimitController.teleportTime = 0;
playerLimitController.warpTime = 0;
playerLastHomes.Clear();
List<String> keysToRemove = new List<String>();
foreach (KeyValuePair<String, List<ServerWarp>> warps in serverWarps) {
List<ServerWarp> warpsToRemove = new List<ServerWarp>();
foreach (ServerWarp warp in warps.Value) {
if (String.IsNullOrWhiteSpace(warp.monumentParent)) warpsToRemove.Add(warp);
}
foreach (ServerWarp warp in warpsToRemove) warps.Value.Remove(warp);
if (warps.Value.Count == 0) keysToRemove.Add(warps.Key);
warpsToRemove.Clear();
warpsToRemove = null;
}
foreach (String key in keysToRemove) {
cmd.RemoveChatCommand(key, this);
cmd.RemoveConsoleCommand(key, this);
serverWarps.Remove(key);
}
keysToRemove.Clear();
keysToRemove = null;
}
WriteData();
}
private void OnEntityKill(PlayerBoat playerBoat) {
if (!playerBoat) return;
UInt64 netIDplayerBoat = playerBoat.net.ID.Value;
playersBoatsServer.Remove(netIDplayerBoat);
}
private void SimpleStatus_SetStatus(BasePlayer player, String nameStatus, Int32 duration) {
if(!SimpleStatus) return;
if (!config.generalController.simpleStatusController.useSimpleStatus) return;
if (String.IsNullOrWhiteSpace(nameStatus)) return;
SimpleStatus.CallHook("SetStatus", player.UserIDString, nameStatus, duration);
}
public String GetLang(String LangKey, String userID = null, params Object[] args) {
sb.Clear();
if (args != null) {
sb.AppendFormat(lang.GetMessage(LangKey, this, userID), args);
return sb.ToString();
}
return lang.GetMessage(LangKey, this, userID);
}
private const String effectSoundTimer = "assets/prefabs/weapons/mp5/effects/fire_select.prefab";
private Boolean CheckHome(BasePlayer player, String homeName, PlayerHome pHome) {
Vector3 positionHome = pHome.positionHome;
if (pHome.netIdEntity != 0) {
if (pHome.typeEntity == TypeHomeEntity.Tugboat) {
if (tugboatsServer.TryGetValue(pHome.netIdEntity, out Tugboat tugboat) && tugboat && !tugboat.IsDestroyed) {
if (tugboat.IsAuthedForBuilding(player)) return true;
SendChat(GetLang("CAN_TELEPORT_HOME_NOT_TUGBOAT_NO_AUTH", player.UserIDString, homeName), player);
return false;
}
SendChat(GetLang("CAN_TELEPORT_HOME_NOT_TUGBOAT", player.UserIDString, homeName), player);
return false;
}
if (pHome.typeEntity == TypeHomeEntity.PlayerBoat) {
if (playersBoatsServer.TryGetValue(pHome.netIdEntity, out PlayerBoat playerBoat) && playerBoat && !playerBoat.IsDestroyed) {
if (playerBoat.IsAuthedForBuilding(player)) return true;
SendChat(GetLang("CAN_TELEPORT_HOME_NOT_PLAYER_BOAT_NO_AUTH", player.UserIDString, homeName), player);
return false;
}
SendChat(GetLang("CAN_TELEPORT_HOME_NOT_PLAYER_BOAT", player.UserIDString, homeName), player);
return false;
}
}
BuildingBlock buildingBlock = GetBuildingBlock(positionHome);
if (!buildingBlock) {
SendChat(GetLang("CAN_TELEPORT_HOME_NOT_BUILDING_BLOCK", player.UserIDString, homeName), player);
return false;
}
if (!config.homeController.setupHomeController.onlyBuildingAuth) return true;
BuildingPrivlidge privilege = buildingBlock.GetBuildingPrivilege();
if (privilege == null || privilege.IsAuthed(player)) return true;
SendChat(GetLang("CAN_TELEPORT_HOME_NOT_AUTH_BUILDING_PRIVILAGE", player.UserIDString, homeName), player);
return false;
}
[ConsoleCommand("gmap.home.request")]
private void HomeConsoleInGMap(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (!player) return;
if (arg.Args.Length == 0) {
SendChat(GetLang("SYNTAX_COMMAND_HOME_TELEPORTATION", player.UserIDString), player, true);
return;
}
RequestHome(player, arg.Args);
}
private void DrawUI_HomeSetup(BasePlayer player) {
if (!config.homeController.suggetionSetHomeAfterInstallBed) return;
if (_interface == null || player == null) return;
player.Invoke(() => {
DestroyUI(player, InterfaceBuilder.IQ_TELEPORT_UI_HOME);
if (bagInstalled.ContainsKey(player)) bagInstalled.Remove(player);
}
, 10f);
String interfaceKey = InterfaceBuilder.IQ_TELEPORT_UI_HOME;
List<String> cache = GetOrSetCacheUI(player, interfaceKey);
if (cache != null && cache.Count != 0) {
foreach (String uiCached in cache) AddUI(player, uiCached);
return;
}
String Interface = InterfaceBuilder.GetInterface(interfaceKey);
if (Interface == null) return;
Interface = Interface.Replace("%TITILE_PANEL%", GetLang("UI_SETUP_HOME_ALERT", player.UserIDString));
Interface = Interface.Replace("%COMMAND_YES%", "ui_teleportation_command sethome");
Interface = Interface.Replace("%COMMAND_NO%", "ui_teleportation_command cancell.sethome");
List<String> newUI = GetOrSetCacheUI(player, interfaceKey, Interface);
cache = newUI;
foreach (String uiCached in cache) AddUI(player, uiCached);
}
private const String colorHomeRequestTime = "0.631 0.416 0.271 1";
private Boolean AcceptRequestTeleportation(BasePlayer player, Boolean isAutoAccept = false) {
if (!playerTeleportationQueue.TryGetValue(player.userID, out TeleportationQueueInfo requester)) {
SendChat(GetLang("CAN_ACCEPT_TELEPORTATION_NOT_REQUEST", player.UserIDString), player, true);
return false;
}
if (!requester.isActive) {
SendChat(GetLang("CAN_ACCEPT_TELEPORTATION_NOT_REQUEST", player.UserIDString), player, true);
return false;
}
if (requester.isAccepted) {
SendChat(GetLang("CAN_ACCEPT_TELEPORTATION_ACTIVE_ACCEPTED", player.UserIDString), player, true);
return false;
}
String canTeleport = CanTeleportation(player, UserRepository.TeleportType.Teleportation, false, true);
if (!String.IsNullOrWhiteSpace(canTeleport)) {
SendChat(canTeleport, player, true);
localUsersRepository[requester.player].DeActiveTeleportation();
return false;
}
Object OnTeleportRequested = Interface.Call("OnTeleportRequested", player, requester.player);
if (OnTeleportRequested != null) {
if (OnTeleportRequested is String hookResult) {
SendChat(hookResult, player, true);
localUsersRepository[requester.player].DeActiveTeleportation();
return false;
}
if (OnTeleportRequested is Boolean hookResultBoolean) if (!hookResultBoolean) {
SendChat(GetLang("ACCESS_CANCELL_TELEPORTATION", player.UserIDString), player, true);
localUsersRepository[requester.player].DeActiveTeleportation();
return false;
}
}
requester.isAccepted = true;
if (config.teleportationController.teleportSetting.suggetionAcceptedUI) DestroyUI(player, InterfaceBuilder.IQ_TELEPORT_UI_TELEPORT);
Int32 teleportationCountdown = config.teleportationController.teleportCountdown.GetCount(requester.player);
SimpleStatus_SetStatus(player, config.generalController.simpleStatusController.settingTeleportationProcess.GetFormatNameStatus(player, "timerTeleportation"), teleportationCountdown);
Coroutine routineTeleportation = ServerMgr.Instance.StartCoroutine(ProcessTTarget(requester.player, player, teleportationCountdown));
localUsersRepository[requester.player].ActiveCoroutineController(routineTeleportation);
casheTeleportationLast[player] = requester.player;
String autoRequestMessage = isAutoAccept ? "CAN_REQUEST_TELEPORTATION_ACCESS_AUTO_TELEPORT" : "CAN_REQUEST_TELEPORTATION_ACCESS";
LogAction(player, TypeLog.AcceptTeleportation, requester.player, default, default);
SendChat(GetLang(autoRequestMessage, player.UserIDString, requester.player.displayName), player);
SendChat(GetLang("REQUEST_TELEPORTATION_ACCESS", requester.player.UserIDString, FormatTime(teleportationCountdown, requester.player.UserIDString)), requester.player);
Interface.Call("OnTeleportAccepted", player, requester.player, teleportationCountdown);
return true;
}
[ChatCommand("atp")]
private void AutoAcceptTeleportChatCmd(BasePlayer player) => AutoTeleportTurn(player);
private void OnEntityDeath(Tugboat tugboat, HitInfo info) {
if (!tugboat) return;
UInt64 netIDTugBoat = tugboat.net.ID.Value;
tugboatsServer.Remove(netIDTugBoat);
}
[ConsoleCommand("homelist")]
private void ConsoleCommand_HomeList(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player == null) return;
Dictionary<String, Vector3> homeList = GetHomes(player.userID);
if (homeList == null || homeList.Count == 0) {
SendChat(GetLang("HOMELIST_COMMAND_EMPTY", player.UserIDString), player);
return;
}
String homesPlayerOnCord = String.Empty;
foreach (KeyValuePair<String, Vector3> homeInfo in homeList) {
String cordMap = MapHelper.PositionToString(homeInfo.Value);
homesPlayerOnCord += GetLang("HOMELIST_COMMAND_FORTMAT_HOME", player.UserIDString, homeInfo.Key, cordMap);
}
SendChat(GetLang("HOMELIST_COMMAND_ALL_LIST", player.UserIDString, homesPlayerOnCord), player);
}
private Int32 ConsumeLimit(BasePlayer player, TypeLimit type) {
if (!playerLimitController.playersLimits.TryGetValue(player.userID, out var limits)) playerLimitController.playersLimits[player.userID] = limits = new Dictionary<TypeLimit, Int32>();
limits.TryGetValue(type, out Int32 used);
Int32 available = Math.Max(0, GetAvailableLimit(player, type));
if (used >= available) return 0;
used++;
limits[type] = used;
return available - used;
}
private String CanSetHome(BasePlayer player, BuildingBlock buildingBlock, String homeName, in Vector3 positionHome, Tugboat tugboatEntity = null, PlayerBoat playerBoat = null) {
Configuration.HomeController.SetupHome homeController = config.homeController.setupHomeController;
Object canSetHome = Interface.Call("OnHomeAdd", player, homeName, positionHome);
if (canSetHome != null) {
if (canSetHome is String errorMessage && !String.IsNullOrWhiteSpace(errorMessage)) return errorMessage;
return GetLang("CAN_SETHOME_OTHER_MESSAGE", player.UserIDString);
}
String statusPlayer = CheckStatusPlayer(player, true, UserRepository.TeleportType.Home);
if (!String.IsNullOrWhiteSpace(statusPlayer)) return statusPlayer;
if(homeController.noSetupInRaidBlock && IsRaidBlocked(player)) return GetLang("CAN_SETHOME_IS_RAIDBLOCK", player.UserIDString);
Dictionary<String, PlayerHome> pData = playerHomes[player.userID];
if (pData.Count >= config.homeController.homeCount.GetCount(player, true)) return GetLang("CAN_SETHOME_MAXIMUM_HOMES", player.UserIDString);
if (pData.ContainsKey(homeName)) return GetLang("CAN_SETHOME_EXIST_HOMENAME", player.UserIDString, homeName);
foreach (KeyValuePair<String, PlayerHome> homesPlayer in pData) {
if (Vector3.Distance(homesPlayer.Value.positionHome, positionHome) < 2.8f) return GetLang("CAN_SETHOME_DISTANCE_EXIST_HOME", player.UserIDString, homesPlayer.Key);
}
if (tugboatEntity) {
if (!config.homeController.setupHomeController.canSetupTugboatHome) return GetLang("CAN_SETHOME_TUGBOAT_DISABLE", player.UserIDString);
UInt64[] friendList = GetFriendList(player);
if(friendList == null || friendList.Length == 0) return !tugboatEntity.IsAuthedForBuilding(player) ? GetLang("CAN_SETHOME_BUILDING_PRIVILAGE_AUTH_TUGBOAT", player.UserIDString) : String.Empty;
Boolean isAuthedFriend = tugboatEntity.children .OfType<VehiclePrivilege>() .Any(vehiclePrivilege => friendList.Any(vehiclePrivilege.IsAuthed));
return !isAuthedFriend && !tugboatEntity.IsAuthedForBuilding(player) ? GetLang("CAN_SETHOME_BUILDING_PRIVILAGE_AUTH_TUGBOAT", player.UserIDString) : String.Empty;
}
if (playerBoat) {
if (!config.homeController.setupHomeController.canSetupPlayerBoats) return GetLang("CAN_SETHOME_BOAT_FOUNDATION_DISABLE", player.UserIDString);
UInt64[] friendList = GetFriendList(player);
if(friendList == null || friendList.Length == 0) return player.IsBuildingBlockedByVehicle() ? GetLang("CAN_SETHOME_BUILDING_PRIVILAGE_AUTH_BOAT_FOUNDATION", player.UserIDString) : String.Empty;
Boolean isAuthedFriend = playerBoat.children .OfType<VehiclePrivilege>() .Any(vehiclePrivilege => friendList.Any(vehiclePrivilege.IsAuthed));
return !isAuthedFriend && !playerBoat.IsAuthedForBuilding(player) ? GetLang("CAN_SETHOME_BUILDING_PRIVILAGE_AUTH_BOAT_FOUNDATION", player.UserIDString) : String.Empty;
}
BuildingPrivlidge buildingPrivilage = player.GetBuildingPrivilege();
if(homeController.onlyBuildingPrivilage && buildingPrivilage == null) return GetLang("CAN_SETHOME_BUILDING_PRIVILAGE", player.UserIDString);
if (homeController.onlyBuildingAuth && buildingPrivilage != null && !player.IsBuildingAuthed()) return GetLang("CAN_SETHOME_BUILDING_PRIVILAGE_AUTH", player.UserIDString);
if (!buildingBlock) {
buildingBlock = GetBuildingBlock(positionHome);
if (!buildingBlock) return GetLang("CAN_SETHOME_BUILDING", player.UserIDString);
}
return String.Empty;
}
private void RustApp_SendNotify(String messageNotify) => RustApp.Call("RA_CreateAlert", this, messageNotify, null, null);
private class InfoLimits {
public Double homeTime;
public Double teleportTime;
public Double warpTime;
public Dictionary<UInt64, Dictionary<TypeLimit, Int32>> playersLimits = new();
}
private void ClearQueue(BasePlayer player, BasePlayer targetPlayer) {
if (player) {
UserRepository pData = localUsersRepository[player];
if(pData != null && pData.IsActiveTeleportation()) pData.DeActiveTeleportation();
playerTeleportationQueue.Remove(player.userID);
if (teleportationActions.TryGetValue(player, out Action action)) {
player.CancelInvoke(action);
teleportationActions.Remove(player);
}
}
if (targetPlayer) {
UserRepository tData = localUsersRepository[targetPlayer];
if(tData != null && tData.IsActiveTeleportation()) tData.DeActiveTeleportation();
playerTeleportationQueue.Remove(targetPlayer.userID);
if (teleportationActions.TryGetValue(targetPlayer, out Action actionTarget)) {
targetPlayer.CancelInvoke(actionTarget);
teleportationActions.Remove(targetPlayer);
}
}
}
private void CreateMapMarkerPlayer(BasePlayer player, Vector3 position, String homeName) {
if (player.State?.pointsOfInterest == null) player.State.pointsOfInterest = new List<MapNote>();
if (player.State.pointsOfInterest.Count >= ConVar.Server.maximumMapMarkers) return;
MapNote note = Pool.Get<MapNote>();
note.worldPosition = position;
note.isPing = false;
note.colourIndex = 2;
note.icon = 2;
note.noteType = 1;
note.label = homeName;
player.State.pointsOfInterest.Add(note);
player.DirtyPlayerState();
player.TeamUpdate();
using MapNoteList mapNoteList = Pool.Get<MapNoteList>();
mapNoteList.notes = Pool.Get<List<MapNote>>();
if (player.ServerCurrentDeathNote != null) mapNoteList.notes.Add(player.ServerCurrentDeathNote);
if (player.State.pointsOfInterest != null) mapNoteList.notes.AddRange(player.State.pointsOfInterest);
player.ClientRPC(RpcTarget.Player("Client_ReceiveMarkers", player), mapNoteList);
mapNoteList.notes.Clear();
Pool.FreeUnmanaged(ref mapNoteList.notes);
}
private Dictionary<BasePlayer, BasePlayer> casheTeleportationLast = new ();
private void OnEntitySpawneds(AutoTurret turret) {
if (turret == null) return;
if(ItemIdCorrecteds.Contains(turret.net.ID.Value)) turretsEx.TryAdd(turret.net.ID.Value, turret);
}
[ConsoleCommand("gmap")]
private void GMapTeleportConsoleCmd(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player == null) return;
GMapTeleportTurn(player);
}
private const String tprLog = LanguageEn ? "sent a teleport request to" : "отправил запрос на телепортацию к";
private void SetHome(BasePlayer player, String homeName, SleepingBag bag = null) {
homeName = homeName.ToLower();
CheckAllHomes(player, homeName);
Vector3 positionHome = player.transform.position;
Vector3 positionHomePing = player.transform.position;
if (bag) {
positionHome = bag.transform.position + new Vector3(0f, 0.5f, 0f);
positionHomePing = positionHome;
bag.niceName = homeName;
bag.name = homeName;
bag.SendNetworkUpdate();
}
BuildingBlock buildingBlock = GetBuildingBlock(positionHome);
Tugboat tugboatEntity = player.GetParentEntity() as Tugboat;
PlayerBoat playerBoat = player.GetParentEntity() as PlayerBoat;
UInt64 netIdEntity = 0;
TypeHomeEntity typeHomeEntity = TypeHomeEntity.None;
if (tugboatEntity) {
netIdEntity = tugboatEntity.net.ID.Value;
positionHome = tugboatEntity.transform.InverseTransformPoint(positionHome);
typeHomeEntity = TypeHomeEntity.Tugboat;
}
if (playerBoat) {
netIdEntity = playerBoat.net.ID.Value;
positionHome = playerBoat.transform.InverseTransformPoint(positionHome);
typeHomeEntity = TypeHomeEntity.PlayerBoat;
}
String canSethome = CanSetHome(player, buildingBlock, homeName, positionHome, tugboatEntity, playerBoat);
if (!String.IsNullOrWhiteSpace(canSethome)) {
SendChat(canSethome, player, true);
return;
}
playerHomes[player.userID].Add(homeName, new PlayerHome() {
netIdEntity = netIdEntity, positionHome = positionHome, typeEntity = typeHomeEntity,
}
);
if (config.homeController.addedPingMarker && !tugboatEntity && !playerBoat) AddPingAtLocation(player, positionHomePing);
if (config.homeController.addedMapMarkerHome && !tugboatEntity && !playerBoat) CreateMapMarkerPlayer(player, positionHome, homeName);
SaveHomeToMemory(player, homeName);
SendChat(GetLang("ACCESS_SETUP_SETHOME", player.UserIDString, homeName), player);
Interface.Call("OnHomeAdded", player, positionHome, homeName);
}
private const Boolean LanguageEn = false;
private void TeleportationPlayer(BasePlayer player, BasePlayer targetPlayer, Vector3 teleportationPosition) {
if (!player.IsValid()) return;
ClearQueue(player, targetPlayer);
BaseVehicle vehicle = targetPlayer.isMounted ? targetPlayer.GetMountedVehicle() : null;
String canTeleport = CanTeleportation(player, UserRepository.TeleportType.Teleportation, parentEntity : vehicle);
if (!String.IsNullOrWhiteSpace(canTeleport)) {
SendChat(canTeleport, player, true);
Interface.Call("OnTeleportInterrupted", player);
return;
}
String canTeleportTarget = CanTeleportation(targetPlayer, UserRepository.TeleportType.Teleportation, false, true, parentEntity : vehicle);
if (!String.IsNullOrWhiteSpace(canTeleportTarget)) {
SendChat(canTeleportTarget, targetPlayer, true);
Interface.Call("OnTeleportInterrupted", player);
return;
}
if (config.teleportationController.teleportSetting.onlyTeleportationFriends) {
if (!IsFriends(player, targetPlayer.userID)) {
SendChat(GetLang("CAN_TELEPORT_ONLY_FRIEND", player.UserIDString), player, true);
SendChat(GetLang("CAN_TELEPORT_ONLY_FRIEND_TARGET", player.UserIDString), targetPlayer, true);
return;
}
}
if (teleportationPosition == default) teleportationPosition = targetPlayer.transform.position;
localUsersRepository[player].SetupCooldown(player, UserRepository.TeleportType.Teleportation);
MovePlayer(player, teleportationPosition, vehicle ? vehicle : targetPlayer.GetParentEntity());
Interface.Call("OnPlayerTeleported", player, targetPlayer);
if (!config.teleportationController.limitTeleportation.useLimitTeleportation) return;
Int32 leftLimit = ConsumeLimit(player, TypeLimit.Teleportation);
Boolean isLimitExhausted = leftLimit <= 0;
String messageResult = isLimitExhausted ? GetLang("TELEPORTATION_PLAYER_LIMIT_NOTHING", player.UserIDString) : GetLang("TELEPORTATION_PLAYER_LIMIT_INFO", player.UserIDString, leftLimit);
SendChat(messageResult, player, isLimitExhausted);
}
[ConsoleCommand("tpr")]
private void TprConsoleCMD(ConsoleSystem.Arg arg) {
BasePlayer player = arg.Player();
if (player == null) return;
if (config.teleportationController.teleportSetting.disableTeleportationPlayer) {
SendChat(GetLang("CAN_REQUEST_TELEPORTATION_DISABLED", player.UserIDString), player, true);
return;
}
if (arg.Args.Length == 0 && !casheTeleportationLast.ContainsKey(player)) {
SendChat(GetLang("SYNTAX_COMMAND_TELEPORT_REQUEST", player.UserIDString), player, true);
return;
}
RequestTeleportation(player, arg.Args);
}
private enum TypeLog {
RequestTeleportation, AcceptTeleportation, RequestHomeTeleportation,
}
private static void DestroyUI(BasePlayer player, String elementName) => CommunityEntity.ServerInstance.ClientRPC<String>(RpcTarget.Player("DestroyUI", player.net.connection), elementName);
private void ClearHomesPlayer(UInt64 userID, String pluginName) {
if (!playerHomes.ContainsKey(userID)) return;
playerHomes[userID].Clear();
Puts(LanguageEn ? $"{pluginName}: All home points for player {userID} have been cleared" : $"{pluginName} : Все точки дома игрока {userID} были очищены");
}
[ChatCommand("rh")]
private void RemoveHomeShortChatCMD(BasePlayer player, String cmd, String[] arg) => RemoveHomeChatCMD(player, cmd, arg);
protected override void LoadDefaultConfig() => config = Configuration.GetNewConfiguration();
private Timer timerCheckLimit;
[ChatCommand("sethome")]
private void SetHomeChatCMD(BasePlayer player, String cmd, String[] arg) {
if (arg.Length == 0) {
SendChat(GetLang("SYNTAX_COMMAND_SETHOME", player.UserIDString), player, true);
return;
}
String homeName = arg[0];
SetHome(player, homeName);
}
private void OnEntityKill(Tugboat tugboat) {
if (!tugboat) return;
UInt64 netIDTugBoat = tugboat.net.ID.Value;
tugboatsServer.Remove(netIDTugBoat);
}
private void OnNewSave(String filename) => AutoClearData(true);
private Boolean useHomeLimit;
private Boolean IsLimitExhausted(BasePlayer player, TypeLimit type) => GetRemainingLimit(player, type) <= 0;
private String FormatTime(Double seconds, String userID = null) {
TimeSpan time = TimeSpan.FromSeconds(seconds);
String result = String.Empty;
String daysLabel = GetLang("TITLE_FORMAT_DAYS", userID);
String hoursLabel = GetLang("TITLE_FORMAT_HOURSE", userID);
String minutesLabel = GetLang("TITLE_FORMAT_MINUTES", userID);
String secondsLabel = GetLang("TITLE_FORMAT_SECONDS", userID);
if (time.Days > 0) result += $"{Format(time.Days, daysLabel, daysLabel, daysLabel)} ";
if (time.Hours > 0) result += $"{Format(time.Hours, hoursLabel, hoursLabel, hoursLabel)} ";
if (time.Minutes > 0) result += $"{Format(time.Minutes, minutesLabel, minutesLabel, minutesLabel)} ";
if (time.Seconds > 0 || string.IsNullOrEmpty(result)) result += $"{Format(time.Seconds, secondsLabel, secondsLabel, secondsLabel)}";
return result.Trim();
}
private const String colorHomeCooldown = "0.31 0.302 0.29 1";
private void RequestTeleportation(BasePlayer player, String[] arg) {
if(config.teleportationController.limitTeleportation.useLimitTeleportation) if (IsLimitExhausted(player, TypeLimit.Teleportation)) {
SendChat(GetLang("CAN_TELEPORT_LIMIT_NOTHING_TELEPORTATION", player.UserIDString), player);
return;
}
String friendNameOrID = arg.Length >= 1 ? String.Join(" ", arg) : String.Empty;
(BasePlayer, String) findInfo = new();
BasePlayer targetPlayer;
if (String.IsNullOrWhiteSpace(friendNameOrID)) {
casheTeleportationLast.TryGetValue(player, out BasePlayer oldPlayerTeleport);
targetPlayer = oldPlayerTeleport;
}
else {
findInfo = FindPlayerNameOrID(player, friendNameOrID);
targetPlayer = findInfo.Item1;
}
String requestError = CanRequestTeleportation(player, targetPlayer, findInfo.Item2);
if (!String.IsNullOrWhiteSpace(requestError)) {
SendChat(requestError, player, true);
return;
}
playerTeleportationQueue.TryAdd(targetPlayer.userID, new TeleportationQueueInfo {
player = player, isActive = true, isAccepted = false
}
);
playerTeleportationQueue.TryAdd(player.userID, new TeleportationQueueInfo {
player = targetPlayer, isActive = false, isAccepted = false
}
);
casheTeleportationLast[player] = targetPlayer;
if (playerSettings[targetPlayer.userID].autoAcceptTeleportationFriends && IsFriends(player, targetPlayer.userID)) {
if (!AcceptRequestTeleportation(targetPlayer, true)) {
SendChat(GetLang("CAN_ACCEPT_TELEPORTATION_NOT_AUTO_ACCEPT", player.UserIDString), player);
ClearQueue(player, targetPlayer);
if (localUsersRepository[player].IsActiveTeleportation()) teleportationActions.Remove(player);
return;
}
SendChat(GetLang("CAN_ACCEPT_TELEPORTATION_YES_AUTO_ACCEPT", player.UserIDString), player);
}
else {
if (config.teleportationController.teleportSetting.suggetionAcceptedUI) DrawUI_TeleportPlayer(player, targetPlayer);
SendChat(GetLang("CAN_REQUEST_TELEPORTATION_SEND", player.UserIDString, targetPlayer.displayName), player);
SendChat(GetLang("CAN_REQUEST_TELEPORTATION_RECEIVE", targetPlayer.UserIDString, player.displayName), targetPlayer);
}
LogAction(player, TypeLog.RequestTeleportation, targetPlayer, default, default);
Action teleportWaitAccept = () => {
if (localUsersRepository[player].IsActiveTeleportation()) {
teleportationActions.Remove(player);
return;
}
ClearQueue(player, targetPlayer);
SendChat(GetLang("CAN_TELEPORT_REQUEST_EXPIRED", player.UserIDString), player);
SendChat(GetLang("CAN_TELEPORT_REQUEST_EXPIRED", targetPlayer.UserIDString), targetPlayer);
}
;
teleportationActions[player] = teleportWaitAccept;
player.Invoke(teleportWaitAccept, 15f);
}
private List<MonumentInfo> localAllMonuments = new();
private void LoadedMapButtons(BasePlayer player) {
if (!config.homeController.uiMapHomeList) return;
if (!playerLastHomes.ContainsKey(player.userID)) return;
Int32 yIndex = 0;
foreach (String keyHomes in playerLastHomes[player.userID]) {
if(!playerHomes[player.userID].TryGetValue(keyHomes, out PlayerHome homeInfo)) continue;
String cordMap = MapHelper.PositionToString(homeInfo.positionHome);
DrawUI_Map_Button(player, keyHomes, cordMap, colorHomeDefault, yIndex);
yIndex++;
if (yIndex == limitMemoryLastHomes) break;
}
}
private static void NormalizePreset(Configuration.PresetOtherSetting p, Configuration.PresetOtherSetting def) {
if (p == null) return;
if (p.count <= 0) p.count = def.count;
if (p.countPermissions == null || p.countPermissions.Count == 0) p.countPermissions = new Dictionary<String, Int32>(def.countPermissions);
}
private void DrawUI_TeleportPlayer(BasePlayer player, BasePlayer targetPlayer) {
if (_interface == null || !player || !targetPlayer) return;
targetPlayer.Invoke(() => {
DestroyUI(targetPlayer, InterfaceBuilder.IQ_TELEPORT_UI_TELEPORT);
}
, 15f);
String interfaceKey = $"{InterfaceBuilder.IQ_TELEPORT_UI_TELEPORT}_{targetPlayer.UserIDString}";
List<String> cache = GetOrSetCacheUI(targetPlayer, interfaceKey);
if (cache != null && cache.Count != 0) {
foreach (String uiCached in cache) AddUI(targetPlayer, uiCached);
return;
}
String Interface = InterfaceBuilder.GetInterface(InterfaceBuilder.IQ_TELEPORT_UI_TELEPORT);
if (Interface == null) return;
String displayName = CorrectedNick(player.displayName);
String titleRequest = GetLang("UI_TPR_REQUSET", targetPlayer.UserIDString, displayName.ToUpper());
Interface = Interface.Replace("%TITILE_PANEL%", titleRequest);
Interface = Interface.Replace("%COMMAND_YES%", "ui_teleportation_command tpa");
Interface = Interface.Replace("%COMMAND_NO%", "ui_teleportation_command tpc");
List<String> newUI = GetOrSetCacheUI(targetPlayer, interfaceKey, Interface);
cache = newUI;
foreach (String uiCached in cache) AddUI(targetPlayer, uiCached);
}
private const String permissionTP = "iqteleportation.tp";
private const String effectSoundTeleport = "assets/prefabs/misc/halloween/lootbag/effects/loot_bag_upgrade.prefab";
private Int32 GetRemainingLimit(BasePlayer player, TypeLimit type) {
Int32 used = playerLimitController.playersLimits.TryGetValue(player.userID, out Dictionary<TypeLimit, Int32> info) && info.TryGetValue(type, out Int32 value) ? value : 0;
Int32 available = Math.Max(0, GetAvailableLimit(player, type));
return Math.Max(0, available - used);
}
private void ParseBoats(Boolean findTugboat, Boolean findBoatBuilding) {
if (!findBoatBuilding && !findTugboat) return;
Int32 tugboatCount = 0;
Int32 playerBoats = 0;
foreach (BaseNetworkable serverEntity in BaseNetworkable.serverEntities.entityList.Get().Values) {
if (findTugboat) {
if (serverEntity is Tugboat tugboat) {
if (tugboatsServer.TryAdd(serverEntity.net.ID.Value, tugboat)) tugboatCount++;
}
}
if (findBoatBuilding) {
if (serverEntity is PlayerBoat playerBoat) {
if (playersBoatsServer.TryAdd(serverEntity.net.ID.Value, playerBoat)) playerBoats++;
}
}
}
Puts(LanguageEn ? $"Saved {tugboatCount} tugboats and {playerBoats} player boats for setting players' home points.\n" : $"Сохранено {tugboatCount} буксиров и {playerBoats} лодок игроков для установки точки дома игроков");
}
private void OnEntitySpawned(Tugboat tugboat) {
if (tugboat == null) return;
UInt64 netIDTugBoat = tugboat.net.ID.Value;
tugboatsServer.TryAdd(netIDTugBoat, tugboat);
}
private readonly List<String> exceptionsBuildingBlockEntities = new() {
"rug.deployed", "rug.bear.deployed", "sleepingbag_leather_deployed", "bed_deployed", "beachtowel.deployed", "box.wooden.large", "woodbox", "coffinstorage",
}
;
private enum TypeHomeEntity {
None, PlayerBoat, Tugboat
}
private const Single radiusCheckLayerHome = 2f;
private void ChatCommandTeleportationWarp(BasePlayer player, String cmd, String[] arg) {
if (!config.warpsContoller.useWarps) return;
if (!serverWarps.TryGetValue(cmd, out List<ServerWarp> warpPoints)) return;
if (config.warpsContoller.warpPermissions.Count != 0) {
if(config.warpsContoller.warpPermissions.TryGetValue(cmd, out String permissionWarp)) if (!permission.UserHasPermission(player.UserIDString, permissionWarp)) {
SendChat(GetLang("WARP_NO_PERMISSIONS", player.UserIDString), player, true);
return;
}
}
ServerWarp randomWarp = GetRandomWarp(warpPoints);
if (randomWarp == null) return;
RequestWarp(player, randomWarp);
}
private void RemoveHomeInMemory(BasePlayer player, String homeName) {
if (!config.homeController.uiMapHomeList) return;
if (!playerLastHomes.TryGetValue(player.userID, out List<String> list)) return;
list.Remove(homeName);
if (list.Count <= 0) playerLastHomes.Remove(player.userID);
DrawUI_LastHomes_Map(player);
}
private Boolean API_HavePendingRequest(BasePlayer player) => playerTeleportationQueue.ContainsKey(player.userID);
private void OnPlayerConnected(BasePlayer player) => RegisteredUser(player);
private void RegisteredPermissions() {
if (config.warpsContoller.useWarps) {
foreach (String countWarpCooldownPermissions in config.warpsContoller.teleportWarpCooldown .countPermissions.Keys) {
if (!permission.PermissionExists(countWarpCooldownPermissions, this)) permission.RegisterPermission(countWarpCooldownPermissions, this);
}
foreach (String countWarpCoutdownPermissions in config.warpsContoller.teleportWarpCountdown .countPermissions.Keys) {
if (!permission.PermissionExists(countWarpCoutdownPermissions, this)) permission.RegisterPermission(countWarpCoutdownPermissions, this);
}
foreach (String permissionWarp in config.warpsContoller.warpPermissions.Values) {
if (!permission.PermissionExists(permissionWarp, this)) permission.RegisterPermission(permissionWarp, this);
}
if(config.warpsContoller.limitWarps.useLimitWarp) foreach (String countWarpsLimitPermissions in config.warpsContoller.limitWarps.limitWarps.countPermissions.Keys) {
if (!permission.PermissionExists(countWarpsLimitPermissions, this)) permission.RegisterPermission(countWarpsLimitPermissions, this);
}
}
foreach (String countTeleportCooldownPermissions in config.teleportationController.teleportCooldown .countPermissions.Keys) {
if (!permission.PermissionExists(countTeleportCooldownPermissions, this)) permission.RegisterPermission(countTeleportCooldownPermissions, this);
}
foreach (String countTeleportCoutdownPermissions in config.teleportationController.teleportCountdown .countPermissions.Keys) {
if (!permission.PermissionExists(countTeleportCoutdownPermissions, this)) permission.RegisterPermission(countTeleportCoutdownPermissions, this);
}
if(config.teleportationController.limitTeleportation.useLimitTeleportation) foreach (String countTeleportationLimitPermissions in config.teleportationController.limitTeleportation.limitTeleportation.countPermissions.Keys) {
if (!permission.PermissionExists(countTeleportationLimitPermissions, this)) permission.RegisterPermission(countTeleportationLimitPermissions, this);
}
foreach (String countHomePermissions in config.homeController.homeCount.countPermissions.Keys) {
if (!permission.PermissionExists(countHomePermissions, this)) permission.RegisterPermission(countHomePermissions, this);
}
foreach (String countHomeCooldownPermissions in config.homeController.homeCooldown.countPermissions.Keys) {
if (!permission.PermissionExists(countHomeCooldownPermissions, this)) permission.RegisterPermission(countHomeCooldownPermissions, this);
}
foreach (String countHomeCoutdownPermissions in config.homeController.homeCountdown.countPermissions.Keys) {
if (!permission.PermissionExists(countHomeCoutdownPermissions, this)) permission.RegisterPermission(countHomeCoutdownPermissions, this);
}
if(config.homeController.limitTeleportationHome.useLimitTeleportationHome) foreach (String countHomeLimitPermissions in config.homeController.limitTeleportationHome.limitHomeTeleportation.countPermissions.Keys) {
if (!permission.PermissionExists(countHomeLimitPermissions, this)) permission.RegisterPermission(countHomeLimitPermissions, this);
}
if (!permission.PermissionExists(permissionGMapTeleport, this)) permission.RegisterPermission(permissionGMapTeleport, this);
if (!permission.PermissionExists(permissionTP, this)) permission.RegisterPermission(permissionTP, this);
}
[ChatCommand("tpc")]
private void CancellTeleportCmdChat(BasePlayer player) => CancellTeleportation(player);
private void SendChat(String message, BasePlayer player, Boolean isError = false) {
if (config.generalController.useOnlyGameTip) player.SendConsoleCommand("gametip.showtoast", new Object[] {
"1", message, "15"
}
);
else {
if (IQChat) IQChat?.Call("API_ALERT_PLAYER", player, message, config.generalController.iqchatSetting.customPrefix, config.generalController.iqchatSetting.customAvatar);
else player.SendConsoleCommand("chat.add", Chat.ChatChannel.Global, 0, message);
}
RunEffect(player, isError ? effectSoundError : effectSoundAccess);
}
private void AddPingAtLocation(BasePlayer player, Vector3 location) {
player.State.pings ??= new List<MapNote>();
MapNote note = Pool.Get<MapNote>();
note.worldPosition = location;
note.isPing = true;
note.timeRemaining = note.totalDuration = 30f;
note.colourIndex = 2;
note.icon = 2;
player.State.pings.Add(note);
player.DirtyPlayerState();
player.SendPingsToClient();
player.TeamUpdate(true);
}
private void CancellTeleportation(BasePlayer player) {
if (config.teleportationController.teleportSetting.suggetionAcceptedUI) DestroyUI(player, InterfaceBuilder.IQ_TELEPORT_UI_TELEPORT);
UserRepository pData = localUsersRepository[player];
if (playerTeleportationQueue.TryGetValue(player.userID, out TeleportationQueueInfo requester)) {
if (config.teleportationController.teleportSetting.suggetionAcceptedUI) DestroyUI(requester.player, InterfaceBuilder.IQ_TELEPORT_UI_TELEPORT);
SendChat(GetLang("ACCESS_CANCELL_TELEPORTATION", player.UserIDString), player);
SendChat(GetLang("ACCESS_CANCELL_TELEPORTATION", requester.player.UserIDString), requester.player);
ClearQueue(player, requester.player);
pData.DeActiveTeleportation();
Interface.Call("OnTeleportRejected", player, requester.player);
SimpleStatus_DestroyStatus(player, config.generalController.simpleStatusController.settingTeleportationProcess.GetFormatNameStatus(player, "timerTeleportation"));
return;
}
if (pData.IsActiveTeleportation()) {
SendChat(GetLang("ACCESS_CANCELL_TELEPORTATION", player.UserIDString), player);
pData.DeActiveTeleportation();
Interface.Call("OnTeleportRejected", player, requester?.player);
SimpleStatus_DestroyStatus(player, config.generalController.simpleStatusController.settingTeleportationProcess.GetFormatNameStatus(player, "timerTeleportation"));
_interface.UpdateMapButtons(player);
return;
}
SendChat(GetLang("CAN_CANCELL_TELEPORTATION_NOT_FOUNDS", player.UserIDString), player);
}
private Object CanDismountEntity(BasePlayer player, BaseMountable mountable) {
if (playerLoaded.Contains(player)) return false;
return null;
}
private void RequestHome(BasePlayer player, String[] arg) {
if(config.homeController.limitTeleportationHome.useLimitTeleportationHome) if (IsLimitExhausted(player, TypeLimit.Home)) {
SendChat(GetLang("CAN_TELEPORT_LIMIT_NOTHING_HOME", player.UserIDString), player);
return;
}
String homeName = arg[0].ToLower();
String friendNameOrID = arg.Length >= 2 ? arg[1] : String.Empty;
String requestError = CanRequestTeleportHome(player, homeName, friendNameOrID, out UInt64 userIDFriend, out String friendName);
if (!String.IsNullOrWhiteSpace(requestError)) {
SendChat(requestError, player, true);
return;
}
Boolean isOtherID = userIDFriend != default && userIDFriend != player.userID;
UInt64 userID = isOtherID ? userIDFriend : player.userID;
PlayerHome pHome = playerHomes[userID][homeName];
Int32 coutdownTeleportation = config.homeController.homeCoun
// ... [Code preview truncated due to length. Full source in attached file] ...