//Oh... More shitcode! public static void GenerateNavGraph() { try { Log.Info("[NAV] Generating navigation graph..."); StreamReader sr = File.OpenText(Config.NPCs_nav_mappings_path); var deserializer = new DeserializerBuilder().IgnoreUnmatchedProperties().Build(); Dictionary <string, List <NavigationNode.NavNodeSerializationInfo> > manual_mappings = deserializer.Deserialize <Dictionary <string, List <NavigationNode.NavNodeSerializationInfo> > >(sr); sr.Close(); Log.Info("[NAV] Mapping lifts..."); foreach (Lift lift in Map.Lifts) { int i = 0; NavigationNode prev_node = null; foreach (Lift.Elevator elevator in lift.elevators) { NavigationNode node = NavigationNode.Create(elevator.target.position, $"AUTO_Elevator_{lift.elevatorName}_{i}".Replace(' ', '_')); node.AttachedElevator = new KeyValuePair <Lift.Elevator, Lift>(elevator, lift); i++; if (prev_node != null) { prev_node.LinkedNodes.Add(node); node.LinkedNodes.Add(prev_node); } else { prev_node = node; } } } foreach (Room r in Map.Rooms) { string rname = r.Name.RemoveBracketsOnEndOfName(); if (!manual_mappings.ContainsKey(rname)) { NavigationNode node = NavigationNode.Create(r.Position, $"AUTO_Room_{r.Name}".Replace(' ', '_')); foreach (DoorVariant d in r.Doors) { if (d == null) { continue; } if (d.gameObject.transform.position == Vector3.zero) { continue; } NavigationNode new_node = NavigationNode.Create(d.gameObject.transform.position, $"AUTO_Door_{(d.gameObject.transform.position)}".Replace(' ', '_')); if (new_node == null) { new_node = NavigationNode.AllNodes[$"AUTO_Door_{(d.gameObject.transform.position)}".Replace(' ', '_')]; } else { new_node.AttachedDoor = d; } node.LinkedNodes.Add(new_node); new_node.LinkedNodes.Add(node); } } else { bool is_first = true; Log.Debug($"Loading manual mappings for room {r.Name}", Plugin.Instance.Config.VerboseOutput); List <NavigationNode.NavNodeSerializationInfo> nodes = manual_mappings[rname]; int i = 0; foreach (DoorVariant d in r.Doors) { if (d == null) //idk { continue; } if (d.gameObject.transform.position == Vector3.zero) { continue; } NavigationNode new_node = NavigationNode.Create(d.gameObject.transform.position, $"AUTO_Door_{(d.gameObject.transform.position)}".Replace(' ', '_')); if (new_node != null) { new_node.AttachedDoor = d; } else { new_node = NavigationNode.AllNodes[$"AUTO_Door_{(d.gameObject.transform.position)}".Replace(' ', '_')]; } } foreach (NavigationNode.NavNodeSerializationInfo info in nodes) { NavigationNode node = NavigationNode.Create(info, is_first ? $"AUTO_Room_{r.Name}".Replace(' ', '_') : $"MANUAL_Room_{r.Name}_{i}".Replace(' ', '_'), rname); is_first = false; foreach (NavigationNode d in NavigationNode.AllNodes.Values.Where(nd => nd != node && Vector3.Distance(nd.Position, node.Position) < Plugin.Instance.Config.NavNodeMapperMaxDistance)) { node.LinkedNodes.Add(d); d.LinkedNodes.Add(node); Log.Debug($"Linked {node.Name} and {d.Name}", Plugin.Instance.Config.VerboseOutput); } i++; } } } } catch (Exception e) { Log.Error($"Caught an exception while generating navigation graph: {e}/{e.StackTrace}"); } }
public bool Execute(ArraySegment <string> arguments, ICommandSender sender, out string response) { if (sender is PlayerCommandSender player) { Player s = Player.Get(player.PlayerId); if (!s.CheckPermission("npc.all")) { response = "Access denied!"; return(false); } if (!Round.IsStarted) { response = "Round is not started!"; return(false); } if (arguments.Count == 0) { response = "Available subcommands: [create, list, remove, clean, rebuild, sav, show]"; return(false); } NavigationNode created_node; Pickup pickup; switch (arguments.At(0)) { case "create": string name = (++new_node_id).ToString(); if (!s.IsAlive) { response = "You must be alive to use this!"; return(false); } created_node = NavigationNode.Create(s.Position, name, s.CurrentRoom.Name.RemoveBracketsOnEndOfName()); if (arguments.Count > 1) { string[] AvailableItemTypes = arguments.At(1).Split(','); foreach (string type in AvailableItemTypes) { created_node.PossibleItemTypes.Add(type.Trim()); } } pickup = ItemType.SCP018.Spawn(1f, created_node.Position + new UnityEngine.Vector3(0, 0.5f, 0)); pickup.Locked = true; foreach (NavigationNode d in NavigationNode.AllNodes.Values.Where(nd => nd != created_node && Vector3.Distance(nd.Position, created_node.Position) < Plugin.Instance.Config.NavNodeMapperMaxDistance)) { created_node.LinkedNodes.Add(d); d.LinkedNodes.Add(created_node); Log.Info($"Linked {created_node.Name} and {d.Name}"); } response = "Created node!"; break; case "list": int id = 0; foreach (NavigationNode node in NavigationNode.AllNodes.Values) { s.RemoteAdminMessage($"{id} - {node.Name}"); } response = "List end"; break; case "remove": if (arguments.Count <= 1) { response = "You need to provide node name!"; return(false); } try { NavigationNode rnode = NavigationNode.AllNodes[arguments.At(1)]; NavigationNode.AllNodes.Remove(rnode.Name); UnityEngine.Object.Destroy(rnode); response = "Node removed"; } catch (KeyNotFoundException) { response = "Node not found!"; return(false); } break; case "clean": NavigationNode.Clear(); response = "Removed all nodes!"; break; case "rebuild": NavigationNode.Clear(); Methods.GenerateNavGraph(); response = "Rebuilt navigation graph"; break; case "sav": Dictionary <string, List <NavigationNode.NavNodeSerializationInfo> > manual_mappings = new Dictionary <string, List <NavigationNode.NavNodeSerializationInfo> >(); IEnumerable <NavigationNode> to_serialize = NavigationNode.AllNodes.Values.Where(n => n.SInfo != null); foreach (NavigationNode node in to_serialize) { node.SInfo.ItemTypes = new List <string>(node.PossibleItemTypes); if (!manual_mappings.ContainsKey(node.Room.RemoveBracketsOnEndOfName())) { List <NavigationNode.NavNodeSerializationInfo> nodes = new List <NavigationNode.NavNodeSerializationInfo> { node.SInfo }; manual_mappings.Add(node.Room.RemoveBracketsOnEndOfName(), nodes); } else { manual_mappings[node.Room.RemoveBracketsOnEndOfName()].Add(node.SInfo); } } FileStream fs = File.Open(Config.NPCs_nav_mappings_path, FileMode.Truncate, FileAccess.Write); StreamWriter sw = new StreamWriter(fs); var serializer = new SerializerBuilder().Build(); var yaml = serializer.Serialize(manual_mappings); sw.Write(yaml); sw.Close(); response = "Saved manual navigation mappings!"; break; case "show": foreach (NavigationNode node in NavigationNode.AllNodes.Values) { pickup = ItemType.SCP018.Spawn(1f, node.Position + new UnityEngine.Vector3(0, 0.5f, 0)); pickup.Locked = true; } response = "Marked nodes!"; break; case "items": if (arguments.Count <= 2) { response = "You need to provide node name and at least one item group!"; return(false); } try { NavigationNode rnode = NavigationNode.AllNodes[arguments.At(1)]; for (int i = 2; i < arguments.Count; i++) { if (rnode.PossibleItemTypes.Add(arguments.At(i))) { s.RemoteAdminMessage($"Added type: {arguments.At(i)}"); } } response = ""; } catch (KeyNotFoundException) { response = "Node not found!"; return(false); } break; case "r_items": if (arguments.Count <= 2) { response = "You need to provide node name and at least one item group!"; return(false); } try { NavigationNode rnode = NavigationNode.AllNodes[arguments.At(1)]; for (int i = 2; i < arguments.Count; i++) { if (rnode.PossibleItemTypes.Remove(arguments.At(i))) { s.RemoteAdminMessage($"Removed type: {arguments.At(i)}"); } } response = ""; } catch (KeyNotFoundException) { response = "Node not found!"; return(false); } break; case "info": if (arguments.Count <= 1) { response = "You need to provide node name!"; return(false); } try { NavigationNode rnode = NavigationNode.AllNodes[arguments.At(1)]; s.RemoteAdminMessage("Linked nodes:"); foreach (NavigationNode node in rnode.LinkedNodes) { s.RemoteAdminMessage(node.Name); } s.RemoteAdminMessage($"Attached door: {rnode.AttachedDoor?.DoorName}"); s.RemoteAdminMessage($"Attached elevator: {rnode.AttachedElevator}"); response = ""; } catch (KeyNotFoundException) { response = "Node not found!"; return(false); } break; default: response = "Unknown subcommand!"; return(false); } } else { response = "Only players can use this!"; return(false); } return(true); }