WIP dockingport/multisub saving in single player mode
This commit is contained in:
@@ -144,7 +144,7 @@
|
|||||||
<Compile Include="Source\Map\Lights\LightSource.cs" />
|
<Compile Include="Source\Map\Lights\LightSource.cs" />
|
||||||
<Compile Include="Source\Map\Map\LocationType.cs" />
|
<Compile Include="Source\Map\Map\LocationType.cs" />
|
||||||
<Compile Include="Source\Map\SubmarineBody.cs" />
|
<Compile Include="Source\Map\SubmarineBody.cs" />
|
||||||
<Compile Include="Source\Map\SubmarineLink.cs" />
|
<Compile Include="Source\Map\LinkedSubmarine.cs" />
|
||||||
<Compile Include="Source\Map\TransitionCinematic.cs" />
|
<Compile Include="Source\Map\TransitionCinematic.cs" />
|
||||||
<Compile Include="Source\Networking\BanList.cs" />
|
<Compile Include="Source\Networking\BanList.cs" />
|
||||||
<Compile Include="Source\Networking\ChatMessage.cs" />
|
<Compile Include="Source\Networking\ChatMessage.cs" />
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
endShiftButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 220, 20, 200, 25), "End shift", Alignment.TopLeft, GUI.Style);
|
endShiftButton = new GUIButton(new Rectangle(GameMain.GraphicsWidth - 220, 20, 200, 25), "End shift", Alignment.TopLeft, GUI.Style);
|
||||||
endShiftButton.Font = GUI.SmallFont;
|
endShiftButton.Font = GUI.SmallFont;
|
||||||
endShiftButton.OnClicked = EndShift;
|
endShiftButton.OnClicked = TryEndShift;
|
||||||
|
|
||||||
for (int i = 0; i < 3; i++)
|
for (int i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
@@ -236,6 +236,39 @@ namespace Barotrauma
|
|||||||
Submarine.Unload();
|
Submarine.Unload();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool TryEndShift(GUIButton button, object obj)
|
||||||
|
{
|
||||||
|
int subsNotDocked = Submarine.Loaded.Count(s => s != Submarine.MainSub && !s.DockedTo.Contains(Submarine.MainSub));
|
||||||
|
|
||||||
|
if (subsNotDocked > 0)
|
||||||
|
{
|
||||||
|
string msg = "";
|
||||||
|
if (subsNotDocked == 1)
|
||||||
|
{
|
||||||
|
msg = "One of of your vessels hasn't been docked to " + Submarine.MainSub.Name
|
||||||
|
+ ". If you leave now, you will permanently lose it."
|
||||||
|
+ " Do you want to leave the vessel behind?";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msg = "Some of of your vessels hasn't been docked to " + Submarine.MainSub.Name
|
||||||
|
+ ". If you leave now, you will permanently lose them."
|
||||||
|
+ " Do you want to leave the vessels behind?";
|
||||||
|
}
|
||||||
|
|
||||||
|
var msgBox = new GUIMessageBox("Warning", msg, new string[] {"Yes", "No"});
|
||||||
|
msgBox.Buttons[0].OnClicked += EndShift;
|
||||||
|
msgBox.Buttons[0].OnClicked += msgBox.Close;
|
||||||
|
msgBox.Buttons[1].OnClicked += msgBox.Close;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
EndShift(button, obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private bool EndShift(GUIButton button, object obj)
|
private bool EndShift(GUIButton button, object obj)
|
||||||
{
|
{
|
||||||
isRunning = false;
|
isRunning = false;
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
class DockingPort : ItemComponent, IDrawableComponent
|
class DockingPort : ItemComponent, IDrawableComponent
|
||||||
{
|
{
|
||||||
private static List<DockingPort> list = new List<DockingPort>();
|
public static List<DockingPort> list = new List<DockingPort>();
|
||||||
|
|
||||||
private Sprite overlaySprite;
|
private Sprite overlaySprite;
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ namespace Barotrauma.Items.Components
|
|||||||
if (adjacentPort != null) Dock(adjacentPort);
|
if (adjacentPort != null) Dock(adjacentPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Dock(DockingPort target)
|
public void Dock(DockingPort target)
|
||||||
{
|
{
|
||||||
if (dockingTarget != null)
|
if (dockingTarget != null)
|
||||||
{
|
{
|
||||||
@@ -133,9 +133,15 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
PlaySound(ActionType.OnUse, item.WorldPosition);
|
PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||||
|
|
||||||
|
item.linkedTo.Add(target.item);
|
||||||
|
|
||||||
|
if (!target.item.Submarine.DockedTo.Contains(item.Submarine)) target.item.Submarine.DockedTo.Add(item.Submarine);
|
||||||
|
if (!item.Submarine.DockedTo.Contains(target.item.Submarine)) item.Submarine.DockedTo.Add(target.item.Submarine);
|
||||||
|
|
||||||
dockingTarget = target;
|
dockingTarget = target;
|
||||||
dockingTarget.dockingTarget = this;
|
dockingTarget.dockingTarget = this;
|
||||||
|
|
||||||
|
docked = true;
|
||||||
dockingTarget.Docked = true;
|
dockingTarget.Docked = true;
|
||||||
|
|
||||||
if (Character.Controlled != null &&
|
if (Character.Controlled != null &&
|
||||||
@@ -296,6 +302,11 @@ namespace Barotrauma.Items.Components
|
|||||||
|
|
||||||
PlaySound(ActionType.OnUse, item.WorldPosition);
|
PlaySound(ActionType.OnUse, item.WorldPosition);
|
||||||
|
|
||||||
|
dockingTarget.item.Submarine.DockedTo.Remove(item.Submarine);
|
||||||
|
item.Submarine.DockedTo.Remove(dockingTarget.item.Submarine);
|
||||||
|
|
||||||
|
item.linkedTo.Clear();
|
||||||
|
|
||||||
docked = false;
|
docked = false;
|
||||||
|
|
||||||
dockingTarget.Undock();
|
dockingTarget.Undock();
|
||||||
@@ -432,6 +443,17 @@ namespace Barotrauma.Items.Components
|
|||||||
list.Remove(this);
|
list.Remove(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void OnMapLoaded()
|
||||||
|
{
|
||||||
|
if (!item.linkedTo.Any()) return;
|
||||||
|
|
||||||
|
Item linkedItem = item.linkedTo.First() as Item;
|
||||||
|
if (linkedItem == null) return;
|
||||||
|
|
||||||
|
DockingPort port = linkedItem.GetComponent<DockingPort>();
|
||||||
|
if (port != null) Dock(port);
|
||||||
|
}
|
||||||
|
|
||||||
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power = 0.0f)
|
public override void ReceiveSignal(int stepsTaken, string signal, Connection connection, Item sender, float power = 0.0f)
|
||||||
{
|
{
|
||||||
switch (connection.Name)
|
switch (connection.Name)
|
||||||
|
|||||||
@@ -0,0 +1,308 @@
|
|||||||
|
using Barotrauma.Items.Components;
|
||||||
|
using Microsoft.Xna.Framework;
|
||||||
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
using Microsoft.Xna.Framework.Input;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
|
namespace Barotrauma
|
||||||
|
{
|
||||||
|
|
||||||
|
class LinkedSubmarinePrefab : MapEntityPrefab
|
||||||
|
{
|
||||||
|
public readonly Submarine mainSub;
|
||||||
|
|
||||||
|
public LinkedSubmarinePrefab(Submarine submarine)
|
||||||
|
{
|
||||||
|
this.mainSub = submarine;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void CreateInstance(Rectangle rect)
|
||||||
|
{
|
||||||
|
System.Diagnostics.Debug.Assert(Submarine.MainSub != null);
|
||||||
|
|
||||||
|
LinkedSubmarine.Create(Submarine.MainSub, mainSub.FilePath, rect.Location.ToVector2());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LinkedSubmarine : MapEntity
|
||||||
|
{
|
||||||
|
private List<Vector2> wallVertices;
|
||||||
|
|
||||||
|
private string filePath;
|
||||||
|
|
||||||
|
private Submarine sub;
|
||||||
|
|
||||||
|
private XElement saveElement;
|
||||||
|
|
||||||
|
public override bool IsLinkable
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinkedSubmarine(Submarine submarine)
|
||||||
|
: base(null, submarine)
|
||||||
|
{
|
||||||
|
linkedTo = new System.Collections.ObjectModel.ObservableCollection<MapEntity>();
|
||||||
|
linkedToID = new List<ushort>();
|
||||||
|
|
||||||
|
InsertToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LinkedSubmarine Create(Submarine mainSub, string filePath, Vector2 position)
|
||||||
|
{
|
||||||
|
LinkedSubmarine sl = new LinkedSubmarine(mainSub);
|
||||||
|
sl.filePath = filePath;
|
||||||
|
|
||||||
|
XDocument doc = Submarine.OpenFile(filePath);
|
||||||
|
if (doc == null || doc.Root == null) return null;
|
||||||
|
|
||||||
|
sl.GenerateWallVertices(doc.Root);
|
||||||
|
|
||||||
|
//for (int i = 0; i < sl.wallVertices.Count; i++)
|
||||||
|
//{
|
||||||
|
// sl.wallVertices[i] = sl.wallVertices[i] += position;
|
||||||
|
//}
|
||||||
|
|
||||||
|
sl.Rect = new Rectangle(
|
||||||
|
(int)sl.wallVertices.Min(v => v.X + position.X),
|
||||||
|
(int)sl.wallVertices.Max(v => v.Y + position.Y),
|
||||||
|
(int)sl.wallVertices.Max(v => v.X + position.X),
|
||||||
|
(int)sl.wallVertices.Min(v => v.Y + position.Y));
|
||||||
|
|
||||||
|
sl.rect = new Rectangle(sl.rect.X, sl.rect.Y, sl.rect.Width - sl.rect.X, sl.rect.Y - sl.rect.Height);
|
||||||
|
|
||||||
|
return sl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool IsMouseOn(Vector2 position)
|
||||||
|
{
|
||||||
|
return Vector2.Distance(position, WorldPosition) < 50.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
|
||||||
|
{
|
||||||
|
if (!editing || wallVertices == null) return;
|
||||||
|
|
||||||
|
Color color = (isHighlighted) ? Color.Orange : Color.Green;
|
||||||
|
if (isSelected) color = Color.Red;
|
||||||
|
|
||||||
|
Vector2 pos = new Vector2(rect.X + rect.Width/2, rect.Y - rect.Height/2);
|
||||||
|
|
||||||
|
for (int i = 0; i < wallVertices.Count; i++)
|
||||||
|
{
|
||||||
|
Vector2 startPos = wallVertices[i] + pos;
|
||||||
|
startPos.Y = -startPos.Y;
|
||||||
|
|
||||||
|
Vector2 endPos = wallVertices[(i + 1) % wallVertices.Count] + pos;
|
||||||
|
endPos.Y = -endPos.Y;
|
||||||
|
|
||||||
|
GUI.DrawLine(spriteBatch,
|
||||||
|
startPos,
|
||||||
|
endPos,
|
||||||
|
color, 0.0f, 5);
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.Y = -pos.Y;
|
||||||
|
GUI.DrawLine(spriteBatch, pos + Vector2.UnitY * 50.0f, pos - Vector2.UnitY * 50.0f, color, 0.0f, 5);
|
||||||
|
GUI.DrawLine(spriteBatch, pos + Vector2.UnitX * 50.0f, pos - Vector2.UnitX * 50.0f, color, 0.0f, 5);
|
||||||
|
|
||||||
|
|
||||||
|
foreach (MapEntity e in linkedTo)
|
||||||
|
{
|
||||||
|
GUI.DrawLine(spriteBatch,
|
||||||
|
new Vector2(WorldPosition.X, -WorldPosition.Y),
|
||||||
|
new Vector2(e.WorldPosition.X, -e.WorldPosition.Y),
|
||||||
|
Color.Red * 0.3f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void DrawEditing(SpriteBatch spriteBatch, Camera cam)
|
||||||
|
{
|
||||||
|
if (editingHUD == null || editingHUD.UserData as LinkedSubmarine != this)
|
||||||
|
{
|
||||||
|
editingHUD = CreateEditingHUD();
|
||||||
|
}
|
||||||
|
|
||||||
|
editingHUD.Draw(spriteBatch);
|
||||||
|
editingHUD.Update((float)Physics.step);
|
||||||
|
|
||||||
|
if (!PlayerInput.LeftButtonClicked() || !PlayerInput.KeyDown(Keys.Space)) return;
|
||||||
|
|
||||||
|
Vector2 position = cam.ScreenToWorld(PlayerInput.MousePosition);
|
||||||
|
|
||||||
|
foreach (MapEntity entity in mapEntityList)
|
||||||
|
{
|
||||||
|
if (entity == this || !entity.IsHighlighted || !(entity is Item) || !entity.IsMouseOn(position)) continue;
|
||||||
|
if (((Item)entity).GetComponent<DockingPort>() == null) continue;
|
||||||
|
if (linkedTo.Contains(entity))
|
||||||
|
{
|
||||||
|
linkedTo.Remove(entity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linkedTo.Add(entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private GUIComponent CreateEditingHUD(bool inGame = false)
|
||||||
|
{
|
||||||
|
int width = 450;
|
||||||
|
int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10;
|
||||||
|
|
||||||
|
editingHUD = new GUIFrame(new Rectangle(x, y, width, 100), GUI.Style);
|
||||||
|
editingHUD.Padding = new Vector4(10, 10, 0, 0);
|
||||||
|
editingHUD.UserData = this;
|
||||||
|
|
||||||
|
new GUITextBlock(new Rectangle(0, 0, 100, 20), "Linked submarine", GUI.Style,
|
||||||
|
Alignment.TopLeft, Alignment.TopLeft, editingHUD, false, GUI.LargeFont);
|
||||||
|
|
||||||
|
y += 20;
|
||||||
|
|
||||||
|
if (!inGame)
|
||||||
|
{
|
||||||
|
new GUITextBlock(new Rectangle(0, 0, 0, 20), "Hold space to link to a docking port",
|
||||||
|
GUI.Style, Alignment.TopRight, Alignment.TopRight, editingHUD).Font = GUI.SmallFont;
|
||||||
|
y += 25;
|
||||||
|
|
||||||
|
}
|
||||||
|
return editingHUD;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void GenerateWallVertices(XElement rootElement)
|
||||||
|
{
|
||||||
|
List<Vector2> points = new List<Vector2>();
|
||||||
|
|
||||||
|
var wallPrefabs =
|
||||||
|
MapEntityPrefab.list.FindAll(mp => (mp is StructurePrefab) && ((StructurePrefab)mp).HasBody);
|
||||||
|
|
||||||
|
foreach (XElement element in rootElement.Elements())
|
||||||
|
{
|
||||||
|
if (element.Name != "Structure") continue;
|
||||||
|
|
||||||
|
string name = ToolBox.GetAttributeString(element, "name", "");
|
||||||
|
if (!wallPrefabs.Any(wp => wp.Name == name)) continue;
|
||||||
|
|
||||||
|
var rect = ToolBox.GetAttributeVector4(element, "rect", Vector4.Zero);
|
||||||
|
|
||||||
|
points.Add(new Vector2(rect.X, rect.Y));
|
||||||
|
points.Add(new Vector2(rect.X + rect.Z, rect.Y));
|
||||||
|
points.Add(new Vector2(rect.X, rect.Y - rect.W));
|
||||||
|
points.Add(new Vector2(rect.X + rect.Z, rect.Y - rect.W));
|
||||||
|
}
|
||||||
|
|
||||||
|
wallVertices = MathUtils.GiftWrap(points);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override XElement Save(XElement parentElement)
|
||||||
|
{
|
||||||
|
XElement saveElement = null;
|
||||||
|
|
||||||
|
if (sub == null)
|
||||||
|
{
|
||||||
|
var doc = Submarine.OpenFile(filePath);
|
||||||
|
saveElement = doc.Root;
|
||||||
|
|
||||||
|
saveElement.Name = "LinkedSubmarine";
|
||||||
|
|
||||||
|
saveElement.Add(new XAttribute("filepath", filePath));
|
||||||
|
|
||||||
|
var linkedPort = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent<DockingPort>() != null);
|
||||||
|
if (linkedPort != null)
|
||||||
|
{
|
||||||
|
saveElement.Add(new XAttribute("linkedto", linkedPort.ID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
saveElement = new XElement("LinkedSubmarine");
|
||||||
|
|
||||||
|
sub.SaveToXElement(saveElement);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveElement.Add(new XAttribute("pos", ToolBox.Vector2ToString(Position - Submarine.HiddenSubPosition)));
|
||||||
|
|
||||||
|
parentElement.Add(saveElement);
|
||||||
|
|
||||||
|
return saveElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Load(XElement element, Submarine submarine)
|
||||||
|
{
|
||||||
|
Vector2 pos = ToolBox.GetAttributeVector2(element, "pos", Vector2.Zero);
|
||||||
|
|
||||||
|
LinkedSubmarine linkedSub = null;
|
||||||
|
|
||||||
|
if (Screen.Selected == GameMain.EditMapScreen)
|
||||||
|
{
|
||||||
|
string filePath = ToolBox.GetAttributeString(element, "filepath", "");
|
||||||
|
|
||||||
|
linkedSub = Create(submarine, filePath, pos);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
linkedSub = new LinkedSubmarine(submarine);
|
||||||
|
linkedSub.saveElement = element;
|
||||||
|
|
||||||
|
linkedSub.rect.Location = pos.ToPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
string linkedToString = ToolBox.GetAttributeString(element, "linkedto", "");
|
||||||
|
if (linkedToString != "")
|
||||||
|
{
|
||||||
|
string[] linkedToIds = linkedToString.Split(',');
|
||||||
|
for (int i = 0; i < linkedToIds.Length; i++)
|
||||||
|
{
|
||||||
|
linkedSub.linkedToID.Add((ushort)int.Parse(linkedToIds[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnMapLoaded()
|
||||||
|
{
|
||||||
|
if (saveElement == null) return;
|
||||||
|
|
||||||
|
sub = Submarine.Load(saveElement, false);
|
||||||
|
sub.SetPosition(WorldPosition - Submarine.WorldPosition);
|
||||||
|
sub.Submarine = Submarine;
|
||||||
|
|
||||||
|
var linkedItem = linkedTo.FirstOrDefault(lt => (lt is Item) && ((Item)lt).GetComponent<DockingPort>() != null);
|
||||||
|
|
||||||
|
if (linkedItem != null)
|
||||||
|
{
|
||||||
|
var linkedPort = ((Item)linkedItem).GetComponent<DockingPort>();
|
||||||
|
|
||||||
|
DockingPort 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)
|
||||||
|
{
|
||||||
|
myPort.Dock(linkedPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -620,7 +620,6 @@ namespace Barotrauma
|
|||||||
foreach (ushort i in e.linkedToID)
|
foreach (ushort i in e.linkedToID)
|
||||||
{
|
{
|
||||||
MapEntity linked = FindEntityByID(i) as MapEntity;
|
MapEntity linked = FindEntityByID(i) as MapEntity;
|
||||||
Debug.Assert(linked.Submarine == sub);
|
|
||||||
|
|
||||||
if (linked != null) e.linkedTo.Add(linked);
|
if (linked != null) e.linkedTo.Add(linked);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,10 +46,12 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private SubmarineBody subBody;
|
private SubmarineBody subBody;
|
||||||
|
|
||||||
|
public readonly List<Submarine> DockedTo;
|
||||||
|
|
||||||
private static Vector2 lastPickedPosition;
|
private static Vector2 lastPickedPosition;
|
||||||
private static float lastPickedFraction;
|
private static float lastPickedFraction;
|
||||||
|
|
||||||
Md5Hash hash;
|
private Md5Hash hash;
|
||||||
|
|
||||||
private string filePath;
|
private string filePath;
|
||||||
private string name;
|
private string name;
|
||||||
@@ -58,7 +60,6 @@ namespace Barotrauma
|
|||||||
|
|
||||||
private float lastNetworkUpdate;
|
private float lastNetworkUpdate;
|
||||||
|
|
||||||
|
|
||||||
//properties ----------------------------------------------------
|
//properties ----------------------------------------------------
|
||||||
|
|
||||||
public string Name
|
public string Name
|
||||||
@@ -231,6 +232,8 @@ namespace Barotrauma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DockedTo = new List<Submarine>();
|
||||||
|
|
||||||
|
|
||||||
ID = ushort.MaxValue;
|
ID = ushort.MaxValue;
|
||||||
base.Remove();
|
base.Remove();
|
||||||
@@ -538,14 +541,7 @@ namespace Barotrauma
|
|||||||
name = System.IO.Path.GetFileNameWithoutExtension(filePath);
|
name = System.IO.Path.GetFileNameWithoutExtension(filePath);
|
||||||
|
|
||||||
XDocument doc = new XDocument(new XElement("Submarine"));
|
XDocument doc = new XDocument(new XElement("Submarine"));
|
||||||
doc.Root.Add(new XAttribute("name", name));
|
SaveToXElement(doc.Root);
|
||||||
doc.Root.Add(new XAttribute("description", Description == null ? "" : Description));
|
|
||||||
|
|
||||||
foreach (MapEntity e in MapEntity.mapEntityList)
|
|
||||||
{
|
|
||||||
if (e.MoveWithLevel ||e.Submarine != this) continue;
|
|
||||||
e.Save(doc.Root);
|
|
||||||
}
|
|
||||||
|
|
||||||
hash = new Md5Hash(doc);
|
hash = new Md5Hash(doc);
|
||||||
doc.Root.Add(new XAttribute("md5hash", hash.Hash));
|
doc.Root.Add(new XAttribute("md5hash", hash.Hash));
|
||||||
@@ -563,6 +559,18 @@ namespace Barotrauma
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SaveToXElement(XElement element)
|
||||||
|
{
|
||||||
|
element.Add(new XAttribute("name", name));
|
||||||
|
element.Add(new XAttribute("description", Description == null ? "" : Description));
|
||||||
|
|
||||||
|
foreach (MapEntity e in MapEntity.mapEntityList)
|
||||||
|
{
|
||||||
|
if (e.MoveWithLevel || e.Submarine != this) continue;
|
||||||
|
e.Save(element);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static bool SaveCurrent(string filePath)
|
public static bool SaveCurrent(string filePath)
|
||||||
{
|
{
|
||||||
if (Submarine.MainSub == null)
|
if (Submarine.MainSub == null)
|
||||||
@@ -853,7 +861,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
GameMain.LightManager.OnMapLoaded();
|
GameMain.LightManager.OnMapLoaded();
|
||||||
|
|
||||||
ID = (ushort)(ushort.MaxValue - Submarine.loaded.Count);
|
ID = (ushort)(ushort.MaxValue - Submarine.loaded.IndexOf(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Submarine Load(XElement element, bool unloadPrevious)
|
public static Submarine Load(XElement element, bool unloadPrevious)
|
||||||
@@ -862,7 +870,7 @@ namespace Barotrauma
|
|||||||
|
|
||||||
//tryload -> false
|
//tryload -> false
|
||||||
|
|
||||||
Submarine sub = new Submarine(ToolBox.GetAttributeString(element, "name", ""));
|
Submarine sub = new Submarine(ToolBox.GetAttributeString(element, "name", ""), "", false);
|
||||||
sub.Load(unloadPrevious, element);
|
sub.Load(unloadPrevious, element);
|
||||||
|
|
||||||
return sub;
|
return sub;
|
||||||
@@ -898,20 +906,14 @@ namespace Barotrauma
|
|||||||
foreach (Submarine sub in loaded)
|
foreach (Submarine sub in loaded)
|
||||||
{
|
{
|
||||||
sub.Remove();
|
sub.Remove();
|
||||||
sub.Clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded.Clear();
|
loaded.Clear();
|
||||||
}
|
|
||||||
|
|
||||||
private void Clear()
|
|
||||||
{
|
|
||||||
if (GameMain.GameScreen.Cam != null) GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
if (GameMain.GameScreen.Cam != null) GameMain.GameScreen.Cam.TargetPos = Vector2.Zero;
|
||||||
|
|
||||||
Entity.RemoveAll();
|
Entity.RemoveAll();
|
||||||
|
|
||||||
subBody = null;
|
|
||||||
|
|
||||||
PhysicsBody.list.Clear();
|
PhysicsBody.list.Clear();
|
||||||
|
|
||||||
Ragdoll.list.Clear();
|
Ragdoll.list.Clear();
|
||||||
@@ -919,6 +921,14 @@ namespace Barotrauma
|
|||||||
GameMain.World.Clear();
|
GameMain.World.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Remove()
|
||||||
|
{
|
||||||
|
base.Remove();
|
||||||
|
|
||||||
|
subBody = null;
|
||||||
|
|
||||||
|
DockedTo.Clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,171 +0,0 @@
|
|||||||
using Microsoft.Xna.Framework;
|
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System.Xml.Linq;
|
|
||||||
|
|
||||||
namespace Barotrauma
|
|
||||||
{
|
|
||||||
|
|
||||||
class LinkedSubmarinePrefab : MapEntityPrefab
|
|
||||||
{
|
|
||||||
public readonly Submarine mainSub;
|
|
||||||
|
|
||||||
public LinkedSubmarinePrefab(Submarine submarine)
|
|
||||||
{
|
|
||||||
this.mainSub = submarine;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void CreateInstance(Rectangle rect)
|
|
||||||
{
|
|
||||||
System.Diagnostics.Debug.Assert(Submarine.MainSub != null);
|
|
||||||
|
|
||||||
LinkedSubmarine.Create(Submarine.MainSub, mainSub.FilePath, rect.Location.ToVector2());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LinkedSubmarine : MapEntity
|
|
||||||
{
|
|
||||||
private List<Vector2> wallVertices;
|
|
||||||
|
|
||||||
private string filePath;
|
|
||||||
|
|
||||||
private XElement saveElement;
|
|
||||||
|
|
||||||
public LinkedSubmarine(Submarine submarine)
|
|
||||||
: base(null, submarine)
|
|
||||||
{
|
|
||||||
InsertToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LinkedSubmarine Create(Submarine mainSub, string filePath, Vector2 position)
|
|
||||||
{
|
|
||||||
LinkedSubmarine sl = new LinkedSubmarine(mainSub);
|
|
||||||
sl.filePath = filePath;
|
|
||||||
|
|
||||||
XDocument doc = Submarine.OpenFile(filePath);
|
|
||||||
if (doc == null || doc.Root == null) return null;
|
|
||||||
|
|
||||||
sl.GenerateWallVertices(doc.Root);
|
|
||||||
|
|
||||||
//for (int i = 0; i < sl.wallVertices.Count; i++)
|
|
||||||
//{
|
|
||||||
// sl.wallVertices[i] = sl.wallVertices[i] += position;
|
|
||||||
//}
|
|
||||||
|
|
||||||
sl.Rect = new Rectangle(
|
|
||||||
(int)sl.wallVertices.Min(v => v.X + position.X),
|
|
||||||
(int)sl.wallVertices.Max(v => v.Y + position.Y),
|
|
||||||
(int)sl.wallVertices.Max(v => v.X + position.X),
|
|
||||||
(int)sl.wallVertices.Min(v => v.Y + position.Y));
|
|
||||||
|
|
||||||
sl.rect = new Rectangle(sl.rect.X, sl.rect.Y, sl.rect.Width - sl.rect.X, sl.rect.Y - sl.rect.Height);
|
|
||||||
|
|
||||||
return sl;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override bool IsMouseOn(Vector2 position)
|
|
||||||
{
|
|
||||||
return Vector2.Distance(position, WorldPosition) < 50.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Draw(SpriteBatch spriteBatch, bool editing, bool back = true)
|
|
||||||
{
|
|
||||||
if (!editing || wallVertices == null) return;
|
|
||||||
|
|
||||||
Color color = (isHighlighted) ? Color.Orange : Color.Green;
|
|
||||||
if (isSelected) color = Color.Red;
|
|
||||||
|
|
||||||
Vector2 pos = new Vector2(rect.X + rect.Width/2, rect.Y - rect.Height/2);
|
|
||||||
|
|
||||||
for (int i = 0; i < wallVertices.Count; i++)
|
|
||||||
{
|
|
||||||
Vector2 startPos = wallVertices[i] + pos;
|
|
||||||
startPos.Y = -startPos.Y;
|
|
||||||
|
|
||||||
Vector2 endPos = wallVertices[(i + 1) % wallVertices.Count] + pos;
|
|
||||||
endPos.Y = -endPos.Y;
|
|
||||||
|
|
||||||
GUI.DrawLine(spriteBatch,
|
|
||||||
startPos,
|
|
||||||
endPos,
|
|
||||||
color, 0.0f, 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
pos.Y = -pos.Y;
|
|
||||||
GUI.DrawLine(spriteBatch, pos + Vector2.UnitY * 50.0f, pos - Vector2.UnitY * 50.0f, color, 0.0f, 5);
|
|
||||||
GUI.DrawLine(spriteBatch, pos + Vector2.UnitX * 50.0f, pos - Vector2.UnitX * 50.0f, color, 0.0f, 5);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GenerateWallVertices(XElement rootElement)
|
|
||||||
{
|
|
||||||
List<Vector2> points = new List<Vector2>();
|
|
||||||
|
|
||||||
var wallPrefabs =
|
|
||||||
MapEntityPrefab.list.FindAll(mp => (mp is StructurePrefab) && ((StructurePrefab)mp).HasBody);
|
|
||||||
|
|
||||||
foreach (XElement element in rootElement.Elements())
|
|
||||||
{
|
|
||||||
if (element.Name != "Structure") continue;
|
|
||||||
|
|
||||||
string name = ToolBox.GetAttributeString(element, "name", "");
|
|
||||||
if (!wallPrefabs.Any(wp => wp.Name == name)) continue;
|
|
||||||
|
|
||||||
var rect = ToolBox.GetAttributeVector4(element, "rect", Vector4.Zero);
|
|
||||||
|
|
||||||
points.Add(new Vector2(rect.X, rect.Y));
|
|
||||||
points.Add(new Vector2(rect.X + rect.Z, rect.Y));
|
|
||||||
points.Add(new Vector2(rect.X, rect.Y - rect.W));
|
|
||||||
points.Add(new Vector2(rect.X + rect.Z, rect.Y - rect.W));
|
|
||||||
}
|
|
||||||
|
|
||||||
wallVertices = MathUtils.GiftWrap(points);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override XElement Save(XElement parentElement)
|
|
||||||
{
|
|
||||||
var doc = Submarine.OpenFile(filePath);
|
|
||||||
|
|
||||||
doc.Root.Name = "LinkedSubmarine";
|
|
||||||
|
|
||||||
doc.Root.Add(
|
|
||||||
new XAttribute("filepath", filePath),
|
|
||||||
new XAttribute("pos", ToolBox.Vector2ToString(Position - Submarine.HiddenSubPosition)));
|
|
||||||
|
|
||||||
parentElement.Add(doc.Root);
|
|
||||||
|
|
||||||
return doc.Root;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Load(XElement element, Submarine submarine)
|
|
||||||
{
|
|
||||||
Vector2 pos = ToolBox.GetAttributeVector2(element, "pos", Vector2.Zero);
|
|
||||||
|
|
||||||
if (Screen.Selected == GameMain.EditMapScreen)
|
|
||||||
{
|
|
||||||
string filePath = ToolBox.GetAttributeString(element, "filepath", "");
|
|
||||||
|
|
||||||
Create(submarine, filePath, pos);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var ls = new LinkedSubmarine(submarine);
|
|
||||||
ls.saveElement = element;
|
|
||||||
|
|
||||||
ls.rect.Location = pos.ToPoint();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnMapLoaded()
|
|
||||||
{
|
|
||||||
if (saveElement == null) return;
|
|
||||||
var sub = Submarine.Load(saveElement, false);
|
|
||||||
sub.SetPosition(WorldPosition - Submarine.WorldPosition);
|
|
||||||
sub.Submarine = Submarine;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -23,10 +23,11 @@ namespace Barotrauma
|
|||||||
|
|
||||||
string tempPath = Path.Combine(SaveFolder, "temp");
|
string tempPath = Path.Combine(SaveFolder, "temp");
|
||||||
|
|
||||||
if (!Directory.Exists(tempPath))
|
if (Directory.Exists(tempPath))
|
||||||
{
|
{
|
||||||
Directory.CreateDirectory(tempPath);
|
Directory.Delete(tempPath, true);
|
||||||
}
|
}
|
||||||
|
Directory.CreateDirectory(tempPath);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user