182 lines
7.4 KiB
C#
182 lines
7.4 KiB
C#
using Barotrauma.Items.Components;
|
|
using Microsoft.Xna.Framework;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using Barotrauma.IO;
|
|
using System.Linq;
|
|
using System.Xml.Linq;
|
|
using System.Collections.Immutable;
|
|
using System.Net;
|
|
|
|
namespace Barotrauma
|
|
{
|
|
partial class ItemAssemblyPrefab : MapEntityPrefab
|
|
{
|
|
public static readonly PrefabCollection<ItemAssemblyPrefab> Prefabs = new PrefabCollection<ItemAssemblyPrefab>();
|
|
|
|
public static readonly string VanillaSaveFolder = Path.Combine("Content", "Items", "Assemblies");
|
|
public static readonly string SaveFolder = "ItemAssemblies";
|
|
|
|
private readonly XElement configElement;
|
|
|
|
public readonly ImmutableArray<(Identifier Identifier, Rectangle Rect)> DisplayEntities;
|
|
|
|
public readonly Rectangle Bounds;
|
|
|
|
public override LocalizedString Name { get; }
|
|
|
|
public override Sprite Sprite => null;
|
|
|
|
public override string OriginalName => Name.Value;
|
|
|
|
public override ImmutableHashSet<Identifier> Tags { get; }
|
|
|
|
public override ImmutableHashSet<Identifier> AllowedLinks => null;
|
|
|
|
public override MapEntityCategory Category => MapEntityCategory.ItemAssembly;
|
|
|
|
public override ImmutableHashSet<string> Aliases => null;
|
|
|
|
protected override Identifier DetermineIdentifier(XElement element)
|
|
{
|
|
return element.GetAttributeIdentifier("identifier", element.GetAttributeIdentifier("name", ""));
|
|
}
|
|
|
|
public ItemAssemblyPrefab(ContentXElement element, ItemAssemblyFile file) : base(element, file)
|
|
{
|
|
configElement = element;
|
|
|
|
SerializableProperty.DeserializeProperties(this, configElement);
|
|
|
|
Name = TextManager.Get($"EntityName.{Identifier}").Fallback(element.GetAttributeString("name", ""));
|
|
Description = TextManager.Get($"EntityDescription.{Identifier}");
|
|
Tags = Enumerable.Empty<Identifier>().ToImmutableHashSet();
|
|
|
|
List<ushort> containedItemIDs = new List<ushort>();
|
|
foreach (XElement entityElement in element.Elements())
|
|
{
|
|
var containerElement = entityElement.GetChildElement("itemcontainer");
|
|
if (containerElement == null) { continue; }
|
|
|
|
string containedString = containerElement.GetAttributeString("contained", "");
|
|
string[] itemIdStrings = containedString.Split(',');
|
|
var itemIds = new List<ushort>[itemIdStrings.Length];
|
|
for (int i = 0; i < itemIdStrings.Length; i++)
|
|
{
|
|
itemIds[i] ??= new List<ushort>();
|
|
foreach (string idStr in itemIdStrings[i].Split(';'))
|
|
{
|
|
if (int.TryParse(idStr, out int id))
|
|
{
|
|
itemIds[i].Add((ushort)id);
|
|
containedItemIDs.Add((ushort)id);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int minX = int.MaxValue, minY = int.MaxValue;
|
|
int maxX = int.MinValue, maxY = int.MinValue;
|
|
var displayEntities = new List<(Identifier, Rectangle)>();
|
|
foreach (XElement entityElement in element.Elements())
|
|
{
|
|
ushort id = (ushort)entityElement.GetAttributeInt("ID", 0);
|
|
if (id > 0 && containedItemIDs.Contains(id)) { continue; }
|
|
|
|
Identifier identifier = entityElement.GetAttributeIdentifier("identifier", entityElement.Name.ToString().ToLowerInvariant());
|
|
|
|
Rectangle rect = entityElement.GetAttributeRect("rect", Rectangle.Empty);
|
|
if (!entityElement.Elements().Any(e => e.Name.LocalName.Equals("wire", StringComparison.OrdinalIgnoreCase)))
|
|
{
|
|
if (!entityElement.GetAttributeBool("hideinassemblypreview", false)) { displayEntities.Add((identifier, rect)); }
|
|
minX = Math.Min(minX, rect.X);
|
|
minY = Math.Min(minY, rect.Y - rect.Height);
|
|
maxX = Math.Max(maxX, rect.Right);
|
|
maxY = Math.Max(maxY, rect.Y);
|
|
}
|
|
}
|
|
DisplayEntities = displayEntities.ToImmutableArray();
|
|
|
|
Bounds = minX == int.MaxValue ?
|
|
new Rectangle(0, 0, 1, 1) :
|
|
new Rectangle(minX, minY, maxX - minX, maxY - minY);
|
|
}
|
|
|
|
protected override void CreateInstance(Rectangle rect)
|
|
{
|
|
#if CLIENT
|
|
var loaded = CreateInstance(rect.Location.ToVector2(), Submarine.MainSub, selectInstance: Screen.Selected == GameMain.SubEditorScreen);
|
|
if (Screen.Selected is SubEditorScreen && loaded.Any())
|
|
{
|
|
SubEditorScreen.StoreCommand(new AddOrDeleteCommand(loaded, false, handleInventoryBehavior: false));
|
|
}
|
|
#else
|
|
var loaded = CreateInstance(rect.Location.ToVector2(), Submarine.MainSub);
|
|
#endif
|
|
}
|
|
|
|
public List<MapEntity> CreateInstance(Vector2 position, Submarine sub, bool selectInstance = false)
|
|
{
|
|
return PasteEntities(position, sub, configElement, ContentFile.Path.Value, selectInstance);
|
|
}
|
|
|
|
public static List<MapEntity> PasteEntities(Vector2 position, Submarine sub, XElement configElement, string filePath = null, bool selectInstance = false)
|
|
{
|
|
int idOffset = Entity.FindFreeIdBlock(configElement.Elements().Count());
|
|
List<MapEntity> entities = MapEntity.LoadAll(sub, configElement, filePath, idOffset);
|
|
if (entities.Count == 0) { return entities; }
|
|
|
|
Vector2 offset = sub?.HiddenSubPosition ?? Vector2.Zero;
|
|
|
|
foreach (MapEntity me in entities)
|
|
{
|
|
me.Move(position);
|
|
me.Submarine = sub;
|
|
if (!(me is Item item)) { continue; }
|
|
Wire wire = item.GetComponent<Wire>();
|
|
//Vector2 subPosition = Submarine == null ? Vector2.Zero : Submarine.HiddenSubPosition;
|
|
if (wire != null)
|
|
{
|
|
//fix wires that have been erroneously saved at the "hidden position"
|
|
if (sub != null && Vector2.Distance(me.Position, sub.HiddenSubPosition) > sub.HiddenSubPosition.Length() / 2)
|
|
{
|
|
me.Move(position);
|
|
}
|
|
wire.MoveNodes(position - offset);
|
|
}
|
|
}
|
|
|
|
MapEntity.MapLoaded(entities, true);
|
|
#if CLIENT
|
|
if (Screen.Selected == GameMain.SubEditorScreen && selectInstance)
|
|
{
|
|
MapEntity.SelectedList.Clear();
|
|
entities.ForEach(MapEntity.AddSelection);
|
|
}
|
|
#endif
|
|
return entities;
|
|
}
|
|
|
|
public void Delete()
|
|
{
|
|
Dispose();
|
|
try
|
|
{
|
|
if (ContentPackage is { Files: { Length: 1 } }
|
|
&& ContentPackageManager.LocalPackages.Contains(ContentPackage))
|
|
{
|
|
Directory.Delete(ContentPackage.Dir, recursive: true);
|
|
ContentPackageManager.LocalPackages.Refresh();
|
|
ContentPackageManager.EnabledPackages.DisableRemovedMods();
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
DebugConsole.ThrowError("Deleting item assembly \"" + Name + "\" failed.", e);
|
|
}
|
|
}
|
|
|
|
public override void Dispose() { }
|
|
}
|
|
}
|