Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaShared/SharedSource/Map/ItemAssemblyPrefab.cs
Juan Pablo Arce 4206f6db42 Unstable 0.17.3.0
2022-03-22 14:44:56 -03:00

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() { }
}
}