protected void ParseLinks(XElement element, IdRemap idRemap) { string linkedToString = element.GetAttributeString("linked", ""); if (!string.IsNullOrEmpty(linkedToString)) { string[] linkedToIds = linkedToString.Split(','); for (int i = 0; i < linkedToIds.Length; i++) { int srcId = int.Parse(linkedToIds[i]); int targetId = idRemap.GetOffsetId(srcId); if (targetId <= 0) { unresolvedLinkedToID ??= new List <ushort>(); unresolvedLinkedToID.Add((ushort)srcId); continue; } linkedToID.Add((ushort)targetId); } } }
public void ResolveLinks(IdRemap childRemap) { if (unresolvedLinkedToID == null) { return; } for (int i = 0; i < unresolvedLinkedToID.Count; i++) { int srcId = unresolvedLinkedToID[i]; int targetId = childRemap.GetOffsetId(srcId); if (targetId > 0) { var otherEntity = FindEntityByID((ushort)targetId) as MapEntity; linkedTo.Add(otherEntity); if (otherEntity.Linkable && otherEntity.linkedTo != null) { otherEntity.linkedTo.Add(this); } unresolvedLinkedToID.RemoveAt(i); i--; } } }
public override void OnMapLoaded() { if (!loadSub) { return; } SubmarineInfo info = new SubmarineInfo(Submarine.Info.FilePath, "", saveElement); if (!info.SubmarineElement.HasElements) { DebugConsole.ThrowError("Failed to load a linked submarine (empty XML element). The save file may be corrupted."); return; } if (!info.SubmarineElement.Elements().Any(e => e.Name.ToString().Equals("hull", StringComparison.OrdinalIgnoreCase))) { DebugConsole.ThrowError("Failed to load a linked submarine (the submarine contains no hulls)."); return; } IdRemap parentRemap = new IdRemap(Submarine.Info.SubmarineElement, Submarine.IdOffset); sub = Submarine.Load(info, false, parentRemap); sub.Info.SubmarineClass = Submarine.Info.SubmarineClass; IdRemap childRemap = new IdRemap(saveElement, sub.IdOffset); Vector2 worldPos = saveElement.GetAttributeVector2("worldpos", Vector2.Zero); if (worldPos != Vector2.Zero) { if (GameMain.GameSession != null && GameMain.GameSession.MirrorLevel) { worldPos.X = GameMain.GameSession.LevelData.Size.X - worldPos.X; } sub.SetPosition(worldPos); } else { sub.SetPosition(WorldPosition); } DockingPort linkedPort = null; DockingPort myPort = null; MapEntity linkedItem = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent <DockingPort>() != null); if (linkedItem == null) { linkedPort = DockingPort.List.FirstOrDefault(dp => dp.DockingTarget != null && dp.DockingTarget.Item.Submarine == sub); } else { linkedPort = ((Item)linkedItem).GetComponent <DockingPort>(); } if (linkedPort == null) { if (purchasedLostShuttles) { linkedPort = (FindEntityByID(originalLinkedToID) as Item)?.GetComponent <DockingPort>(); } if (linkedPort == null) { return; } } originalLinkedPort = linkedPort; ushort originalMyId = childRemap.GetOffsetId(originalMyPortID); myPort = (FindEntityByID(originalMyId) as Item)?.GetComponent <DockingPort>(); if (myPort == null) { float closestDistance = 0.0f; foreach (DockingPort port in DockingPort.List) { if (port.Item.Submarine != sub || port.IsHorizontal != linkedPort.IsHorizontal) { continue; } float dist = Vector2.Distance(port.Item.WorldPosition, linkedPort.Item.WorldPosition); if (myPort == null || dist < closestDistance) { myPort = port; closestDistance = dist; } } } if (myPort != null) { originalMyPortID = myPort.Item.ID; myPort.Undock(applyEffects: false); myPort.DockingDir = 0; //something else is already docked to the port this sub should be docked to //may happen if a shuttle is lost, another vehicle docked to where the shuttle used to be, //and the shuttle is then restored in the campaign mode //or if the user connects multiple subs to the same docking ports in the sub editor if (linkedPort.Docked && linkedPort.DockingTarget != null && linkedPort.DockingTarget != myPort) { //just spawn below the main sub sub.SetPosition( linkedPort.Item.Submarine.WorldPosition - new Vector2(0, linkedPort.Item.Submarine.GetDockedBorders().Height / 2 + sub.GetDockedBorders().Height / 2)); } else { Vector2 portDiff = myPort.Item.WorldPosition - sub.WorldPosition; Vector2 offset = myPort.IsHorizontal ? Vector2.UnitX * myPort.GetDir(linkedPort) : Vector2.UnitY * myPort.GetDir(linkedPort); offset *= myPort.DockedDistance; sub.SetPosition((linkedPort.Item.WorldPosition - portDiff) - offset); myPort.Dock(linkedPort); myPort.Lock(isNetworkMessage: true, applyEffects: false); } } if (GameMain.GameSession?.GameMode is CampaignMode campaign && campaign.PurchasedLostShuttles) { foreach (Structure wall in Structure.WallList) { if (wall.Submarine != sub) { continue; } for (int i = 0; i < wall.SectionCount; i++) { wall.SetDamage(i, 0, createNetworkEvent: false); } } foreach (Hull hull in Hull.hullList) { if (hull.Submarine != sub) { continue; } hull.WaterVolume = 0.0f; hull.OxygenPercentage = 100.0f; } } sub.SetPosition(sub.WorldPosition - Submarine.WorldPosition, forceUndockFromStaticSubmarines: false); sub.Submarine = Submarine; }
public static List <MapEntity> LoadAll(Submarine submarine, XElement parentElement, string filePath, int idOffset) { IdRemap idRemap = new IdRemap(parentElement, idOffset); List <MapEntity> entities = new List <MapEntity>(); foreach (XElement element in parentElement.Elements()) { string typeName = element.Name.ToString(); Type t; try { t = Type.GetType("Barotrauma." + typeName, true, true); if (t == null) { DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type \"" + typeName + "\"."); continue; } } catch (Exception e) { DebugConsole.ThrowError("Error in " + filePath + "! Could not find a entity of the type \"" + typeName + "\".", e); continue; } if (t == typeof(Structure)) { string name = element.Attribute("name").Value; string identifier = element.GetAttributeString("identifier", ""); StructurePrefab structurePrefab = Structure.FindPrefab(name, identifier); if (structurePrefab == null) { ItemPrefab itemPrefab = ItemPrefab.Find(name, identifier); if (itemPrefab != null) { t = typeof(Item); } } } try { MethodInfo loadMethod = t.GetMethod("Load", new[] { typeof(XElement), typeof(Submarine), typeof(IdRemap) }); if (loadMethod == null) { DebugConsole.ThrowError("Could not find the method \"Load\" in " + t + "."); } else if (!loadMethod.ReturnType.IsSubclassOf(typeof(MapEntity))) { DebugConsole.ThrowError("Error loading entity of the type \"" + t.ToString() + "\" - load method does not return a valid map entity."); } else { object newEntity = loadMethod.Invoke(t, new object[] { element, submarine, idRemap }); if (newEntity != null) { entities.Add((MapEntity)newEntity); } } } catch (TargetInvocationException e) { DebugConsole.ThrowError("Error while loading entity of the type " + t + ".", e.InnerException); } catch (Exception e) { DebugConsole.ThrowError("Error while loading entity of the type " + t + ".", e); } } return(entities); }