Иконка ресурса

FREE BusStopTeleport : 1.0.2 1.0.2

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using UnityEngine;
using Oxide.Core.Libraries.Covalence;
using Oxide.Game.Rust.Cui;
using Oxide.Core.Plugins;
using Oxide.Core;
using Rust;

namespace Oxide.Plugins {
	[Info("Bus Stop Teleport", "yetzt", "1.0.2")]
	[Description("Teleport using Bus Stops")]

	public class BusStopTeleport : RustPlugin {

		private const string UsePerm = "busstopteleport.use";

		[PluginReference]
		private Plugin NoEscape;

		List<ulong> hasUI = new List<ulong>();
		private readonly string Layer = "busstopUI";

		class StoredData {
			public Dictionary<ulong, BusStop> BusStops = new Dictionary<ulong, BusStop>();
			public List<ulong> Chairs = new List<ulong>();
			public StoredData(){}
		}
		StoredData storedData;

		class BusStop {
			public Vector3 Location = new Vector3();
			public string Label = "";
			public string Grid = "";
			public ulong Chair = 0;
			public BusStop(){}
			public BusStop(Vector3 pos, string label, string grid, ulong chair) {
				Location = pos;
				Label = label;
				Grid = grid;
				Chair = chair;
			}
		}

		BusStop busStop;

		void SaveData() => Interface.Oxide.DataFileSystem.WriteObject("BusStopTeleport", storedData);

		private void Init() {
			permission.RegisterPermission(UsePerm, this);
			cmd.AddConsoleCommand("busstop.close", this, nameof(closeUI));
			cmd.AddConsoleCommand("busstop.teleport", this, nameof(cmdTeleport));
			cmd.AddConsoleCommand("busstop.reset", this, nameof(cmdResetNetwork));
		}

		private bool IsAdmin(BasePlayer player) {
			if (player == null) return false;
			if (player?.net?.connection == null) return true;
			return player.net.connection.authLevel > 0;
		}


		[ChatCommand("bus")]
		void replyBus(BasePlayer player, string cmd, string[] args) {
			if (IsAdmin(player) || permission.UserHasPermission(player.userID.ToString(), UsePerm)) showUI(player, 0);
		}

		void OnServerInitialized() {
			Puts("Initializing");
			storedData = Interface.Oxide.DataFileSystem.ReadObject<StoredData>("BusStopTeleport");
			resetNetwork();
		}

		void Unload() {

			// Remove Chairs
			foreach(var item in storedData.BusStops.Values) {
				var chair = BaseNetworkable.serverEntities.Find(new NetworkableId(item.Chair)) as BaseEntity;
				if (chair != null) chair.Kill();
			}

			// Delete Data
			storedData.BusStops.Clear();
			storedData.Chairs.Clear();
//			storedData.BusStops.Save();
//			storedData.Chairs.Save();

		}

		void showUI(BasePlayer player, ulong chair) {

			CuiHelper.DestroyUi(player, Layer);
			if (hasUI.Contains(player.userID)) {
				hasUI.Remove(player.userID);
				return;
			}

			var container = new CuiElementContainer();

			// overlay
			container.Add(new CuiPanel {
				CursorEnabled = true,
				Image = {
					Color = "0 0 0 0"
				},
				RectTransform = {
					AnchorMin = "0 0",
					AnchorMax = "1 1"
				}
			}, "Overlay", Layer);

			// background
			container.Add(new CuiPanel {
				Image = new CuiImageComponent
				{
					Color = "0 0 0 0.95"
				},
				RectTransform =
				{
					AnchorMin = "0 0",
					AnchorMax = "0.4 1"
				}
			}, Layer);

			// close
			container.Add(new CuiButton {
				RectTransform = {
					AnchorMin = "0.02 0.1",
					AnchorMax = "0.12 0.16"
				},
				Button = {
					Command = "busstop.close",
					Color = "0.4 0.15 0.1 0.9",
					Close = Layer
				},
				Text = {
					Align = TextAnchor.MiddleCenter,
					Text = "EXIT",
					Color = "0.9 0.9 0.9 0.9",
					FontSize = 20
				}
			}, Layer);

			// headline
			container.Add(new CuiLabel {
				RectTransform = {
					AnchorMin = "0.02 0.90",
					AnchorMax = "0.2 0.97"
				},
				Text = {
					Text = "RUST",
					Align = TextAnchor.MiddleLeft,
					Color = "1 1 1 1",
					FontSize = 50
				}
			}, Layer);

			container.Add(new CuiLabel {
				RectTransform = {
					AnchorMin = "0.02 0.84",
					AnchorMax = "0.2 0.91"
				},
				Text = {
					Text = "TRANSPORT",
					Align = TextAnchor.MiddleLeft,
					Color = "1 1 1 1",
					FontSize = 50
				}
			}, Layer);

			container.Add(new CuiLabel {
				RectTransform = {
					AnchorMin = "0.02 0.78",
					AnchorMax = "0.2 0.85"
				},
				Text = {
					Text = "NETWORK",
					Align = TextAnchor.MiddleLeft,
					Color = "1 1 1 1",
					FontSize = 50
				}
			}, Layer);

			// add vertical line
			container.Add(new CuiPanel {
				Image = new CuiImageComponent
				{
					Color = "0 0.7 1 1"
				},
				RectTransform =
				{
					AnchorMin = "0.248 0",
					AnchorMax = "0.252 1"
				}
			}, Layer);

			int i = 0;
			foreach(var item in storedData.BusStops.Values) {

				if (chair == item.Chair) continue;

				//a dot
				container.Add(new CuiPanel {
					Image = new CuiImageComponent {
						Color = "0 0.7 1 1"
					},
					RectTransform = {
						AnchorMin = "0.246 "+(0.94f-(i*0.035f)).ToString(),
						AnchorMax = "0.254 "+(0.953f-(i*0.035f)).ToString()
					}
				}, Layer);

				container.Add(new CuiLabel {
					RectTransform = {
						AnchorMin = "0.22 "+(0.93f-(i*0.035f)).ToString(),
						AnchorMax = "0.24 "+(0.963f-(i*0.035f)).ToString()
					},
					Text = {
						Text = item.Grid,
						Align = TextAnchor.MiddleRight,
						Color = "0.7 0.7 0.7 1",
						FontSize = 20
					}
				}, Layer);

				container.Add(new CuiButton {
					RectTransform = {
						AnchorMin = "0.26 "+(0.93f-(i*0.035f)).ToString(),
						AnchorMax = "0.4 "+(0.963f-(i*0.035f)).ToString()
					},
					Button = {
						Command = "busstop.teleport "+item.Chair,
						Color = "0 0 0 0",
						Close = Layer
					},
					Text = {
						Align = TextAnchor.MiddleLeft,
						Text = item.Label.ToUpper(),
						Color = "1 1 1 1",
						FontSize = 20
					}
				}, Layer);

				i++;

			}

			CuiHelper.DestroyUi(player, Layer);
			CuiHelper.AddUi(player, container);

			hasUI.Add(player.userID);

		}

		private void resetNetwork() {

			foreach(var item in storedData.BusStops.Values) {
				var chair = BaseNetworkable.serverEntities.Find(new NetworkableId(item.Chair)) as BaseEntity;
				if (chair != null) chair.Kill();
			}

			storedData.BusStops = new Dictionary<ulong, BusStop>();
			storedData.Chairs = new List<ulong>();

			FindMonuments();

		}

		private void closeUI(ConsoleSystem.Arg arg) {
			var player = arg.Player();
			if (player == null) return;
			player.EnsureDismounted();
			CuiHelper.DestroyUi(player, Layer);
			hasUI.Remove(player.userID);
		}

		private void cmdTeleport(ConsoleSystem.Arg arg) {
			var player = arg.Player();
			if (player == null) return;
			if (!hasUI.Contains(player.userID)) return;
			CuiHelper.DestroyUi(player, Layer);
			hasUI.Remove(player.userID);

			BusStop busstop;
			if (!storedData.BusStops.TryGetValue(Convert.ToUInt32(arg.Args[0]), out busstop)) return;

			performTeleport(player, busstop.Location);
			return;
		}

		private void cmdResetNetwork(ConsoleSystem.Arg arg) {
			if (IsAdmin(arg.Player())) resetNetwork();
		}

		void performTeleport(BasePlayer player, Vector3 position){

			HeldEntity heldEntity = player.GetHeldEntity();
			if (heldEntity != null) heldEntity.SetHeld(false);

			player.EnsureDismounted();

			if (player.net?.connection != null) player.ClientRPCPlayer(null, player, "StartLoading");

			if (!player.IsSleeping()) {
				player.SetPlayerFlag(BasePlayer.PlayerFlags.Sleeping, true);
				if (!BasePlayer.sleepingPlayerList.Contains(player)) BasePlayer.sleepingPlayerList.Add(player);
				player.CancelInvoke("InventoryUpdate");
			}

			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.SendNetworkUpdateImmediate();

			if (player.net?.connection == null) return;
			try { player.ClearEntityQueue(); } catch { }

			player.SendFullSnapshot();
			player.SetParent(null, true, true);

			Wakeup(player);

			return;

		}

		private void Wakeup(BasePlayer player) {
			if (!player.IsConnected) return;
			if (player.IsReceivingSnapshot) {
				timer.Once(1f, () => Wakeup(player));
				return;
			}
			player.EndSleeping();
		}

		void FindMonuments() {

			Dictionary<ulong, GameObject> busstops = new Dictionary<ulong, GameObject>();

			foreach (var go in UnityEngine.Object.FindObjectsOfType<GameObject>()) {
				if (go.name != "assets/bundled/prefabs/autospawn/decor/busstop/busstop.prefab") continue;

				// spawn invisible chair, fallback to visible chair
				var chair = GameManager.server.CreateEntity("assets/bundled/prefabs/static/chair.invisible.static.prefab", go.transform.position, go.transform.rotation, true);
				if (chair == null) chair = GameManager.server.CreateEntity("assets/bundled/prefabs/static/chair_b.static.prefab", go.transform.position, go.transform.rotation, true);

				chair.transform.RotateAround(go.transform.position, Vector3.up, 90f);
				chair.transform.Translate(Vector3.up * 0.52f);
				chair.transform.Translate(Vector3.forward * -1.7f);

				chair.Spawn();

				Vector3 pos = go.transform.position;
				pos.y = pos.y+0.3f;

				storedData.Chairs.Add(chair.net.ID.Value);
				busstops.Add(chair.net.ID.Value, go);

			}

			Puts($"Found {busstops.Count} Bus Stops.");

			List<ulong> doublecheck = new List<ulong>();

			foreach (var monument in TerrainMeta.Path.Monuments) {
				if (monument.name.Contains("substation") || monument.name.Contains("cave") || monument.name.Contains("tiny")) continue;

				float size = 0f;
				string name = "";

				switch (monument.name.Split('/').Last()) {
					case "lighthouse.prefab":
						name = "Lighthouse";
						size = 100f;
						break;

					case "stables_a.prefab":
						name = "Stables";
						size = 100f;
						break;

					case "stables_b.prefab":
						name = "Barn";
						size = 100f;
						break;

					case "fishing_village_a.prefab":
					case "fishing_village_b.prefab":
					case "fishing_village_c.prefab":
						name = "Fishing Village";
						size = 100f;
						break;

					case "harbor_1.prefab":
					case "harbor_2.prefab":
						name = "Harbor";
						size = 150f;
						break;

					case "excavator_1.prefab":
						name = "Excavator";
						size = 300f;
						break;

					case "launch_site_1.prefab":
						name = "Launch Site";
						size = 400f;
						break;

					case "trainyard_1.prefab":
						name = "Trainyard";
						size = 200f;
						break;

					case "water_treatment_plant_1.prefab":
						name = "Water Treatment Plant";
						size = 200f;
						break;

					case "military_tunnel_1.prefab":
						name = "Military Tunnel";
						size = 200f;
						break;

					case "powerplant_1.prefab":
						name = "Powerplant";
						size = 200f;
						break;

					case "airfield_1.prefab":
						name = "Airfield";
						size = 200f;
						break;

					case "compound.prefab":
						name = "Outpost";
						size = 150f;
						break;

					case "bandit_town.prefab":
						name = "Bandit Camp";
						size = 150f;
						break;

					case "radtown_small_3.prefab":
						name = "Sewer Branch";
						size = 200f;
						break;

					case "warehouse.prefab":
						name = "Mining Outpost";
						size = 100f;
						break;

					case "satellite_dish.prefab":
						name = "Satellite Dish";
						size = 150f;
						break;

					case "supermarket_1.prefab":
						name = "Supermarket";
						size = 100f;
						break;

					case "gas_station_1.prefab":
						name = "Gas Station";
						size = 100f;
						break;

					case "junkyard_1.prefab":
						name = "Junkyard";
						size = 200f;
						break;

					case "swamp_c.prefab":
						name = "Abandonned Cabins";
						size = 150f;
						break;

					case "sphere_tank.prefab":
						name = "Dome";
						size = 150f;
						break;

					case "mining_quarry_a.prefab":
						name = "Sulphur Quarry";
						size = 100f;
						break;

					case "mining_quarry_b.prefab":
						name = "Stone Quarry";
						size = 100f;
						break;

					case "mining_quarry_c.prefab":
						name = "HQM Quarry";
						size = 100f;
						break;

					case "OilrigAI":
						name = "Small Oilrig";
						size = 100f;
						break;

					case "OilrigAI2":
						name = "Large Oilrig";
						size = 150f;
						break;

					case "desert_military_base_a.prefab":
					case "desert_military_base_b.prefab":
					case "desert_military_base_c.prefab":
					case "desert_military_base_d.prefab":
						name = "Desert Military Base";
						size = 150f;
						break;

					case "arctic_research_base_a.prefab":
						name = "Arctic Research Base";
						size = 150f;
						break;

					case "nuclear_missile_silo.prefab":
						name = "Nuclear Missile Silo";
						size = 200f;
					break;

					case "monument_marker.prefab":
						// Puts("marker "+monument.name+" "+monument.transform.root.name);
						name = monument.transform.root.name;
						size = 100f;
						break;
					case "cave_large_hard.prefab":
					case "cave_large_medium.prefab":
					case "cave_medium_easy.prefab":
					case "cave_medium_hard.prefab":
					case "cave_medium_medium.prefab":
					case "cave_small_easy.prefab":
					case "cave_small_hard.prefab":
					case "cave_small_medium.prefab":
					case "ice_lake_1.prefab":
					case "ice_lake_2.prefab":
					case "ice_lake_3.prefab":
					case "ice_lake_4.prefab":
					case "swamp_a.prefab":
					case "swamp_b.prefab":
					case "water_well_a.prefab":
					case "water_well_b.prefab":
					case "water_well_c.prefab":
					case "water_well_d.prefab":
					case "water_well_e.prefab":
					case "underwater_lab_a.prefab":
					case "underwater_lab_b.prefab":
					case "underwater_lab_c.prefab":
					case "underwater_lab_d.prefab":
					case "entrance_bunker_a.prefab":
					case "entrance_bunker_b.prefab":
					case "entrance_bunker_c.prefab":
					case "entrance_bunker_d.prefab":
						// ignore
						continue;
					break;
					default:
						Puts($"Unknown Monument: "+monument.name.Split('/').Last());
						continue;
				}

				// find closest bus stop

				float dist = 1000f;
				float newdist = 0f;
				bool found = false;
				GameObject closest = new GameObject();
				ulong closestchair = 0;

				foreach (KeyValuePair<ulong, GameObject> busstop in busstops) {

					if (doublecheck.Contains(busstop.Key)) continue;

					newdist = Vector3.Distance(monument.transform.position, busstop.Value.transform.position);
					// Puts($"{monument.transform.position} ↔ {name}: {newdist}");
					if (newdist > size) continue;
					if (newdist < dist) {
						found = true;
						dist = newdist;
						closest = busstop.Value;
						closestchair = busstop.Key;
					}

				}

				if (found) {
					Puts($"Found Busstop for '{name}' at {closest.transform.position}");

					// add bus stop to dboubleckeck
					doublecheck.Add(closestchair);

					Vector3 pos = closest.transform.position;
					pos.y = pos.y+0.3f;

					string grid = getGrid(pos);
					busStop = new BusStop(pos, name, grid, closestchair);

					storedData.BusStops.Add(closestchair, busStop);

				} else {
					Puts($"No Busstop for '{name}'");
				}

			}

			// return list
			SaveData();

		}

		string getGrid(Vector3 pos) { // FIXME this is not always correct
			char letter = 'A';
			var x = Mathf.Floor((pos.x+(ConVar.Server.worldsize/2)) / 146.3f)%26;
			var z = (Mathf.Floor(ConVar.Server.worldsize/146.3f))-Mathf.Floor((pos.z+(ConVar.Server.worldsize/2)) / 146.3f);
			letter = (char)(((int)letter)+x);
			return $"{letter}{z}";
		}

		object CanMountEntity(BasePlayer player, BaseMountable entity) {

			if (!storedData.Chairs.Contains(entity.net.ID.Value)) return null;

			// noescape integration
			var flag = NoEscape?.Call<bool>("IsEscapeBlocked", player) ?? false;
			if (flag == true) {
				Player.Message(player, "You are still blocked from taking the bus");
				return null;
			}

			showUI(player, entity.net.ID.Value);
			return null;

		}

		object CanDismountEntity(BasePlayer player, BaseMountable entity) {

			if (player == null) return null;

			if (!storedData.Chairs.Contains(entity.net.ID.Value)) return null;

			CuiHelper.DestroyUi(player, Layer);
			hasUI.Remove(player.userID);

			return null;

		}

	}

}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху