/// <summary> /// Create a <see cref="Portal" /> list from a <see cref="ZPackage" /> /// </summary> /// <param name="zpkg"></param> /// <returns></returns> public static PortalList FromZPackage(ZPackage zpkg) { Logger.LogDebug("Deserializing portal list from ZPackage"); var ret = new PortalList(); var numConnectedPortals = zpkg.ReadInt(); while (numConnectedPortals > 0) { var portalPosition = zpkg.ReadVector3(); var portalName = zpkg.ReadString(); Logger.LogDebug($"{portalName}@{portalPosition}"); ret.Add(new Portal(portalPosition, portalName, true)); numConnectedPortals--; } var numUnconnectedPortals = zpkg.ReadInt(); while (numUnconnectedPortals > 0) { var portalPosition = zpkg.ReadVector3(); var portalName = zpkg.ReadString(); Logger.LogDebug($"{portalName}@{portalPosition}"); ret.Add(new Portal(portalPosition, portalName, false)); numUnconnectedPortals--; } return(ret); }
/// <summary> /// RPC to handle initial sync to a new peer /// </summary> /// <param name="sender"></param> /// <param name="teleporterZPackage"></param> public static void RPC_TeleporterSyncInit(long sender, ZPackage teleporterZPackage) { // SERVER SIDE if (ZNet.instance.IsServerInstance() || ZNet.instance.IsLocalInstance()) { Logger.LogInfo($"Sending portal data to peer #{sender}"); var portals = PortalList.GetPortals(); if (ZNet.instance.IsLocalInstance()) { UpdatePins(portals); } var package = portals.ToZPackage(); ZRoutedRpc.instance.InvokeRoutedRPC(sender, nameof(RPC_TeleporterSyncInit), package); } // CLIENT SIDE if (ZNet.instance.IsClientInstance()) { if (teleporterZPackage != null && teleporterZPackage.Size() > 0 && sender == ZRoutedRpc.instance.GetServerPeerID()) { // Read package and create pins from portal list Logger.LogInfo("Received portal data from server"); portalsFromServer = PortalList.FromZPackage(teleporterZPackage); UpdatePins(portalsFromServer); } } }
/// <summary> /// CLIENT SIDE: Initially pull portals after SetMapData on Minimap /// </summary> private static void UpdatePortalPins(On.Minimap.orig_SetMapData orig, Minimap self, byte[] data) { orig(self, data); if (ZNet.instance.IsServerInstance()) { return; } if (!ConfigUtil.Get <bool>("Map", "showPortalsOnMap")) { return; } if (ZNet.instance.IsLocalInstance()) { Logger.LogMessage("Initializing portals"); UpdatePins(PortalList.GetPortals()); } if (ZNet.instance.IsClientInstance()) { Logger.LogMessage("Sending portal sync request to server"); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), nameof(RPC_Veilheim_TeleporterSyncInit), new ZPackage()); } }
/// <summary> /// Get the current list of <see cref="Portal" /> ZDOs /// </summary> /// <returns></returns> public static PortalList GetPortals() { Logger.LogDebug("Creating portal list from ZDOMan"); // Collect all portal locations/names var connected = new List <ZDO>(); var unconnected = new Dictionary <string, ZDO>(); foreach (var zdoarray in ZDOMan.instance.m_objectsBySector) { if (zdoarray != null) { foreach (var zdo in zdoarray.Where(x => x.m_prefab == -661882940)) { var tag = zdo.GetString("tag"); if (!unconnected.ContainsKey(tag)) { unconnected.Add(tag, zdo); } else { connected.Add(zdo); connected.Add(unconnected[tag]); unconnected.Remove(tag); } } } } // Make a list of all Portals var ret = new PortalList(); Portal portal; Logger.LogDebug("Connected Portals"); foreach (var entry in connected.OrderBy(x => x.GetString("tag"))) { portal = new Portal(entry.m_position, entry.GetString("tag"), true); Logger.LogDebug(portal); ret.Add(portal); } Logger.LogDebug("Unconnected Portals"); foreach (var entry in unconnected.OrderBy(x => x.Value.GetString("tag"))) { portal = new Portal(entry.Value.m_position, entry.Value.GetString("tag"), false); Logger.LogDebug(portal); ret.Add(portal); } return(ret); }
public static void UpdatePortalPins(Minimap instance) { if (ZNet.instance.IsServerInstance()) { return; } if (!Configuration.Current.Map.IsEnabled || !Configuration.Current.Map.showPortalsOnMap) { return; } if (ZNet.instance.IsLocalInstance()) { Logger.LogInfo("Initializing portals"); UpdatePins(PortalList.GetPortals()); } if (ZNet.instance.IsClientInstance()) { Logger.LogInfo("Sending portal sync request to server"); ZRoutedRpc.instance.InvokeRoutedRPC(ZRoutedRpc.instance.GetServerPeerID(), nameof(RPC_TeleporterSyncInit), new ZPackage()); } }
public static void OpenPortalSelection() { if (TextInput.instance.m_panel.activeSelf) { Logger.LogInfo("Generating portal selection"); // set position of textinput (a bit higher) TextInput.instance.m_panel.transform.localPosition = new Vector3(0, 270.0f, 0); // Create gameobject(s) if not exist if (portalRect == null) { portalRect = GenerateGUI(); } IEnumerable <Portal> singlePortals; // Generate list of unconnected portals from ZDOMan if (ZNet.instance.IsLocalInstance()) { singlePortals = PortalList.GetPortals().Where(x => !x.m_con); } // or from PortalsOnMap.portalsFromServer, if it is a real client else { singlePortals = PortalsOnMap.portalsFromServer.Where(x => !x.m_con); } // remove all buttons from earlier calls foreach (var oldbt in teleporterButtons) { if (oldbt != null) { Object.Destroy(oldbt); } } // empty the local list teleporterButtons.Clear(); var idx = 0; // calculate number of lines var lines = singlePortals.Count() / 3; // Get name of portal var currentTag = TextInput.instance.m_textField.text; if (string.IsNullOrEmpty(currentTag)) { currentTag = "<unnamed>"; TextInput.instance.m_textField.text = currentTag; } if (TextInput.instance.m_panel.transform.Find("OK") != null) { var originalButton = TextInput.instance.m_panel.transform.Find("OK").gameObject; foreach (var portal in singlePortals) { // Skip if it is the selected teleporter if (portal.m_tag == currentTag || currentTag == "<unnamed>" && string.IsNullOrEmpty(portal.m_tag)) { continue; } // clone button var newButton = Object.Instantiate(originalButton, buttonList.GetComponent <RectTransform>()); newButton.name = "TP" + idx; // set position newButton.transform.localPosition = new Vector3(-600.0f / 3f + idx % 3 * 600.0f / 3f, lines * 25f - idx / 3 * 50f, 0f); // enable newButton.SetActive(true); // set button text newButton.GetComponentInChildren <Text>().text = portal.m_tag; // add event payload newButton.GetComponentInChildren <Button>().onClick.AddListener(() => { // Set input field text to new name TextInput.instance.m_textField.text = portal.m_tag; // simulate enter key TextInput.instance.OnEnter(portal.m_tag); // hide textinput TextInput.instance.Hide(); }); // Add to local list teleporterButtons.Add(newButton); idx++; } } if (singlePortals.Count() > 0) { // show buttonlist only if single teleports are available to choose from portalRect.gameObject.SetActive(true); } // Set anchor buttonList.GetComponent <RectTransform>().anchoredPosition = new Vector2(0, -(singlePortals.Count() / 3) * 25.0f); // Set size buttonList.GetComponent <RectTransform>().SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, singlePortals.Count() / 3 * 50.0f + 50f); // release mouselock GameCamera.instance.m_mouseCapture = false; GameCamera.instance.UpdateMouseCapture(); } }
private static void CreatePortalGUI(string currentTag) { if (GUIRoot == null) { GUIRoot = Object.Instantiate(GUIManager.Instance.GetPrefab("PortalButtonBox")); GUIRoot.transform.SetParent(GUIManager.PixelFix.transform, false); GUIRoot.GetComponentInChildren <Image>().sprite = GUIManager.Instance.GetSprite("woodpanel_trophys"); } foreach (var button in teleporterButtons) { Object.Destroy(button); } teleporterButtons.Clear(); IEnumerable <Portal> singlePortals; // Generate list of unconnected portals from ZDOMan if (ZNet.instance.IsLocalInstance()) { singlePortals = PortalList.GetPortals().Where(x => !x.m_con); } // or from PortalsOnMap.portalsFromServer, if it is a real client else { singlePortals = PortalsOnMap.portalsFromServer.Where(x => !x.m_con); } var idx = 0; var lines = singlePortals.Count() / 3; foreach (var portal in singlePortals) { // Skip if it is the selected teleporter if (portal.m_tag == currentTag || currentTag == "<unnamed>" && string.IsNullOrEmpty(portal.m_tag)) { continue; } var newButton = GUIManager.Instance.CreateButton(portal.m_tag, GUIRoot.transform.Find("Image/Scroll View/Viewport/Content"), new Vector2(0, 1), new Vector2(0, 1), new Vector2(0, 0)); newButton.GetComponent <Button>().onClick.AddListener(() => { // Set input field text to new name TextInput.instance.m_textField.text = portal.m_tag; // simulate enter key TextInput.instance.OnEnter(portal.m_tag); // hide textinput TextInput.instance.Hide(); // Reset visibility state GUIRoot.SetActive(false); }); newButton.name = "TP" + teleporterButtons.Count; newButton.SetActive(true); newButton.GetComponent <RectTransform>().anchoredPosition = new Vector2(95f + idx % 3 * (180f + 20f), -(idx / 3) * 50f - 25f); teleporterButtons.Add(newButton); idx++; } GUIRoot.transform.Find("Image/Scroll View/Viewport/Content").GetComponent <RectTransform>() .SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, lines * 50f + 50f); GUIRoot.SetActive(teleporterButtons.Count > 0); }
/// <summary> /// Add and remove pins in internal list based on a list of portals /// </summary> /// <param name="portals"></param> public static void UpdatePins(PortalList portals) { Logger.LogDebug("Updating pins of portals on minimap"); // prevent MT crashing lock (portalPins) { // Add connected portals (separated connected and unconnected, maybe show another icon?) foreach (var portal in portals.FindAll(x => x.m_con)) { Logger.LogDebug(portal); // Was pin already added? var foundPin = portalPins.FirstOrDefault(x => x.m_pos == portal.m_pos); if (foundPin != null) { // Did the pin's name change? if (foundPin.m_name != portal.m_tag) { // Remove pin at location and readd with new name portalPins.Remove(foundPin); portalPins.Add(CreatePinData(portal.m_pos, Minimap.PinType.Icon4, portal.m_tag, false, false)); } } else { // Add new pin portalPins.Add(CreatePinData(portal.m_pos, Minimap.PinType.Icon4, portal.m_tag, false, false)); } } // Add unconnected portals (maybe show another icon / text?) foreach (var portal in portals.FindAll(x => !x.m_con)) { Logger.LogDebug(portal); // Was pin already added? var foundPin = portalPins.FirstOrDefault(x => x.m_pos == portal.m_pos); if (foundPin != null) { // Did the pin's name change? if (foundPin.m_name != portal.m_tag) { // Remove pin at location and readd with new name portalPins.Remove(foundPin); portalPins.Add(CreatePinData(portal.m_pos, Minimap.PinType.Icon4, portal.m_tag, false, false)); } } else { // Add new pin portalPins.Add(CreatePinData(portal.m_pos, Minimap.PinType.Icon4, portal.m_tag, false, false)); } } // Remove destroyed portals from map // doesn't really react on portal destruction, only works if after a portal was destroyed, someone set the name on another portal foreach (var kv in portalPins.ToList()) { if (portals.All(x => x.m_pos != kv.m_pos)) { portalPins.Remove(kv); } } } Logger.LogInfo("Portal pins updated succesfully"); }