- Renamed a bunch of ObjectProperty-related stuff (ObjectProperty -> SerializableProperty, IPropertyObject -> ISerializableEntity, the "SerializableProperty" attribute -> Serialize).

- Rectangle serialization.
- Option to restrict numeric properties to a range of values.
- WIP generic ISerializableEntity editor.
This commit is contained in:
Joonas Rikkonen
2017-11-08 21:15:03 +02:00
parent a0d606ef5f
commit 8e556f1c76
60 changed files with 1035 additions and 678 deletions
@@ -206,6 +206,7 @@
<Compile Include="Source\Screens\NetLobbyScreen.cs" /> <Compile Include="Source\Screens\NetLobbyScreen.cs" />
<Compile Include="Source\Screens\Screen.cs" /> <Compile Include="Source\Screens\Screen.cs" />
<Compile Include="Source\Screens\ServerListScreen.cs" /> <Compile Include="Source\Screens\ServerListScreen.cs" />
<Compile Include="Source\Serialization\SerializableEntityEditor.cs" />
<Compile Include="Source\Sounds\OggSound.cs" /> <Compile Include="Source\Sounds\OggSound.cs" />
<Compile Include="Source\Sounds\OggStream.cs" /> <Compile Include="Source\Sounds\OggStream.cs" />
<Compile Include="Source\Sounds\Sound.cs" /> <Compile Include="Source\Sounds\Sound.cs" />
@@ -299,6 +300,7 @@
<None Include="OpenTK.dll.config" /> <None Include="OpenTK.dll.config" />
<None Include="packages.config" /> <None Include="packages.config" />
</ItemGroup> </ItemGroup>
<ItemGroup />
<Import Project="..\BarotraumaShared\BarotraumaShared.projitems" Label="Shared" /> <Import Project="..\BarotraumaShared\BarotraumaShared.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
@@ -11,7 +11,7 @@ using System.Xml.Linq;
namespace Barotrauma namespace Barotrauma
{ {
partial class Character : Entity, IDamageable, IPropertyObject, IClientSerializable, IServerSerializable partial class Character : Entity, IDamageable, ISerializableEntity, IClientSerializable, IServerSerializable
{ {
protected float soundTimer; protected float soundTimer;
protected float soundInterval; protected float soundInterval;
@@ -59,7 +59,7 @@ namespace Barotrauma
public static GUIComponent UpdateMouseOn() public static GUIComponent UpdateMouseOn()
{ {
MouseOn = null; MouseOn = null;
for (int i=ComponentsToUpdate.Count-1;i>=0;i--) for (int i = ComponentsToUpdate.Count - 1; i >= 0; i--)
{ {
GUIComponent c = ComponentsToUpdate[i]; GUIComponent c = ComponentsToUpdate[i];
if (c.MouseRect.Contains(PlayerInput.MousePosition)) if (c.MouseRect.Contains(PlayerInput.MousePosition))
@@ -149,7 +149,9 @@ namespace Barotrauma
rect = value; rect = value;
if (prevX == rect.X && prevY == rect.Y && rect.Width == prevWidth && rect.Height == prevHeight) return; if (prevX == rect.X && prevY == rect.Y && rect.Width == prevWidth && rect.Height == prevHeight) return;
//TODO: fix this (or replace with something better in the new GUI system)
//simply expanding the rects by the same amount as their parent only works correctly in some special cases
foreach (GUIComponent child in children) foreach (GUIComponent child in children)
{ {
child.Rect = new Rectangle( child.Rect = new Rectangle(
@@ -166,9 +168,7 @@ namespace Barotrauma
get { return CanBeFocused ? rect : Rectangle.Empty; } get { return CanBeFocused ? rect : Rectangle.Empty; }
} }
public Dictionary<GUIComponent.ComponentState, List<UISprite>> sprites; public Dictionary<ComponentState, List<UISprite>> sprites;
//public Alignment SpriteAlignment { get; set; }
//public bool RepeatSpriteX, RepeatSpriteY;
public virtual Color OutlineColor { get; set; } public virtual Color OutlineColor { get; set; }
@@ -271,15 +271,44 @@ namespace Barotrauma
return false; return false;
} }
protected virtual void SetAlpha(float a)
{
color = new Color(color.R / 255.0f, color.G / 255.0f, color.B / 255.0f, a);
}
public virtual void Flash(Color? color = null) public virtual void Flash(Color? color = null)
{ {
flashTimer = FlashDuration; flashTimer = FlashDuration;
flashColor = (color == null) ? Color.Red * 0.8f : (Color)color; flashColor = (color == null) ? Color.Red * 0.8f : (Color)color;
}
//foreach (GUIComponent child in children) public void FadeOut(float duration, bool removeAfter)
//{ {
// child.Flash(); CoroutineManager.StartCoroutine(LerpAlpha(0.0f, duration, removeAfter));
//} }
private IEnumerable<object> LerpAlpha(float to, float duration, bool removeAfter)
{
float t = 0.0f;
float startA = color.A;
while (t < duration)
{
t += CoroutineManager.DeltaTime;
SetAlpha(MathHelper.Lerp(startA, to, t / duration));
yield return CoroutineStatus.Running;
}
SetAlpha(to);
if (removeAfter && parent != null)
{
parent.RemoveChild(this);
}
yield return CoroutineStatus.Success;
} }
public virtual void Draw(SpriteBatch spriteBatch) public virtual void Draw(SpriteBatch spriteBatch)
@@ -431,13 +460,34 @@ namespace Barotrauma
} }
} }
public void SetDimensions(Point size, bool expandChildren = false)
{
Point expandAmount = size - rect.Size;
rect = new Rectangle(rect.X, rect.Y, size.X, size.Y);
if (expandChildren)
{
//TODO: fix this (or replace with something better in the new GUI system)
//simply expanding the rects by the same amount as their parent only works correctly in some special cases
foreach (GUIComponent child in children)
{
child.Rect = new Rectangle(
child.rect.X,
child.rect.Y,
child.rect.Width + expandAmount.X,
child.rect.Height + expandAmount.Y);
}
}
}
protected virtual void UpdateDimensions(GUIComponent parent = null) protected virtual void UpdateDimensions(GUIComponent parent = null)
{ {
Rectangle parentRect = (parent==null) ? new Rectangle(0,0,GameMain.GraphicsWidth, GameMain.GraphicsHeight) : parent.rect; Rectangle parentRect = (parent == null) ? new Rectangle(0, 0, GameMain.GraphicsWidth, GameMain.GraphicsHeight) : parent.rect;
Vector4 padding = (parent == null) ? Vector4.Zero : parent.padding; Vector4 padding = (parent == null) ? Vector4.Zero : parent.padding;
if (rect.Width == 0) rect.Width = parentRect.Width - rect.X if (rect.Width == 0) rect.Width = parentRect.Width - rect.X
- (int)padding.X - (int)padding.Z; - (int)padding.X - (int)padding.Z;
if (rect.Height == 0) rect.Height = parentRect.Height - rect.Y if (rect.Height == 0) rect.Height = parentRect.Height - rect.Y
@@ -445,7 +495,7 @@ namespace Barotrauma
if (alignment.HasFlag(Alignment.CenterX)) if (alignment.HasFlag(Alignment.CenterX))
{ {
rect.X += parentRect.X + (int)parentRect.Width/2 - (int)rect.Width/2; rect.X += parentRect.X + (int)parentRect.Width / 2 - (int)rect.Width / 2;
} }
else if (alignment.HasFlag(Alignment.Right)) else if (alignment.HasFlag(Alignment.Right))
{ {
@@ -72,15 +72,20 @@ namespace Barotrauma
} }
public GUIDropDown(Rectangle rect, string text, string style, GUIComponent parent = null) public GUIDropDown(Rectangle rect, string text, string style, GUIComponent parent = null)
: this(rect, text, style, Alignment.TopLeft, parent)
{
}
public GUIDropDown(Rectangle rect, string text, string style, Alignment alignment, GUIComponent parent = null)
: base(style) : base(style)
{ {
this.rect = rect; this.rect = rect;
if (parent != null) parent.AddChild(this); if (parent != null) parent.AddChild(this);
button = new GUIButton(this.rect, text, Color.White, Alignment.TopLeft, Alignment.CenterLeft, "GUIDropDown", null); button = new GUIButton(this.rect, text, Color.White, alignment, Alignment.CenterLeft, "GUIDropDown", null);
GUI.Style.Apply(button, style, this); GUI.Style.Apply(button, style, this);
button.OnClicked = OnClicked; button.OnClicked = OnClicked;
listBox = new GUIListBox(new Rectangle(this.rect.X, this.rect.Bottom, this.rect.Width, 200), style, null); listBox = new GUIListBox(new Rectangle(this.rect.X, this.rect.Bottom, this.rect.Width, 200), style, null);
@@ -33,7 +33,7 @@ namespace Barotrauma.Items.Components
} }
} }
partial class ItemComponent : IPropertyObject partial class ItemComponent : ISerializableEntity
{ {
private Dictionary<ActionType, List<ItemSound>> sounds; private Dictionary<ActionType, List<ItemSound>> sounds;
@@ -109,13 +109,13 @@ namespace Barotrauma.Items.Components
if (sound == null) return 0.0f; if (sound == null) return 0.0f;
if (sound.VolumeProperty == "") return 1.0f; if (sound.VolumeProperty == "") return 1.0f;
ObjectProperty op = null; SerializableProperty property = null;
if (properties.TryGetValue(sound.VolumeProperty.ToLowerInvariant(), out op)) if (properties.TryGetValue(sound.VolumeProperty.ToLowerInvariant(), out property))
{ {
float newVolume = 0.0f; float newVolume = 0.0f;
try try
{ {
newVolume = (float)op.GetValue(); newVolume = (float)property.GetValue();
} }
catch catch
{ {
@@ -128,12 +128,7 @@ namespace Barotrauma.Items.Components
return 0.0f; return 0.0f;
} }
//public virtual void Draw(SpriteBatch spriteBatch, bool editing = false)
//{
// item.drawableComponents = Array.FindAll(item.drawableComponents, i => i != this);
//}
public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { } public virtual void DrawHUD(SpriteBatch spriteBatch, Character character) { }
public virtual void AddToGUIUpdateList() { } public virtual void AddToGUIUpdateList() { }
@@ -10,7 +10,7 @@ namespace Barotrauma.Items.Components
private Color textColor; private Color textColor;
[SerializableProperty("", true), Editable(100)] [Serialize("", true), Editable(100)]
public string Text public string Text
{ {
get { return textBlock.Text.Replace("\n", ""); } get { return textBlock.Text.Replace("\n", ""); }
@@ -27,7 +27,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty("0.0,0.0,0.0,1.0", true)] [Editable, Serialize("0.0,0.0,0.0,1.0", true)]
public Color TextColor public Color TextColor
{ {
get { return textColor; } get { return textColor; }
@@ -37,7 +37,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(1.0f, true)] [Editable, Serialize(1.0f, true)]
public float TextScale public float TextScale
{ {
get { return textBlock == null ? 1.0f : textBlock.TextScale; } get { return textBlock == null ? 1.0f : textBlock.TextScale; }
@@ -12,7 +12,7 @@ using System.Linq;
namespace Barotrauma namespace Barotrauma
{ {
partial class Item : MapEntity, IDamageable, IPropertyObject, IServerSerializable, IClientSerializable partial class Item : MapEntity, IDamageable, ISerializableEntity, IServerSerializable, IClientSerializable
{ {
public override Sprite Sprite public override Sprite Sprite
{ {
@@ -145,12 +145,12 @@ namespace Barotrauma
public override void DrawEditing(SpriteBatch spriteBatch, Camera cam) public override void DrawEditing(SpriteBatch spriteBatch, Camera cam)
{ {
if (editingHUD != null) editingHUD.Draw(spriteBatch); if (editingHUD != null && editingHUD.UserData == this) editingHUD.Draw(spriteBatch);
} }
private GUIComponent CreateEditingHUD(bool inGame = false) private GUIComponent CreateEditingHUD(bool inGame = false)
{ {
List<ObjectProperty> editableProperties = inGame ? GetProperties<InGameEditable>() : GetProperties<Editable>(); /*List<SerializableProperty> editableProperties = inGame ? GetProperties<InGameEditable>() : GetProperties<Editable>();
int requiredItemCount = 0; int requiredItemCount = 0;
if (!inGame) if (!inGame)
@@ -159,27 +159,29 @@ namespace Barotrauma
{ {
requiredItemCount += ic.requiredItems.Count; requiredItemCount += ic.requiredItems.Count;
} }
} }*/
int width = 450; int width = 450;
int height = 80 + requiredItemCount * 20; int height = 150;
int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10; int x = GameMain.GraphicsWidth / 2 - width / 2, y = 10;
foreach (var objectProperty in editableProperties) /*foreach (var objectProperty in editableProperties)
{ {
var editable = objectProperty.Attributes.OfType<Editable>().FirstOrDefault(); var editable = objectProperty.Attributes.OfType<Editable>().FirstOrDefault();
if (editable != null) height += (int)(Math.Ceiling(editable.MaxLength / 40.0f) * 18.0f) + 5; if (editable != null) height += (int)(Math.Ceiling(editable.MaxLength / 40.0f) * 18.0f) + 5;
} }*/
editingHUD = new GUIFrame(new Rectangle(x, y, width, height), ""); editingHUD = new GUIListBox(new Rectangle(x, y, width, height), "");
editingHUD.Padding = new Vector4(10, 10, 0, 0); //editingHUD.Padding = new Vector4(10, 10, 0, 0);
editingHUD.UserData = this; editingHUD.UserData = this;
new GUITextBlock(new Rectangle(0, 0, 100, 20), prefab.Name, "", /*new GUITextBlock(new Rectangle(0, 0, 0, 20), prefab.Name, "",
Alignment.TopLeft, Alignment.TopLeft, editingHUD, false, GUI.LargeFont); Alignment.TopLeft, Alignment.TopLeft, editingHUD, false, GUI.LargeFont);*/
y += 25; new SerializableEntityEditor(this, inGame, editingHUD);
if (!inGame) //y += 25;
/*if (!inGame)
{ {
if (prefab.IsLinkable) if (prefab.IsLinkable)
{ {
@@ -198,7 +200,7 @@ namespace Barotrauma
PropertyDescriptor property = properties.Find("JoinedNames", false); PropertyDescriptor property = properties.Find("JoinedNames", false);
namesBox.Text = relatedItem.JoinedNames; namesBox.Text = relatedItem.JoinedNames;
namesBox.UserData = new ObjectProperty(property, relatedItem); namesBox.UserData = new SerializableProperty(property, relatedItem);
namesBox.OnEnterPressed = EnterProperty; namesBox.OnEnterPressed = EnterProperty;
namesBox.OnTextChanged = PropertyChanged; namesBox.OnTextChanged = PropertyChanged;
@@ -206,9 +208,15 @@ namespace Barotrauma
} }
} }
if (requiredItemCount > 0) y += 10; if (requiredItemCount > 0) y += 10;
}*/
foreach (ItemComponent ic in components)
{
if (SerializableProperty.GetProperties<Editable>(ic).Count == 0) continue;
new SerializableEntityEditor(ic, inGame, editingHUD);
} }
foreach (var objectProperty in editableProperties) /*foreach (var objectProperty in editableProperties)
{ {
int boxHeight = 18; int boxHeight = 18;
var editable = objectProperty.Attributes.OfType<Editable>().FirstOrDefault(); var editable = objectProperty.Attributes.OfType<Editable>().FirstOrDefault();
@@ -272,8 +280,7 @@ namespace Barotrauma
} }
y = y + boxHeight + 5; y = y + boxHeight + 5;
}*/
}
return editingHUD; return editingHUD;
} }
@@ -346,10 +353,10 @@ namespace Barotrauma
private bool EnterProperty(GUITickBox tickBox) private bool EnterProperty(GUITickBox tickBox)
{ {
var objectProperty = tickBox.UserData as ObjectProperty; var property = tickBox.UserData as SerializableProperty;
if (objectProperty == null) return false; if (property == null) return false;
objectProperty.TrySetValue(tickBox.Selected); property.TrySetValue(tickBox.Selected);
return true; return true;
} }
@@ -358,24 +365,24 @@ namespace Barotrauma
{ {
textBox.Color = Color.DarkGreen; textBox.Color = Color.DarkGreen;
var objectProperty = textBox.UserData as ObjectProperty; var property = textBox.UserData as SerializableProperty;
if (objectProperty == null) return false; if (property == null) return false;
object prevValue = objectProperty.GetValue(); object prevValue = property.GetValue();
textBox.Deselect(); textBox.Deselect();
if (objectProperty.TrySetValue(text)) if (property.TrySetValue(text))
{ {
textBox.Text = text; textBox.Text = text;
if (GameMain.Server != null) if (GameMain.Server != null)
{ {
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, objectProperty }); GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, property });
} }
else if (GameMain.Client != null) else if (GameMain.Client != null)
{ {
GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, objectProperty }); GameMain.Client.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, property });
} }
return true; return true;
@@ -7,7 +7,7 @@ using System.Collections.Generic;
namespace Barotrauma namespace Barotrauma
{ {
partial class Hull : MapEntity, IPropertyObject, IServerSerializable partial class Hull : MapEntity, ISerializableEntity, IServerSerializable
{ {
public const int MaxDecalsPerHull = 10; public const int MaxDecalsPerHull = 10;
@@ -5,7 +5,7 @@ using System.Linq;
namespace Barotrauma.Networking namespace Barotrauma.Networking
{ {
partial class GameServer : NetworkMember, IPropertyObject partial class GameServer : NetworkMember, ISerializableEntity
{ {
private GUIFrame settingsFrame; private GUIFrame settingsFrame;
private GUIFrame[] settingsTabs; private GUIFrame[] settingsTabs;
@@ -0,0 +1,196 @@
using Barotrauma.Networking;
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Barotrauma
{
class SerializableEntityEditor : GUIComponent
{
private GUIComponent editingHUD;
public SerializableEntityEditor(ISerializableEntity entity, bool inGame, GUIComponent parent) : base("")
{
List<SerializableProperty> editableProperties = inGame ?
SerializableProperty.GetProperties<InGameEditable>(entity) :
SerializableProperty.GetProperties<Editable>(entity);
/*int requiredItemCount = 0;
if (!inGame)
{
foreach (ItemComponent ic in components)
{
requiredItemCount += ic.requiredItems.Count;
}
}
foreach (var objectProperty in editableProperties)
{
var editable = objectProperty.Attributes.OfType<Editable>().FirstOrDefault();
if (editable != null) height += (int)(Math.Ceiling(editable.MaxLength / 40.0f) * 18.0f) + 5;
}*/
editingHUD = new GUIFrame(new Rectangle(0, 0, 0, 0), null, parent);
editingHUD.Padding = new Vector4(10, 10, 00, 20);
editingHUD.UserData = this;
new GUITextBlock(new Rectangle(0, 0, 100, 20), entity.Name, "",
Alignment.TopLeft, Alignment.TopLeft, editingHUD, false, GUI.Font);
int y = 20, padding = 5;
foreach (var property in editableProperties)
{
//int boxHeight = 18;
//var editable = property.Attributes.OfType<Editable>().FirstOrDefault();
//if (editable != null) boxHeight = (int)(Math.Ceiling(editable.MaxLength / 40.0f) * 18.0f);
object value = property.GetValue();
GUIComponent propertyField = null;
if (value is bool)
{
propertyField = CreateBoolField(entity, property, (bool)value, y, editingHUD);
}
else if (value.GetType().IsEnum)
{
propertyField = CreateEnumField(entity, property, value, y, editingHUD);
}
else if (value is string)
{
propertyField = CreateStringField(entity, property, (string)value, y, editingHUD);
}
else if (value is int)
{
propertyField = CreateIntField(entity, property, (int)value, y, editingHUD);
}
else if (value is float)
{
propertyField = CreateFloatField(entity, property, (float)value, y, editingHUD);
}
if (propertyField != null)
{
y += propertyField.Rect.Height + padding;
}
}
editingHUD.SetDimensions(new Point(editingHUD.Rect.Width, editingHUD.children.Sum(c => c.Rect.Height) + 10), false);
}
private GUIComponent CreateBoolField(ISerializableEntity entity, SerializableProperty property, bool value, int yPos, GUIComponent parent)
{
GUITickBox propertyTickBox = new GUITickBox(new Rectangle(10, yPos, 18, 18), property.Name, Alignment.Left, parent);
propertyTickBox.Font = GUI.SmallFont;
propertyTickBox.Selected = value;
propertyTickBox.OnSelected = (tickBox) =>
{
if (property.TrySetValue(tickBox.Selected))
{
TrySendNetworkUpdate(entity, property);
}
return true;
};
return propertyTickBox;
}
private GUIComponent CreateIntField(ISerializableEntity entity, SerializableProperty property, int value, int yPos, GUIComponent parent)
{
new GUITextBlock(new Rectangle(10, yPos, 100, 18), property.Name, "", parent, GUI.SmallFont);
GUINumberInput numberInput = new GUINumberInput(new Rectangle(180, yPos, 0, 18), "", Alignment.Left, null, null, parent);
numberInput.Font = GUI.SmallFont;
var editableAttribute = property.GetAttribute<Editable>();
numberInput.MinValue = editableAttribute.MinValueInt;
numberInput.MinValue = editableAttribute.MaxValueInt;
numberInput.OnValueChanged += (numInput, number) =>
{
if (property.TrySetValue(number))
{
TrySendNetworkUpdate(entity, property);
}
};
return numberInput;
}
private GUIComponent CreateFloatField(ISerializableEntity entity, SerializableProperty property, float value, int yPos, GUIComponent parent)
{
new GUITextBlock(new Rectangle(10, yPos, 100, 18), property.Name, "", parent, GUI.SmallFont);
GUINumberInput numberInput = new GUINumberInput(new Rectangle(180, yPos, 0, 18), "", Alignment.Left, null, null, parent);
numberInput.Font = GUI.SmallFont;
return numberInput;
}
private GUIComponent CreateEnumField(ISerializableEntity entity, SerializableProperty property, object value, int yPos, GUIComponent parent)
{
new GUITextBlock(new Rectangle(0, yPos, 100, 18), property.Name, "", Alignment.TopLeft, Alignment.Left, editingHUD, false, GUI.SmallFont);
GUIDropDown enumDropDown = new GUIDropDown(new Rectangle(180, yPos, 0, 18), "", "", Alignment.TopLeft, parent);
foreach (object enumValue in Enum.GetValues(value.GetType()))
{
var enumTextBlock = new GUITextBlock(new Rectangle(0, 0, 200, 25), enumValue.ToString(), "", enumDropDown);
enumTextBlock.UserData = enumValue;
}
enumDropDown.OnSelected += (selected, val) =>
{
if (property.TrySetValue(val))
{
TrySendNetworkUpdate(entity, property);
}
return true;
};
enumDropDown.SelectItem(value);
return enumDropDown;
}
private GUIComponent CreateStringField(ISerializableEntity entity, SerializableProperty property, string value, int yPos, GUIComponent parent)
{
new GUITextBlock(new Rectangle(0, yPos, 100, 18), property.Name, "", Alignment.TopLeft, Alignment.Left, parent, false, GUI.SmallFont);
GUITextBox propertyBox = new GUITextBox(new Rectangle(0, yPos, 250, 18), Alignment.Right, "", parent);
propertyBox.Font = GUI.SmallFont;
//if (boxHeight > 18) propertyBox.Wrap = true;
propertyBox.Text = value;
propertyBox.OnEnterPressed = (textBox, text) =>
{
if (property.TrySetValue(value))
{
TrySendNetworkUpdate(entity, property);
}
return true;
};
return propertyBox;
}
private void TrySendNetworkUpdate(ISerializableEntity entity, SerializableProperty property)
{
if (GameMain.Server != null)
{
IServerSerializable serverSerializable = entity as IServerSerializable;
if (serverSerializable != null)
{
GameMain.Server.CreateEntityEvent(serverSerializable, new object[] { NetEntityEvent.Type.ChangeProperty, property });
}
}
else if (GameMain.Client != null)
{
IClientSerializable clientSerializable = entity as IClientSerializable;
if (clientSerializable != null)
{
GameMain.Client.CreateEntityEvent(clientSerializable, new object[] { NetEntityEvent.Type.ChangeProperty, property });
}
}
}
}
}
@@ -3,7 +3,7 @@ using System.Xml.Linq;
namespace Barotrauma namespace Barotrauma
{ {
partial class Character : Entity, IDamageable, IPropertyObject, IClientSerializable, IServerSerializable partial class Character : Entity, IDamageable, ISerializableEntity, IClientSerializable, IServerSerializable
{ {
//the Character that the player is currently controlling //the Character that the player is currently controlling
private const Character controlled = null; private const Character controlled = null;
@@ -2,7 +2,7 @@
namespace Barotrauma.Items.Components namespace Barotrauma.Items.Components
{ {
partial class ItemComponent : IPropertyObject partial class ItemComponent : ISerializableEntity
{ {
private bool LoadElemProjSpecific(XElement subElement) private bool LoadElemProjSpecific(XElement subElement)
{ {
@@ -5,21 +5,21 @@ namespace Barotrauma.Items.Components
{ {
partial class ItemLabel : ItemComponent, IDrawableComponent partial class ItemLabel : ItemComponent, IDrawableComponent
{ {
[SerializableProperty("", true), Editable(100)] [Serialize("", true), Editable(100)]
public string Text public string Text
{ {
get; get;
set; set;
} }
[Editable, SerializableProperty("0.0,0.0,0.0,1.0", true)] [Editable, Serialize("0.0,0.0,0.0,1.0", true)]
public Color TextColor public Color TextColor
{ {
get; get;
set; set;
} }
[Editable, SerializableProperty(1.0f, true)] [Editable, Serialize(1.0f, true)]
public float TextScale public float TextScale
{ {
get; get;
@@ -3,7 +3,7 @@ using Microsoft.Xna.Framework;
namespace Barotrauma namespace Barotrauma
{ {
partial class Hull : MapEntity, IPropertyObject, IServerSerializable partial class Hull : MapEntity, ISerializableEntity, IServerSerializable
{ {
public override bool IsMouseOn(Vector2 position) public override bool IsMouseOn(Vector2 position)
{ {
@@ -10,7 +10,7 @@ using Barotrauma.Items.Components;
namespace Barotrauma namespace Barotrauma
{ {
partial class Character : Entity, IDamageable, IPropertyObject, IClientSerializable, IServerSerializable partial class Character : Entity, IDamageable, ISerializableEntity, IClientSerializable, IServerSerializable
{ {
public static List<Character> CharacterList = new List<Character>(); public static List<Character> CharacterList = new List<Character>();
@@ -61,8 +61,8 @@ namespace Barotrauma
protected float lastRecvPositionUpdateTime; protected float lastRecvPositionUpdateTime;
public readonly Dictionary<string, ObjectProperty> Properties; public readonly Dictionary<string, SerializableProperty> Properties;
public Dictionary<string, ObjectProperty> ObjectProperties public Dictionary<string, SerializableProperty> SerializableProperties
{ {
get { return Properties; } get { return Properties; }
} }
@@ -545,7 +545,7 @@ namespace Barotrauma
lowPassMultiplier = 1.0f; lowPassMultiplier = 1.0f;
Properties = ObjectProperty.GetProperties(this); Properties = SerializableProperty.GetProperties(this);
Info = characterInfo; Info = characterInfo;
if (file == humanConfigFile && characterInfo == null) if (file == humanConfigFile && characterInfo == null)
@@ -13,7 +13,7 @@ namespace Barotrauma
private Entity entity; private Entity entity;
private List<IPropertyObject> targets; private List<ISerializableEntity> targets;
public float StartTimer public float StartTimer
{ {
@@ -26,7 +26,7 @@ namespace Barotrauma
delay = element.GetAttributeFloat("delay", 1.0f); delay = element.GetAttributeFloat("delay", 1.0f);
} }
public override void Apply(ActionType type, float deltaTime, Entity entity, List<IPropertyObject> targets) public override void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets)
{ {
if (this.type != type) return; if (this.type != type) return;
@@ -33,7 +33,7 @@ namespace Barotrauma
var levelString = element.GetAttributeString("level", ""); var levelString = element.GetAttributeString("level", "");
if (levelString.Contains(",")) if (levelString.Contains(","))
{ {
levelRange = XMLExtensions.ParseToVector2(levelString, false); levelRange = XMLExtensions.ParseVector2(levelString, false);
} }
else else
{ {
@@ -209,26 +209,26 @@ namespace Barotrauma
return true; return true;
} }
public virtual void Apply(ActionType type, float deltaTime, Entity entity, IPropertyObject target) public virtual void Apply(ActionType type, float deltaTime, Entity entity, ISerializableEntity target)
{ {
if (this.type != type || !HasRequiredItems(entity)) return; if (this.type != type || !HasRequiredItems(entity)) return;
if (targetNames != null && !targetNames.Contains(target.Name)) return; if (targetNames != null && !targetNames.Contains(target.Name)) return;
List<IPropertyObject> targets = new List<IPropertyObject>(); List<ISerializableEntity> targets = new List<ISerializableEntity>();
targets.Add(target); targets.Add(target);
Apply(deltaTime, entity, targets); Apply(deltaTime, entity, targets);
} }
public virtual void Apply(ActionType type, float deltaTime, Entity entity, List<IPropertyObject> targets) public virtual void Apply(ActionType type, float deltaTime, Entity entity, List<ISerializableEntity> targets)
{ {
if (this.type != type || !HasRequiredItems(entity)) return; if (this.type != type || !HasRequiredItems(entity)) return;
Apply(deltaTime, entity, targets); Apply(deltaTime, entity, targets);
} }
protected void Apply(float deltaTime, Entity entity, List<IPropertyObject> targets) protected void Apply(float deltaTime, Entity entity, List<ISerializableEntity> targets)
{ {
#if CLIENT #if CLIENT
if (sound != null) if (sound != null)
@@ -259,13 +259,13 @@ namespace Barotrauma
} }
} }
foreach (IPropertyObject target in targets) foreach (ISerializableEntity target in targets)
{ {
for (int i = 0; i < propertyNames.Length; i++) for (int i = 0; i < propertyNames.Length; i++)
{ {
ObjectProperty property; SerializableProperty property;
if (!target.ObjectProperties.TryGetValue(propertyNames[i], out property)) continue; if (!target.SerializableProperties.TryGetValue(propertyNames[i], out property)) continue;
if (duration > 0.0f) if (duration > 0.0f)
{ {
@@ -308,7 +308,7 @@ namespace Barotrauma
#endif #endif
} }
private IEnumerable<object> ApplyToPropertyOverDuration(float duration, ObjectProperty property, object value) private IEnumerable<object> ApplyToPropertyOverDuration(float duration, SerializableProperty property, object value)
{ {
float timer = duration; float timer = duration;
while (timer > 0.0f) while (timer > 0.0f)
@@ -323,7 +323,7 @@ namespace Barotrauma
yield return CoroutineStatus.Success; yield return CoroutineStatus.Success;
} }
private void ApplyToProperty(ObjectProperty property, object value, float deltaTime) private void ApplyToProperty(SerializableProperty property, object value, float deltaTime)
{ {
if (disableDeltaTime || setValue) deltaTime = 1.0f; if (disableDeltaTime || setValue) deltaTime = 1.0f;
@@ -47,21 +47,21 @@ namespace Barotrauma.Items.Components
set { dockingDir = value; } set { dockingDir = value; }
} }
[SerializableProperty("32.0,32.0", false)] [Serialize("32.0,32.0", false)]
public Vector2 DistanceTolerance public Vector2 DistanceTolerance
{ {
get { return distanceTolerance; } get { return distanceTolerance; }
set { distanceTolerance = value; } set { distanceTolerance = value; }
} }
[SerializableProperty(32.0f, false)] [Serialize(32.0f, false)]
public float DockedDistance public float DockedDistance
{ {
get; get;
set; set;
} }
[SerializableProperty(true, false)] [Serialize(true, false)]
public bool IsHorizontal public bool IsHorizontal
{ {
get; get;
@@ -111,13 +111,13 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty("0.0,0.0,0.0,0.0", false)] [Serialize("0.0,0.0,0.0,0.0", false)]
public string Window public string Window
{ {
get { return XMLExtensions.Vector4ToString(new Vector4(window.X, window.Y, window.Width, window.Height)); } get { return XMLExtensions.Vector4ToString(new Vector4(window.X, window.Y, window.Width, window.Height)); }
set set
{ {
Vector4 vector = XMLExtensions.ParseToVector4(value); Vector4 vector = XMLExtensions.ParseVector4(value);
if (vector.Z != 0.0f || vector.W != 0.0f) if (vector.Z != 0.0f || vector.W != 0.0f)
{ {
window = new Rectangle((int)vector.X, (int)vector.Y, (int)vector.Z, (int)vector.W); window = new Rectangle((int)vector.X, (int)vector.Y, (int)vector.Z, (int)vector.W);
@@ -130,7 +130,7 @@ namespace Barotrauma.Items.Components
get { return window; } get { return window; }
} }
[Editable, SerializableProperty(false, true)] [Editable, Serialize(false, true)]
public bool IsOpen public bool IsOpen
{ {
get { return isOpen; } get { return isOpen; }
@@ -29,49 +29,49 @@ namespace Barotrauma.Items.Components
//the angle in which the Character holds the item //the angle in which the Character holds the item
protected float holdAngle; protected float holdAngle;
[SerializableProperty(false, true)] [Serialize(false, true)]
public bool Attached public bool Attached
{ {
get { return attached && item.ParentInventory == null; } get { return attached && item.ParentInventory == null; }
set { attached = value; } set { attached = value; }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool ControlPose public bool ControlPose
{ {
get; get;
set; set;
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool Attachable public bool Attachable
{ {
get { return attachable; } get { return attachable; }
set { attachable = value; } set { attachable = value; }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool AttachedByDefault public bool AttachedByDefault
{ {
get { return attachedByDefault; } get { return attachedByDefault; }
set { attachedByDefault = value; } set { attachedByDefault = value; }
} }
[SerializableProperty("0.0,0.0", false)] [Serialize("0.0,0.0", false)]
public Vector2 HoldPos public Vector2 HoldPos
{ {
get { return ConvertUnits.ToDisplayUnits(holdPos); } get { return ConvertUnits.ToDisplayUnits(holdPos); }
set { holdPos = ConvertUnits.ToSimUnits(value); } set { holdPos = ConvertUnits.ToSimUnits(value); }
} }
[SerializableProperty("0.0,0.0", false)] [Serialize("0.0,0.0", false)]
public Vector2 AimPos public Vector2 AimPos
{ {
get { return ConvertUnits.ToDisplayUnits(aimPos); } get { return ConvertUnits.ToDisplayUnits(aimPos); }
set { aimPos = ConvertUnits.ToSimUnits(value); } set { aimPos = ConvertUnits.ToSimUnits(value); }
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float HoldAngle public float HoldAngle
{ {
get { return MathHelper.ToDegrees(holdAngle); } get { return MathHelper.ToDegrees(holdAngle); }
@@ -24,14 +24,14 @@ namespace Barotrauma.Items.Components
private float reloadTimer; private float reloadTimer;
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float Range public float Range
{ {
get { return ConvertUnits.ToDisplayUnits(range); } get { return ConvertUnits.ToDisplayUnits(range); }
set { range = ConvertUnits.ToSimUnits(value); } set { range = ConvertUnits.ToSimUnits(value); }
} }
[SerializableProperty(0.5f, false)] [Serialize(0.5f, false)]
public float Reload public float Reload
{ {
get { return reload; } get { return reload; }
@@ -22,7 +22,7 @@ namespace Barotrauma.Items.Components
private UsableIn usableIn; private UsableIn usableIn;
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float Force public float Force
{ {
get { return force; } get { return force; }
@@ -30,7 +30,7 @@ namespace Barotrauma.Items.Components
} }
#if CLIENT #if CLIENT
[SerializableProperty("", false)] [Serialize("", false)]
public string Particles public string Particles
{ {
get { return particles; } get { return particles; }
@@ -13,28 +13,28 @@ namespace Barotrauma.Items.Components
private Vector2 barrelPos; private Vector2 barrelPos;
[SerializableProperty("0.0,0.0", false)] [Serialize("0.0,0.0", false)]
public string BarrelPos public string BarrelPos
{ {
get { return XMLExtensions.Vector2ToString(ConvertUnits.ToDisplayUnits(barrelPos)); } get { return XMLExtensions.Vector2ToString(ConvertUnits.ToDisplayUnits(barrelPos)); }
set { barrelPos = ConvertUnits.ToSimUnits(XMLExtensions.ParseToVector2(value)); } set { barrelPos = ConvertUnits.ToSimUnits(XMLExtensions.ParseVector2(value)); }
} }
[SerializableProperty(1.0f, false)] [Serialize(1.0f, false)]
public float Reload public float Reload
{ {
get { return reload; } get { return reload; }
set { reload = Math.Max(value, 0.0f); } set { reload = Math.Max(value, 0.0f); }
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float Spread public float Spread
{ {
get; get;
set; set;
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float UnskilledSpread public float UnskilledSpread
{ {
get; get;
@@ -21,44 +21,44 @@ namespace Barotrauma.Items.Components
private float activeTimer; private float activeTimer;
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float Range public float Range
{ {
get { return range; } get { return range; }
set { range = value; } set { range = value; }
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float StructureFixAmount public float StructureFixAmount
{ {
get; set; get; set;
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float LimbFixAmount public float LimbFixAmount
{ {
get; set; get; set;
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float ExtinquishAmount public float ExtinquishAmount
{ {
get; set; get; set;
} }
[SerializableProperty("", false)] [Serialize("", false)]
public string Particles public string Particles
{ {
get { return particles; } get { return particles; }
set { particles = value; } set { particles = value; }
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float ParticleSpeed public float ParticleSpeed
{ {
get; set; get; set;
} }
[SerializableProperty("0.0,0.0", false)] [Serialize("0.0,0.0", false)]
public Vector2 BarrelPos public Vector2 BarrelPos
{ {
get { return barrelPos; } get { return barrelPos; }
@@ -12,7 +12,7 @@ namespace Barotrauma.Items.Components
bool throwing; bool throwing;
[SerializableProperty(1.0f, false)] [Serialize(1.0f, false)]
public float ThrowForce public float ThrowForce
{ {
get { return throwForce; } get { return throwForce; }
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
/// <summary> /// <summary>
/// The base class for components holding the different functionalities of the item /// The base class for components holding the different functionalities of the item
/// </summary> /// </summary>
partial class ItemComponent : IPropertyObject partial class ItemComponent : ISerializableEntity
{ {
protected Item item; protected Item item;
@@ -47,15 +47,15 @@ namespace Barotrauma.Items.Components
private string msg; private string msg;
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float PickingTime public float PickingTime
{ {
get; get;
private set; private set;
} }
public readonly Dictionary<string, ObjectProperty> properties; public readonly Dictionary<string, SerializableProperty> properties;
public Dictionary<string, ObjectProperty> ObjectProperties public Dictionary<string, SerializableProperty> SerializableProperties
{ {
get { return properties; } get { return properties; }
} }
@@ -103,21 +103,21 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool CanBePicked public bool CanBePicked
{ {
get { return canBePicked; } get { return canBePicked; }
set { canBePicked = value; } set { canBePicked = value; }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool DrawHudWhenEquipped public bool DrawHudWhenEquipped
{ {
get; get;
private set; private set;
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool CanBeSelected public bool CanBeSelected
{ {
get { return canBeSelected; } get { return canBeSelected; }
@@ -136,7 +136,7 @@ namespace Barotrauma.Items.Components
protected set; protected set;
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool DeleteOnUse public bool DeleteOnUse
{ {
get; get;
@@ -153,7 +153,7 @@ namespace Barotrauma.Items.Components
get { return name; } get { return name; }
} }
[SerializableProperty("", false)] [Serialize("", false)]
public string Msg public string Msg
{ {
get { return msg; } get { return msg; }
@@ -164,7 +164,7 @@ namespace Barotrauma.Items.Components
{ {
this.item = item; this.item = item;
properties = ObjectProperty.GetProperties(this); properties = SerializableProperty.GetProperties(this);
//canBePicked = ToolBox.GetAttributeBool(element, "canbepicked", false); //canBePicked = ToolBox.GetAttributeBool(element, "canbepicked", false);
//canBeSelected = ToolBox.GetAttributeBool(element, "canbeselected", false); //canBeSelected = ToolBox.GetAttributeBool(element, "canbeselected", false);
@@ -205,7 +205,7 @@ namespace Barotrauma.Items.Components
DebugConsole.ThrowError("Invalid pick key in " + element + "!", e); DebugConsole.ThrowError("Invalid pick key in " + element + "!", e);
} }
properties = ObjectProperty.DeserializeProperties(this, element); properties = SerializableProperty.DeserializeProperties(this, element);
foreach (XElement subElement in element.Elements()) foreach (XElement subElement in element.Elements())
{ {
@@ -477,7 +477,7 @@ namespace Barotrauma.Items.Components
} }
} }
public void ApplyStatusEffects(ActionType type, List<IPropertyObject> targets, float deltaTime) public void ApplyStatusEffects(ActionType type, List<ISerializableEntity> targets, float deltaTime)
{ {
if (statusEffectLists == null) return; if (statusEffectLists == null) return;
@@ -496,7 +496,7 @@ namespace Barotrauma.Items.Components
foreach (XAttribute attribute in componentElement.Attributes()) foreach (XAttribute attribute in componentElement.Attributes())
{ {
ObjectProperty property = null; SerializableProperty property = null;
if (!properties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out property)) continue; if (!properties.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out property)) continue;
property.TrySetValue(attribute.Value); property.TrySetValue(attribute.Value);
@@ -586,7 +586,7 @@ namespace Barotrauma.Items.Components
componentElement.Add(newElement); componentElement.Add(newElement);
} }
ObjectProperty.SerializeProperties(this, componentElement); SerializableProperty.SerializeProperties(this, componentElement);
parentElement.Add(componentElement); parentElement.Add(componentElement);
return componentElement; return componentElement;
@@ -18,7 +18,7 @@ namespace Barotrauma.Items.Components
private ushort[] itemIds; private ushort[] itemIds;
//how many items can be contained //how many items can be contained
[SerializableProperty(5, false)] [Serialize(5, false)]
public int Capacity public int Capacity
{ {
get { return capacity; } get { return capacity; }
@@ -26,7 +26,7 @@ namespace Barotrauma.Items.Components
} }
private int capacity; private int capacity;
[SerializableProperty(true, false)] [Serialize(true, false)]
public bool HideItems public bool HideItems
{ {
get { return hideItems; } get { return hideItems; }
@@ -38,7 +38,7 @@ namespace Barotrauma.Items.Components
} }
private bool hideItems; private bool hideItems;
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool DrawInventory public bool DrawInventory
{ {
get { return drawInventory; } get { return drawInventory; }
@@ -47,7 +47,7 @@ namespace Barotrauma.Items.Components
private bool drawInventory; private bool drawInventory;
//the position of the first item in the container //the position of the first item in the container
[SerializableProperty("0.0,0.0", false)] [Serialize("0.0,0.0", false)]
public Vector2 ItemPos public Vector2 ItemPos
{ {
get { return itemPos; } get { return itemPos; }
@@ -56,7 +56,7 @@ namespace Barotrauma.Items.Components
private Vector2 itemPos; private Vector2 itemPos;
//item[i].Pos = itemPos + itemInterval*i //item[i].Pos = itemPos + itemInterval*i
[SerializableProperty("0.0,0.0", false)] [Serialize("0.0,0.0", false)]
public Vector2 ItemInterval public Vector2 ItemInterval
{ {
get { return itemInterval; } get { return itemInterval; }
@@ -64,7 +64,7 @@ namespace Barotrauma.Items.Components
} }
private Vector2 itemInterval; private Vector2 itemInterval;
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float ItemRotation public float ItemRotation
{ {
get { return MathHelper.ToDegrees(itemRotation); } get { return MathHelper.ToDegrees(itemRotation); }
@@ -73,7 +73,7 @@ namespace Barotrauma.Items.Components
private float itemRotation; private float itemRotation;
[SerializableProperty("0.5,0.9", false)] [Serialize("0.5,0.9", false)]
public Vector2 HudPos public Vector2 HudPos
{ {
get { return hudPos; } get { return hudPos; }
@@ -84,7 +84,7 @@ namespace Barotrauma.Items.Components
} }
private Vector2 hudPos; private Vector2 hudPos;
[SerializableProperty(5, false)] [Serialize(5, false)]
public int SlotsPerRow public int SlotsPerRow
{ {
get { return slotsPerRow; } get { return slotsPerRow; }
@@ -23,7 +23,7 @@ namespace Barotrauma.Items.Components
// } // }
//} //}
[Editable, SerializableProperty(2000.0f, true)] [Editable, Serialize(2000.0f, true)]
public float MaxForce public float MaxForce
{ {
get { return maxForce; } get { return maxForce; }
@@ -16,21 +16,21 @@ namespace Barotrauma.Items.Components
bool hasPower; bool hasPower;
[Editable, SerializableProperty(false, true)] [Editable, Serialize(false, true)]
public bool RequireWaterDetectors public bool RequireWaterDetectors
{ {
get; get;
set; set;
} }
[Editable, SerializableProperty(true, true)] [Editable, Serialize(true, true)]
public bool RequireOxygenDetectors public bool RequireOxygenDetectors
{ {
get; get;
set; set;
} }
[Editable, SerializableProperty(false, true)] [Editable, Serialize(false, true)]
public bool ShowHullIntegrity public bool ShowHullIntegrity
{ {
get; get;
@@ -29,7 +29,7 @@ namespace Barotrauma.Items.Components
private set; private set;
} }
[Editable, SerializableProperty(100.0f, true)] [Editable, Serialize(100.0f, true)]
public float GeneratedAmount public float GeneratedAmount
{ {
get { return generatedAmount; } get { return generatedAmount; }
@@ -15,7 +15,7 @@ namespace Barotrauma.Items.Components
public Hull hull1; public Hull hull1;
[SerializableProperty(0.0f, true)] [Serialize(0.0f, true)]
public float FlowPercentage public float FlowPercentage
{ {
get { return flowPercentage; } get { return flowPercentage; }
@@ -27,7 +27,7 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(80.0f, false)] [Serialize(80.0f, false)]
public float MaxFlow public float MaxFlow
{ {
get { return maxFlow; } get { return maxFlow; }
@@ -26,14 +26,14 @@ namespace Barotrauma.Items.Components
private float displayBorderSize; private float displayBorderSize;
[SerializableProperty(10000.0f, false)] [Serialize(10000.0f, false)]
public float Range public float Range
{ {
get { return range; } get { return range; }
set { range = MathHelper.Clamp(value, 0.0f, 100000.0f); } set { range = MathHelper.Clamp(value, 0.0f, 100000.0f); }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool DetectSubmarineWalls public bool DetectSubmarineWalls
{ {
get; get;
@@ -54,7 +54,7 @@ namespace Barotrauma.Items.Components
private float? nextServerLogWriteTime; private float? nextServerLogWriteTime;
private float lastServerLogWriteTime; private float lastServerLogWriteTime;
[Editable, SerializableProperty(9500.0f, true)] [Editable, Serialize(9500.0f, true)]
public float MeltDownTemp public float MeltDownTemp
{ {
get { return meltDownTemp; } get { return meltDownTemp; }
@@ -64,7 +64,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(9000.0f, true)] [Editable, Serialize(9000.0f, true)]
public float FireTemp public float FireTemp
{ {
get { return fireTemp; } get { return fireTemp; }
@@ -74,7 +74,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(1.0f, true)] [Editable, Serialize(1.0f, true)]
public float PowerPerTemp public float PowerPerTemp
{ {
get { return powerPerTemp; } get { return powerPerTemp; }
@@ -84,7 +84,7 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(0.0f, true)] [Serialize(0.0f, true)]
public float FissionRate public float FissionRate
{ {
get { return fissionRate; } get { return fissionRate; }
@@ -95,7 +95,7 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(0.0f, true)] [Serialize(0.0f, true)]
public float CoolingRate public float CoolingRate
{ {
get { return coolingRate; } get { return coolingRate; }
@@ -106,7 +106,7 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(0.0f, true)] [Serialize(0.0f, true)]
public float Temperature public float Temperature
{ {
get { return temperature; } get { return temperature; }
@@ -122,7 +122,7 @@ namespace Barotrauma.Items.Components
return (temperature > 0.0f); return (temperature > 0.0f);
} }
[SerializableProperty(false, true)] [Serialize(false, true)]
public bool AutoTemp public bool AutoTemp
{ {
get { return autoTemp; } get { return autoTemp; }
@@ -139,7 +139,7 @@ namespace Barotrauma.Items.Components
public float AvailableFuel { get; set; } public float AvailableFuel { get; set; }
[SerializableProperty(500.0f, true)] [Serialize(500.0f, true)]
public float ShutDownTemp public float ShutDownTemp
{ {
get { return shutDownTemp; } get { return shutDownTemp; }
@@ -67,7 +67,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(0.5f, true)] [Editable, Serialize(0.5f, true)]
public float NeutralBallastLevel public float NeutralBallastLevel
{ {
get { return neutralBallastLevel; } get { return neutralBallastLevel; }
@@ -336,7 +336,7 @@ namespace Barotrauma.Items.Components
{ {
if (connection.Name == "velocity_in") if (connection.Name == "velocity_in")
{ {
currVelocity = XMLExtensions.ParseToVector2(signal, false); currVelocity = XMLExtensions.ParseVector2(signal, false);
} }
else else
{ {
@@ -32,21 +32,21 @@ namespace Barotrauma.Items.Components
private set; private set;
} }
[Editable, SerializableProperty(10.0f, true)] [Editable, Serialize(10.0f, true)]
public float MaxOutPut public float MaxOutPut
{ {
set { maxOutput = value; } set { maxOutput = value; }
get { return maxOutput; } get { return maxOutput; }
} }
[SerializableProperty(10.0f, true), Editable] [Serialize(10.0f, true), Editable]
public float Capacity public float Capacity
{ {
get { return capacity; } get { return capacity; }
set { capacity = Math.Max(value, 1.0f); } set { capacity = Math.Max(value, 1.0f); }
} }
[Editable, SerializableProperty(0.0f, true)] [Editable, Serialize(0.0f, true)]
public float Charge public float Charge
{ {
get { return charge; } get { return charge; }
@@ -63,7 +63,7 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(10.0f, true), Editable] [Serialize(10.0f, true), Editable]
public float RechargeSpeed public float RechargeSpeed
{ {
get { return rechargeSpeed; } get { return rechargeSpeed; }
@@ -75,7 +75,7 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(10.0f, false), Editable] [Serialize(10.0f, false), Editable]
public float MaxRechargeSpeed public float MaxRechargeSpeed
{ {
get { return maxRechargeSpeed; } get { return maxRechargeSpeed; }
@@ -18,14 +18,14 @@ namespace Barotrauma.Items.Components
//the maximum amount of power the item can draw from connected items //the maximum amount of power the item can draw from connected items
protected float powerConsumption; protected float powerConsumption;
[Editable, SerializableProperty(0.5f, true)] [Editable, Serialize(0.5f, true)]
public float MinVoltage public float MinVoltage
{ {
get { return minVoltage; } get { return minVoltage; }
set { minVoltage = value; } set { minVoltage = value; }
} }
[Editable, SerializableProperty(0.0f, true)] [Editable, Serialize(0.0f, true)]
public float PowerConsumption public float PowerConsumption
{ {
get { return powerConsumption; } get { return powerConsumption; }
@@ -33,7 +33,7 @@ namespace Barotrauma.Items.Components
} }
[SerializableProperty(false,true)] [Serialize(false,true)]
public override bool IsActive public override bool IsActive
{ {
get { return base.IsActive; } get { return base.IsActive; }
@@ -44,14 +44,14 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(0.0f, true)] [Serialize(0.0f, true)]
public float CurrPowerConsumption public float CurrPowerConsumption
{ {
get {return currPowerConsumption; } get {return currPowerConsumption; }
set { currPowerConsumption = value; } set { currPowerConsumption = value; }
} }
[SerializableProperty(0.0f, true)] [Serialize(0.0f, true)]
public float Voltage public float Voltage
{ {
get { return voltage; } get { return voltage; }
@@ -23,35 +23,35 @@ namespace Barotrauma.Items.Components
public Character User; public Character User;
[SerializableProperty(10.0f, false)] [Serialize(10.0f, false)]
public float LaunchImpulse public float LaunchImpulse
{ {
get { return launchImpulse; } get { return launchImpulse; }
set { launchImpulse = value; } set { launchImpulse = value; }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool CharacterUsable public bool CharacterUsable
{ {
get { return characterUsable; } get { return characterUsable; }
set { characterUsable = value; } set { characterUsable = value; }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool DoesStick public bool DoesStick
{ {
get { return doesStick; } get { return doesStick; }
set { doesStick = value; } set { doesStick = value; }
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool Hitscan public bool Hitscan
{ {
get; get;
set; set;
} }
[SerializableProperty(false, false)] [Serialize(false, false)]
public bool RemoveOnHit public bool RemoveOnHit
{ {
get; get;
@@ -13,7 +13,7 @@ namespace Barotrauma.Items.Components
//the output is sent if both inputs have received a signal within the timeframe //the output is sent if both inputs have received a signal within the timeframe
protected float timeFrame; protected float timeFrame;
[InGameEditable, SerializableProperty(0.0f, true)] [InGameEditable, Serialize(0.0f, true)]
public float TimeFrame public float TimeFrame
{ {
get { return timeFrame; } get { return timeFrame; }
@@ -23,14 +23,14 @@ namespace Barotrauma.Items.Components
} }
} }
[InGameEditable, SerializableProperty("1", true)] [InGameEditable, Serialize("1", true)]
public string Output public string Output
{ {
get { return output; } get { return output; }
set { output = value; } set { output = value; }
} }
[InGameEditable, SerializableProperty("", true)] [InGameEditable, Serialize("", true)]
public string FalseOutput public string FalseOutput
{ {
get { return falseOutput; } get { return falseOutput; }
@@ -15,7 +15,7 @@ namespace Barotrauma.Items.Components
private Queue<Tuple<string, DateTime>> signalQueue; private Queue<Tuple<string, DateTime>> signalQueue;
[InGameEditable, SerializableProperty(1.0f, true)] [InGameEditable, Serialize(1.0f, true)]
public float Delay public float Delay
{ {
get { return (float)delay.TotalSeconds; } get { return (float)delay.TotalSeconds; }
@@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components
private bool castShadows; private bool castShadows;
[Editable, SerializableProperty(100.0f, true)] [Editable, Serialize(100.0f, true)]
public float Range public float Range
{ {
get { return range; } get { return range; }
@@ -31,7 +31,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(true, true)] [Editable, Serialize(true, true)]
public bool CastShadows public bool CastShadows
{ {
get { return castShadows; } get { return castShadows; }
@@ -44,7 +44,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(false, true)] [Editable, Serialize(false, true)]
public bool IsOn public bool IsOn
{ {
get { return IsActive; } get { return IsActive; }
@@ -57,7 +57,7 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float Flicker public float Flicker
{ {
get { return flicker; } get { return flicker; }
@@ -67,7 +67,7 @@ namespace Barotrauma.Items.Components
} }
} }
[InGameEditable, SerializableProperty("1.0,1.0,1.0,1.0", true)] [InGameEditable, Serialize("1.0,1.0,1.0,1.0", true)]
public Color LightColor public Color LightColor
{ {
get { return lightColor; } get { return lightColor; }
@@ -207,7 +207,7 @@ namespace Barotrauma.Items.Components
IsActive = (signal != "0"); IsActive = (signal != "0");
break; break;
case "set_color": case "set_color":
LightColor = XMLExtensions.ParseToColor(signal, false); LightColor = XMLExtensions.ParseColor(signal, false);
break; break;
} }
} }
@@ -17,7 +17,7 @@ namespace Barotrauma.Items.Components
private float updateTimer; private float updateTimer;
[InGameEditable, SerializableProperty(0.0f, true)] [InGameEditable, Serialize(0.0f, true)]
public float Range public float Range
{ {
get { return range; } get { return range; }
@@ -27,14 +27,14 @@ namespace Barotrauma.Items.Components
} }
} }
[InGameEditable, SerializableProperty("1", true)] [InGameEditable, Serialize("1", true)]
public string Output public string Output
{ {
get { return output; } get { return output; }
set { output = value; } set { output = value; }
} }
[InGameEditable, SerializableProperty("", true)] [InGameEditable, Serialize("", true)]
public string FalseOutput public string FalseOutput
{ {
get { return falseOutput; } get { return falseOutput; }
@@ -20,14 +20,14 @@ namespace Barotrauma.Items.Components
private float phase; private float phase;
[InGameEditable, SerializableProperty(WaveType.Pulse, true)] [InGameEditable, Serialize(WaveType.Pulse, true)]
public WaveType OutputType public WaveType OutputType
{ {
get; get;
set; set;
} }
[InGameEditable, SerializableProperty(1.0f, true)] [InGameEditable, Serialize(1.0f, true)]
public float Frequency public float Frequency
{ {
get { return frequency; } get { return frequency; }
@@ -16,14 +16,14 @@ namespace Barotrauma.Items.Components
private Regex regex; private Regex regex;
[InGameEditable, SerializableProperty("1", true)] [InGameEditable, Serialize("1", true)]
public string Output public string Output
{ {
get { return output; } get { return output; }
set { output = value; } set { output = value; }
} }
[InGameEditable, SerializableProperty("", true)] [InGameEditable, Serialize("", true)]
public string Expression public string Expression
{ {
get { return expression; } get { return expression; }
@@ -11,7 +11,7 @@ namespace Barotrauma.Items.Components
private bool isOn; private bool isOn;
[Editable, SerializableProperty(1000.0f, true)] [Editable, Serialize(1000.0f, true)]
public float MaxPower public float MaxPower
{ {
get { return maxPower; } get { return maxPower; }
@@ -21,7 +21,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(false, true)] [Editable, Serialize(false, true)]
public bool IsOn public bool IsOn
{ {
get get
@@ -8,20 +8,20 @@ namespace Barotrauma.Items.Components
private string targetSignal; private string targetSignal;
[InGameEditable, SerializableProperty("1", true)] [InGameEditable, Serialize("1", true)]
public string Output public string Output
{ {
get { return output; } get { return output; }
set { output = value; } set { output = value; }
} }
[InGameEditable, SerializableProperty("0", true)] [InGameEditable, Serialize("0", true)]
public string FalseOutput public string FalseOutput
{ {
get { return falseOutput; } get { return falseOutput; }
set { falseOutput = value; } set { falseOutput = value; }
} }
[InGameEditable, SerializableProperty("", true)] [InGameEditable, Serialize("", true)]
public string TargetSignal public string TargetSignal
{ {
get { return targetSignal; } get { return targetSignal; }
@@ -14,14 +14,14 @@ namespace Barotrauma.Items.Components
private int channel; private int channel;
[SerializableProperty(20000.0f, false)] [Serialize(20000.0f, false)]
public float Range public float Range
{ {
get { return range; } get { return range; }
set { range = Math.Max(value, 0.0f); } set { range = Math.Max(value, 0.0f); }
} }
[InGameEditable, SerializableProperty(1, true)] [InGameEditable, Serialize(1, true)]
public int Channel public int Channel
{ {
get { return channel; } get { return channel; }
@@ -31,7 +31,7 @@ namespace Barotrauma.Items.Components
} }
} }
[Editable, SerializableProperty(false, false)] [Editable, Serialize(false, false)]
public bool LinkToChat public bool LinkToChat
{ {
get; get;
@@ -26,7 +26,7 @@ namespace Barotrauma.Items.Components
Camera cam; Camera cam;
[SerializableProperty("0,0", false)] [Serialize("0,0", false)]
public Vector2 BarrelPos public Vector2 BarrelPos
{ {
get get
@@ -39,21 +39,21 @@ namespace Barotrauma.Items.Components
} }
} }
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float LaunchImpulse public float LaunchImpulse
{ {
get { return launchImpulse; } get { return launchImpulse; }
set { launchImpulse = value; } set { launchImpulse = value; }
} }
[SerializableProperty(5.0f, false)] [Serialize(5.0f, false)]
public float Reload public float Reload
{ {
get { return reloadTime; } get { return reloadTime; }
set { reloadTime = value; } set { reloadTime = value; }
} }
[SerializableProperty("0.0,0.0", true), Editable] [Serialize("0.0,0.0", true), Editable]
public Vector2 RotationLimits public Vector2 RotationLimits
{ {
get get
@@ -350,7 +350,7 @@ namespace Barotrauma.Items.Components
switch (connection.Name) switch (connection.Name)
{ {
case "position_in": case "position_in":
Vector2 receivedPos = XMLExtensions.ParseToVector2(signal, false); Vector2 receivedPos = XMLExtensions.ParseVector2(signal, false);
Vector2 centerPos = new Vector2(item.WorldRect.X + barrelPos.X, item.WorldRect.Y - barrelPos.Y); Vector2 centerPos = new Vector2(item.WorldRect.X + barrelPos.X, item.WorldRect.Y - barrelPos.Y);
@@ -35,14 +35,14 @@ namespace Barotrauma.Items.Components
private Vector2 armorSector; private Vector2 armorSector;
[SerializableProperty(0.0f, false)] [Serialize(0.0f, false)]
public float ArmorValue public float ArmorValue
{ {
get { return armorValue; } get { return armorValue; }
set { armorValue = MathHelper.Clamp(value, 0.0f, 100.0f); } set { armorValue = MathHelper.Clamp(value, 0.0f, 100.0f); }
} }
[SerializableProperty("0.0,360.0", false)] [Serialize("0.0,360.0", false)]
public Vector2 ArmorSector public Vector2 ArmorSector
{ {
get { return armorSector; } get { return armorSector; }
@@ -23,7 +23,7 @@ namespace Barotrauma
OnImpact OnImpact
} }
partial class Item : MapEntity, IDamageable, IPropertyObject, IServerSerializable, IClientSerializable partial class Item : MapEntity, IDamageable, ISerializableEntity, IServerSerializable, IClientSerializable
{ {
const float MaxVel = 64.0f; const float MaxVel = 64.0f;
@@ -64,8 +64,8 @@ namespace Barotrauma
//a dictionary containing lists of the status effects in all the components of the item //a dictionary containing lists of the status effects in all the components of the item
private Dictionary<ActionType, List<StatusEffect>> statusEffectLists; private Dictionary<ActionType, List<StatusEffect>> statusEffectLists;
public readonly Dictionary<string, ObjectProperty> properties; public readonly Dictionary<string, SerializableProperty> properties;
public Dictionary<string, ObjectProperty> ObjectProperties public Dictionary<string, SerializableProperty> SerializableProperties
{ {
get { return properties; } get { return properties; }
} }
@@ -169,14 +169,11 @@ namespace Barotrauma
} }
protected Color spriteColor; protected Color spriteColor;
[Editable, SerializableProperty("1.0,1.0,1.0,1.0", true)] [Editable, Serialize("1.0,1.0,1.0,1.0", true)]
public string SpriteColor public Color SpriteColor
{ {
get { return XMLExtensions.Vector4ToString(spriteColor.ToVector4()); } get { return spriteColor; }
set set { spriteColor = value; }
{
spriteColor = new Color(XMLExtensions.ParseToVector4(value));
}
} }
public Color Color public Color Color
@@ -220,7 +217,7 @@ namespace Barotrauma
get { return condition; } get { return condition; }
} }
[Editable, SerializableProperty("", true)] [Editable, Serialize("", true)]
public string Tags public string Tags
{ {
get { return string.Join(",",tags); } get { return string.Join(",",tags); }
@@ -313,11 +310,11 @@ namespace Barotrauma
#endif #endif
} }
public List<IPropertyObject> AllPropertyObjects public List<ISerializableEntity> AllPropertyObjects
{ {
get get
{ {
List<IPropertyObject> pobjects = new List<IPropertyObject>(); List<ISerializableEntity> pobjects = new List<ISerializableEntity>();
pobjects.Add(this); pobjects.Add(this);
foreach (ItemComponent ic in components) foreach (ItemComponent ic in components)
{ {
@@ -359,7 +356,7 @@ namespace Barotrauma
XElement element = prefab.ConfigElement; XElement element = prefab.ConfigElement;
if (element == null) return; if (element == null) return;
properties = ObjectProperty.DeserializeProperties(this, element); properties = SerializableProperty.DeserializeProperties(this, element);
if (submarine == null || !submarine.Loading) FindHull(); if (submarine == null || !submarine.Loading) FindHull();
@@ -457,14 +454,14 @@ namespace Barotrauma
public override MapEntity Clone() public override MapEntity Clone()
{ {
Item clone = new Item(rect, prefab, Submarine); Item clone = new Item(rect, prefab, Submarine);
foreach (KeyValuePair<string, ObjectProperty> property in properties) foreach (KeyValuePair<string, SerializableProperty> property in properties)
{ {
if (!property.Value.Attributes.OfType<Editable>().Any()) continue; if (!property.Value.Attributes.OfType<Editable>().Any()) continue;
clone.properties[property.Key].TrySetValue(property.Value.GetValue()); clone.properties[property.Key].TrySetValue(property.Value.GetValue());
} }
for (int i = 0; i < components.Count; i++) for (int i = 0; i < components.Count; i++)
{ {
foreach (KeyValuePair<string, ObjectProperty> property in components[i].properties) foreach (KeyValuePair<string, SerializableProperty> property in components[i].properties)
{ {
if (!property.Value.Attributes.OfType<Editable>().Any()) continue; if (!property.Value.Attributes.OfType<Editable>().Any()) continue;
clone.components[i].properties[property.Key].TrySetValue(property.Value.GetValue()); clone.components[i].properties[property.Key].TrySetValue(property.Value.GetValue());
@@ -706,7 +703,7 @@ namespace Barotrauma
} }
} }
List<IPropertyObject> targets = new List<IPropertyObject>(); List<ISerializableEntity> targets = new List<ISerializableEntity>();
if (containedItems != null) if (containedItems != null)
{ {
if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained)) if (effect.Targets.HasFlag(StatusEffect.TargetType.Contained))
@@ -1235,13 +1232,13 @@ namespace Barotrauma
} }
public List<ObjectProperty> GetProperties<T>() public List<SerializableProperty> GetProperties<T>()
{ {
List<ObjectProperty> editableProperties = ObjectProperty.GetProperties<T>(this); List<SerializableProperty> editableProperties = SerializableProperty.GetProperties<T>(this);
foreach (ItemComponent ic in components) foreach (ItemComponent ic in components)
{ {
List<ObjectProperty> componentProperties = ObjectProperty.GetProperties<T>(ic); List<SerializableProperty> componentProperties = SerializableProperty.GetProperties<T>(ic);
foreach (var property in componentProperties) foreach (var property in componentProperties)
{ {
editableProperties.Add(property); editableProperties.Add(property);
@@ -1355,15 +1352,15 @@ namespace Barotrauma
private void WritePropertyChange(NetBuffer msg, object[] extraData) private void WritePropertyChange(NetBuffer msg, object[] extraData)
{ {
var allProperties = GetProperties<InGameEditable>(); var allProperties = GetProperties<InGameEditable>();
ObjectProperty objectProperty = extraData[1] as ObjectProperty; SerializableProperty property = extraData[1] as SerializableProperty;
if (objectProperty != null) if (property != null)
{ {
if (allProperties.Count > 1) if (allProperties.Count > 1)
{ {
msg.WriteRangedInteger(0, allProperties.Count - 1, allProperties.IndexOf(objectProperty)); msg.WriteRangedInteger(0, allProperties.Count - 1, allProperties.IndexOf(property));
} }
object value = objectProperty.GetValue(); object value = property.GetValue();
if (value is string) if (value is string)
{ {
msg.Write((string)value); msg.Write((string)value);
@@ -1398,24 +1395,24 @@ namespace Barotrauma
propertyIndex = msg.ReadRangedInteger(0, allProperties.Count-1); propertyIndex = msg.ReadRangedInteger(0, allProperties.Count-1);
} }
ObjectProperty objectProperty = allProperties[propertyIndex]; SerializableProperty property = allProperties[propertyIndex];
Type type = objectProperty.PropertyType; Type type = property.PropertyType;
if (type == typeof(string)) if (type == typeof(string))
{ {
objectProperty.TrySetValue(msg.ReadString()); property.TrySetValue(msg.ReadString());
} }
else if (type == typeof(float)) else if (type == typeof(float))
{ {
objectProperty.TrySetValue(msg.ReadFloat()); property.TrySetValue(msg.ReadFloat());
} }
else if (type == typeof(int)) else if (type == typeof(int))
{ {
objectProperty.TrySetValue(msg.ReadInt32()); property.TrySetValue(msg.ReadInt32());
} }
else if (type == typeof(bool)) else if (type == typeof(bool))
{ {
objectProperty.TrySetValue(msg.ReadBoolean()); property.TrySetValue(msg.ReadBoolean());
} }
else else
{ {
@@ -1424,7 +1421,7 @@ namespace Barotrauma
if (GameMain.Server != null) if (GameMain.Server != null)
{ {
GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, objectProperty }); GameMain.Server.CreateEntityEvent(this, new object[] { NetEntityEvent.Type.ChangeProperty, property });
} }
} }
@@ -1638,12 +1635,12 @@ namespace Barotrauma
foreach (XAttribute attribute in element.Attributes()) foreach (XAttribute attribute in element.Attributes())
{ {
ObjectProperty property = null; SerializableProperty property = null;
if (!item.properties.TryGetValue(attribute.Name.ToString(), out property)) continue; if (!item.properties.TryGetValue(attribute.Name.ToString(), out property)) continue;
bool shouldBeLoaded = false; bool shouldBeLoaded = false;
foreach (var propertyAttribute in property.Attributes.OfType<SerializableProperty>()) foreach (var propertyAttribute in property.Attributes.OfType<Serialize>())
{ {
if (propertyAttribute.isSaveable) if (propertyAttribute.isSaveable)
{ {
@@ -1713,7 +1710,7 @@ namespace Barotrauma
element.Add(new XAttribute("linked", string.Join(",", linkedToIDs))); element.Add(new XAttribute("linked", string.Join(",", linkedToIDs)));
} }
ObjectProperty.SerializeProperties(this, element); SerializableProperty.SerializeProperties(this, element);
foreach (ItemComponent ic in components) foreach (ItemComponent ic in components)
{ {
@@ -289,7 +289,7 @@ namespace Barotrauma
string spriteColorStr = element.GetAttributeString("spritecolor", "1.0,1.0,1.0,1.0"); string spriteColorStr = element.GetAttributeString("spritecolor", "1.0,1.0,1.0,1.0");
SpriteColor = new Color(XMLExtensions.ParseToVector4(spriteColorStr)); SpriteColor = new Color(XMLExtensions.ParseVector4(spriteColorStr));
price = element.GetAttributeInt("price", 0); price = element.GetAttributeInt("price", 0);
@@ -8,7 +8,7 @@ using System.Xml.Linq;
namespace Barotrauma namespace Barotrauma
{ {
partial class Hull : MapEntity, IPropertyObject, IServerSerializable partial class Hull : MapEntity, ISerializableEntity, IServerSerializable
{ {
const float NetworkUpdateInterval = 0.5f; const float NetworkUpdateInterval = 0.5f;
@@ -40,8 +40,8 @@ namespace Barotrauma
//how much excess water the room can contain (= more than the volume of the room) //how much excess water the room can contain (= more than the volume of the room)
public const float MaxCompress = 10000f; public const float MaxCompress = 10000f;
public readonly Dictionary<string, ObjectProperty> properties; public readonly Dictionary<string, SerializableProperty> properties;
public Dictionary<string, ObjectProperty> ObjectProperties public Dictionary<string, SerializableProperty> SerializableProperties
{ {
get { return properties; } get { return properties; }
} }
@@ -139,7 +139,7 @@ namespace Barotrauma
} }
} }
[SerializableProperty(90.0f, true)] [Serialize(90.0f, true)]
public float Oxygen public float Oxygen
{ {
get { return oxygen; } get { return oxygen; }
@@ -197,7 +197,7 @@ namespace Barotrauma
fireSources = new List<FireSource>(); fireSources = new List<FireSource>();
properties = ObjectProperty.GetProperties(this); properties = SerializableProperty.GetProperties(this);
int arraySize = (rectangle.Width / WaveWidth + 1); int arraySize = (rectangle.Width / WaveWidth + 1);
waveY = new float[arraySize]; waveY = new float[arraySize];
@@ -44,7 +44,7 @@ namespace Barotrauma
} }
} }
class LevelGenerationParams : IPropertyObject class LevelGenerationParams : ISerializableEntity
{ {
private static List<LevelGenerationParams> levelParams; private static List<LevelGenerationParams> levelParams;
private static List<Biome> biomes; private static List<Biome> biomes;
@@ -102,27 +102,27 @@ namespace Barotrauma
set; set;
} }
[SerializableProperty(1000, false)] [Serialize(1000, false)]
public int BackgroundSpriteAmount public int BackgroundSpriteAmount
{ {
get; get;
set; set;
} }
public Dictionary<string, ObjectProperty> ObjectProperties public Dictionary<string, SerializableProperty> SerializableProperties
{ {
get; get;
set; set;
} }
[SerializableProperty(100000.0f, false)] [Serialize(100000.0f, false)]
public float Width public float Width
{ {
get { return width; } get { return width; }
set { width = Math.Max(value, 2000.0f); } set { width = Math.Max(value, 2000.0f); }
} }
[SerializableProperty(50000.0f, false)] [Serialize(50000.0f, false)]
public float Height public float Height
{ {
get { return height; } get { return height; }
@@ -160,7 +160,7 @@ namespace Barotrauma
} }
} }
[SerializableProperty(5, false)] [Serialize(5, false)]
public int SmallTunnelCount public int SmallTunnelCount
{ {
get { return smallTunnelCount; } get { return smallTunnelCount; }
@@ -177,21 +177,21 @@ namespace Barotrauma
} }
} }
[SerializableProperty(-300000.0f, false)] [Serialize(-300000.0f, false)]
public float SeaFloorDepth public float SeaFloorDepth
{ {
get { return seaFloorBaseDepth; } get { return seaFloorBaseDepth; }
set { seaFloorBaseDepth = MathHelper.Clamp(value, Level.MaxEntityDepth, 0.0f); } set { seaFloorBaseDepth = MathHelper.Clamp(value, Level.MaxEntityDepth, 0.0f); }
} }
[SerializableProperty(1000.0f, false)] [Serialize(1000.0f, false)]
public float SeaFloorVariance public float SeaFloorVariance
{ {
get { return seaFloorVariance; } get { return seaFloorVariance; }
set { seaFloorVariance = value; } set { seaFloorVariance = value; }
} }
[SerializableProperty(0, false)] [Serialize(0, false)]
public int MountainCountMin public int MountainCountMin
{ {
get { return mountainCountMin; } get { return mountainCountMin; }
@@ -201,7 +201,7 @@ namespace Barotrauma
} }
} }
[SerializableProperty(0, false)] [Serialize(0, false)]
public int MountainCountMax public int MountainCountMax
{ {
get { return mountainCountMax; } get { return mountainCountMax; }
@@ -211,7 +211,7 @@ namespace Barotrauma
} }
} }
[SerializableProperty(1000.0f, false)] [Serialize(1000.0f, false)]
public float MountainHeightMin public float MountainHeightMin
{ {
get { return mountainHeightMin; } get { return mountainHeightMin; }
@@ -221,7 +221,7 @@ namespace Barotrauma
} }
} }
[SerializableProperty(5000.0f, false)] [Serialize(5000.0f, false)]
public float MountainHeightMax public float MountainHeightMax
{ {
get { return mountainHeightMax; } get { return mountainHeightMax; }
@@ -231,14 +231,14 @@ namespace Barotrauma
} }
} }
[SerializableProperty(1, false)] [Serialize(1, false)]
public int RuinCount public int RuinCount
{ {
get { return ruinCount; } get { return ruinCount; }
set { ruinCount = MathHelper.Clamp(value, 0, 10); } set { ruinCount = MathHelper.Clamp(value, 0, 10); }
} }
[SerializableProperty(0.4f, false)] [Serialize(0.4f, false)]
public float BottomHoleProbability public float BottomHoleProbability
{ {
get { return bottomHoleProbability; } get { return bottomHoleProbability; }
@@ -278,7 +278,7 @@ namespace Barotrauma
private LevelGenerationParams(XElement element) private LevelGenerationParams(XElement element)
{ {
Name = element == null ? "default" : element.Name.ToString(); Name = element == null ? "default" : element.Name.ToString();
ObjectProperties = ObjectProperty.DeserializeProperties(this, element); SerializableProperties = SerializableProperty.DeserializeProperties(this, element);
Vector3 colorVector = element.GetAttributeVector3("BackgroundColor", new Vector3(50, 46, 20)); Vector3 colorVector = element.GetAttributeVector3("BackgroundColor", new Vector3(50, 46, 20));
BackgroundColor = new Color((int)colorVector.X, (int)colorVector.Y, (int)colorVector.Z); BackgroundColor = new Color((int)colorVector.X, (int)colorVector.Y, (int)colorVector.Z);
@@ -132,7 +132,7 @@ namespace Barotrauma
sp.size.Y = element.GetAttributeFloat("height", 0.0f); sp.size.Y = element.GetAttributeFloat("height", 0.0f);
string spriteColorStr = element.GetAttributeString("spritecolor", "1.0,1.0,1.0,1.0"); string spriteColorStr = element.GetAttributeString("spritecolor", "1.0,1.0,1.0,1.0");
sp.SpriteColor = new Color(XMLExtensions.ParseToVector4(spriteColorStr)); sp.SpriteColor = new Color(XMLExtensions.ParseVector4(spriteColorStr));
sp.maxHealth = element.GetAttributeFloat("health", 100.0f); sp.maxHealth = element.GetAttributeFloat("health", 100.0f);
@@ -26,7 +26,7 @@ namespace Barotrauma.Networking
} }
} }
partial class GameServer : NetworkMember, IPropertyObject partial class GameServer : NetworkMember, ISerializableEntity
{ {
List<UnauthenticatedClient> unauthenticatedClients = new List<UnauthenticatedClient>(); List<UnauthenticatedClient> unauthenticatedClients = new List<UnauthenticatedClient>();
@@ -19,7 +19,7 @@ namespace Barotrauma.Networking
No = 0, Maybe = 1, Yes = 2 No = 0, Maybe = 1, Yes = 2
} }
partial class GameServer : NetworkMember, IPropertyObject partial class GameServer : NetworkMember, ISerializableEntity
{ {
private class SavedClientPermission private class SavedClientPermission
{ {
@@ -40,7 +40,7 @@ namespace Barotrauma.Networking
public const string SettingsFile = "serversettings.xml"; public const string SettingsFile = "serversettings.xml";
public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.txt"; public static readonly string ClientPermissionsFile = "Data" + Path.DirectorySeparatorChar + "clientpermissions.txt";
public Dictionary<string, ObjectProperty> ObjectProperties public Dictionary<string, SerializableProperty> SerializableProperties
{ {
get; get;
private set; private set;
@@ -86,7 +86,7 @@ namespace Barotrauma.Networking
private List<SavedClientPermission> clientPermissions = new List<SavedClientPermission>(); private List<SavedClientPermission> clientPermissions = new List<SavedClientPermission>();
[SerializableProperty(true, true)] [Serialize(true, true)]
public bool RandomizeSeed public bool RandomizeSeed
{ {
get; get;
@@ -94,21 +94,21 @@ namespace Barotrauma.Networking
} }
[SerializableProperty(300.0f, true)] [Serialize(300.0f, true)]
public float RespawnInterval public float RespawnInterval
{ {
get; get;
private set; private set;
} }
[SerializableProperty(180.0f, true)] [Serialize(180.0f, true)]
public float MaxTransportTime public float MaxTransportTime
{ {
get; get;
private set; private set;
} }
[SerializableProperty(0.2f, true)] [Serialize(0.2f, true)]
public float MinRespawnRatio public float MinRespawnRatio
{ {
get; get;
@@ -116,42 +116,42 @@ namespace Barotrauma.Networking
} }
[SerializableProperty(60.0f, true)] [Serialize(60.0f, true)]
public float AutoRestartInterval public float AutoRestartInterval
{ {
get; get;
set; set;
} }
[SerializableProperty(true, true)] [Serialize(true, true)]
public bool AllowSpectating public bool AllowSpectating
{ {
get; get;
private set; private set;
} }
[SerializableProperty(true, true)] [Serialize(true, true)]
public bool EndRoundAtLevelEnd public bool EndRoundAtLevelEnd
{ {
get; get;
private set; private set;
} }
[SerializableProperty(true, true)] [Serialize(true, true)]
public bool SaveServerLogs public bool SaveServerLogs
{ {
get; get;
private set; private set;
} }
[SerializableProperty(true, true)] [Serialize(true, true)]
public bool AllowFileTransfers public bool AllowFileTransfers
{ {
get; get;
private set; private set;
} }
[SerializableProperty(800, true)] [Serialize(800, true)]
private int LinesPerLogFile private int LinesPerLogFile
{ {
get get
@@ -175,7 +175,7 @@ namespace Barotrauma.Networking
} }
} }
[SerializableProperty(true, true)] [Serialize(true, true)]
public bool AllowRespawn public bool AllowRespawn
{ {
get; get;
@@ -203,21 +203,21 @@ namespace Barotrauma.Networking
get { return banList; } get { return banList; }
} }
[SerializableProperty(true, true)] [Serialize(true, true)]
public bool AllowVoteKick public bool AllowVoteKick
{ {
get; get;
private set; private set;
} }
[SerializableProperty(0.6f, true)] [Serialize(0.6f, true)]
public float EndVoteRequiredRatio public float EndVoteRequiredRatio
{ {
get; get;
private set; private set;
} }
[SerializableProperty(0.6f, true)] [Serialize(0.6f, true)]
public float KickVoteRequiredRatio public float KickVoteRequiredRatio
{ {
get; get;
@@ -228,7 +228,7 @@ namespace Barotrauma.Networking
{ {
XDocument doc = new XDocument(new XElement("serversettings")); XDocument doc = new XDocument(new XElement("serversettings"));
ObjectProperty.SerializeProperties(this, doc.Root, true); SerializableProperty.SerializeProperties(this, doc.Root, true);
doc.Root.SetAttributeValue("name", name); doc.Root.SetAttributeValue("name", name);
doc.Root.SetAttributeValue("public", isPublic); doc.Root.SetAttributeValue("public", isPublic);
@@ -279,7 +279,7 @@ namespace Barotrauma.Networking
doc = new XDocument(new XElement("serversettings")); doc = new XDocument(new XElement("serversettings"));
} }
ObjectProperties = ObjectProperty.DeserializeProperties(this, doc.Root); SerializableProperties = SerializableProperty.DeserializeProperties(this, doc.Root);
AutoRestart = doc.Root.GetAttributeBool("autorestart", false); AutoRestart = doc.Root.GetAttributeBool("autorestart", false);
#if CLIENT #if CLIENT
@@ -2,14 +2,14 @@
namespace Barotrauma namespace Barotrauma
{ {
interface IPropertyObject interface ISerializableEntity
{ {
string Name string Name
{ {
get; get;
} }
Dictionary<string, ObjectProperty> ObjectProperties Dictionary<string, SerializableProperty> SerializableProperties
{ {
get; get;
} }
@@ -1,385 +0,0 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
namespace Barotrauma
{
[AttributeUsage(AttributeTargets.Property)]
public class Editable : System.Attribute
{
public int MaxLength;
public Editable(int maxLength = 20)
{
MaxLength = maxLength;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class InGameEditable : Editable
{
}
[AttributeUsage(AttributeTargets.Property)]
public class SerializableProperty : System.Attribute
{
public object defaultValue;
public bool isSaveable;
public SerializableProperty(object defaultValue, bool isSaveable)
{
this.defaultValue = defaultValue;
this.isSaveable = isSaveable;
}
}
class ObjectProperty
{
private readonly PropertyDescriptor propertyDescriptor;
private readonly PropertyInfo propertyInfo;
private readonly object obj;
public string Name
{
get { return propertyDescriptor.Name; }
}
public AttributeCollection Attributes
{
get { return propertyDescriptor.Attributes; }
}
public Type PropertyType
{
get
{
return propertyInfo.PropertyType;
}
}
public ObjectProperty(PropertyDescriptor property, object obj)
{
this.propertyDescriptor = property;
propertyInfo = property.ComponentType.GetProperty(property.Name);
this.obj = obj;
}
public bool TrySetValue(string value)
{
if (value == null) return false;
if (propertyDescriptor.PropertyType == typeof(string))
{
propertyInfo.SetValue(obj, value, null);
}
else if (propertyDescriptor.PropertyType == typeof(float))
{
float floatVal;
if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out floatVal))
{
propertyInfo.SetValue(obj, floatVal, null);
}
}
else if (propertyDescriptor.PropertyType == typeof(bool))
{
propertyInfo.SetValue(obj, value.ToLowerInvariant() == "true", null);
}
else if (propertyDescriptor.PropertyType == typeof(int))
{
int intVal;
if (int.TryParse(value, out intVal))
{
propertyInfo.SetValue(obj, intVal, null);
}
}
else if (propertyDescriptor.PropertyType == typeof(Vector2))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToVector2(value));
}
else if (propertyDescriptor.PropertyType == typeof(Vector3))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToVector3(value));
}
else if (propertyDescriptor.PropertyType == typeof(Vector4))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToVector4(value));
}
else if (propertyDescriptor.PropertyType == typeof(Color))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToColor(value));
}
else if (propertyDescriptor.PropertyType.IsEnum)
{
object enumVal;
try
{
enumVal = Enum.Parse(propertyInfo.PropertyType, value);
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj + "\" to " + value + " (not a valid " + propertyInfo.PropertyType + ")", e);
return false;
}
propertyInfo.SetValue(obj, enumVal);
}
else
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj + "\" to " + value);
DebugConsole.ThrowError("(Type not implemented)");
return false;
}
return true;
}
public bool TrySetValue(object value)
{
if (value == null) return false;
if (obj == null || propertyDescriptor == null) return false;
try
{
if (value.GetType() == typeof(string) &&
propertyDescriptor.PropertyType == typeof(Vector2))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToVector2(value.ToString()));
}
else if (value.GetType() == typeof(string) &&
propertyDescriptor.PropertyType == typeof(Vector3))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToVector3(value.ToString()));
}
else if (value.GetType() == typeof(string) &&
propertyDescriptor.PropertyType == typeof(Vector4))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToVector4(value.ToString()));
}
else if (value.GetType() == typeof(string) &&
propertyDescriptor.PropertyType == typeof(Color))
{
propertyInfo.SetValue(obj, XMLExtensions.ParseToColor(value.ToString()));
}
else if (propertyDescriptor.PropertyType != value.GetType())
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj.ToString() + "\" to " + value.ToString());
DebugConsole.ThrowError("(Non-matching type, should be " + propertyDescriptor.PropertyType + " instead of " + value.GetType() + ")");
return false;
}
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(float value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(bool value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(int value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public object GetValue()
{
if (obj == null || propertyDescriptor == null) return false;
try
{
return propertyInfo.GetValue(obj, null);
}
catch
{
return false;
}
}
public static List<ObjectProperty> GetProperties<T>(IPropertyObject obj)
{
List<ObjectProperty> editableProperties = new List<ObjectProperty>();
foreach (var property in obj.ObjectProperties.Values)
{
if (property.Attributes.OfType<T>().Any()) editableProperties.Add(property);
}
return editableProperties;
}
public static Dictionary<string, ObjectProperty> GetProperties(IPropertyObject obj)
{
var properties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
Dictionary<string, ObjectProperty> dictionary = new Dictionary<string, ObjectProperty>();
foreach (var property in properties)
{
dictionary.Add(property.Name.ToLowerInvariant(), new ObjectProperty(property, obj));
}
return dictionary;
}
/*/// <summary>
/// Sets all serializable properties to their default value
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static Dictionary<string, ObjectProperty> InitProperties(IPropertyObject obj)
{
return DeserializeProperties(obj, null);
}*/
public static Dictionary<string, ObjectProperty> DeserializeProperties(IPropertyObject obj, XElement element)
{
var properties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
Dictionary<string, ObjectProperty> dictionary = new Dictionary<string, ObjectProperty>();
foreach (var property in properties)
{
ObjectProperty objProperty = new ObjectProperty(property, obj);
dictionary.Add(property.Name.ToLowerInvariant(), objProperty);
//set the value of the property to the default value if there is one
foreach (var ini in property.Attributes.OfType<SerializableProperty>())
{
objProperty.TrySetValue(ini.defaultValue);
break;
}
}
if (element != null)
{
//go through all the attributes in the xml element
//and set the value of the matching property if it is initializable
foreach (XAttribute attribute in element.Attributes())
{
ObjectProperty property = null;
if (!dictionary.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out property)) continue;
if (!property.Attributes.OfType<SerializableProperty>().Any()) continue;
property.TrySetValue(attribute.Value);
}
}
return dictionary;
}
public static void SerializeProperties(IPropertyObject obj, XElement element, bool saveIfDefault = false)
{
var saveProperties = GetProperties<SerializableProperty>(obj);
foreach (var property in saveProperties)
{
object value = property.GetValue();
if (value == null) continue;
if (!saveIfDefault)
{
//only save
// - if the attribute is saveable and it's different from the default value
// - or can be changed in-game or in the editor
bool save = false;
foreach (var attribute in property.Attributes.OfType<SerializableProperty>())
{
if ((attribute.isSaveable && !attribute.defaultValue.Equals(value)) ||
property.Attributes.OfType<Editable>().Any())
{
save = true;
break;
}
}
if (!save) continue;
}
string stringValue;
if (value.GetType() == typeof(float))
{
//make sure the decimal point isn't converted to a comma or anything else
stringValue = ((float)value).ToString("G", CultureInfo.InvariantCulture);
}
else if (value.GetType() == typeof(Vector2))
{
Vector2 vector = (Vector2)value;
stringValue =
vector.X.ToString("G", CultureInfo.InvariantCulture) + "," +
vector.Y.ToString("G", CultureInfo.InvariantCulture);
}
else if (value.GetType() == typeof(Vector3))
{
Vector3 vector = (Vector3)value;
stringValue =
vector.X.ToString("G", CultureInfo.InvariantCulture) + "," +
vector.Y.ToString("G", CultureInfo.InvariantCulture) + "," +
vector.Z.ToString("G", CultureInfo.InvariantCulture);
}
else if (value.GetType() == typeof(Vector4))
{
Vector4 vector = (Vector4)value;
stringValue =
vector.X.ToString("G", CultureInfo.InvariantCulture) + "," +
vector.Y.ToString("G", CultureInfo.InvariantCulture) + "," +
vector.Z.ToString("G", CultureInfo.InvariantCulture) + "," +
vector.W.ToString("G", CultureInfo.InvariantCulture);
}
else if (value.GetType() == typeof(Color))
{
Color color = (Color)value;
stringValue =
(color.R / 255.0f).ToString("G", CultureInfo.InvariantCulture) + "," +
(color.G / 255.0f).ToString("G", CultureInfo.InvariantCulture) + "," +
(color.B / 255.0f).ToString("G", CultureInfo.InvariantCulture) + "," +
(color.A / 255.0f).ToString("G", CultureInfo.InvariantCulture);
}
else
{
stringValue = value.ToString();
}
element.Add(new XAttribute(property.Name.ToLowerInvariant(), stringValue));
}
}
}
}
@@ -0,0 +1,449 @@
using Microsoft.Xna.Framework;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
namespace Barotrauma
{
[AttributeUsage(AttributeTargets.Property)]
public class Editable : Attribute
{
public int MaxLength;
public int? MinValueInt, MaxValueInt;
public float? MinValueFloat, MaxValueFloat;
public Editable(int maxLength = 20)
{
MaxLength = maxLength;
}
public Editable(int? minValue, int? maxValue)
{
MinValueInt = minValue;
MaxValueInt = maxValue;
}
public Editable(float? minValue, float? maxValue)
{
MinValueFloat = minValue;
MaxValueFloat = maxValue;
}
}
[AttributeUsage(AttributeTargets.Property)]
public class InGameEditable : Editable
{
}
[AttributeUsage(AttributeTargets.Property)]
public class Serialize : Attribute
{
public object defaultValue;
public bool isSaveable;
public Serialize(object defaultValue, bool isSaveable)
{
this.defaultValue = defaultValue;
this.isSaveable = isSaveable;
}
}
class SerializableProperty
{
private static Dictionary<Type, string> supportedTypes = new Dictionary<Type, string>
{
{ typeof(bool), "bool" },
{ typeof(int), "int" },
{ typeof(float), "float" },
{ typeof(string), "string" },
{ typeof(Vector2), "vector2" },
{ typeof(Vector3), "vector3" },
{ typeof(Vector4), "vector4" },
{ typeof(Rectangle), "rectangle" },
{ typeof(Color), "color" },
};
private readonly PropertyDescriptor propertyDescriptor;
private readonly PropertyInfo propertyInfo;
private readonly object obj;
public string Name
{
get { return propertyDescriptor.Name; }
}
public AttributeCollection Attributes
{
get { return propertyDescriptor.Attributes; }
}
public Type PropertyType
{
get
{
return propertyInfo.PropertyType;
}
}
public SerializableProperty(PropertyDescriptor property, object obj)
{
this.propertyDescriptor = property;
propertyInfo = property.ComponentType.GetProperty(property.Name);
this.obj = obj;
}
public T GetAttribute<T>() where T : Attribute
{
foreach (Attribute a in Attributes)
{
if (a is T) return (T)a;
}
return default(T);
}
public bool TrySetValue(string value)
{
if (value == null) return false;
string typeName;
if (!supportedTypes.TryGetValue(propertyDescriptor.PropertyType, out typeName))
{
if (propertyDescriptor.PropertyType.IsEnum)
{
object enumVal;
try
{
enumVal = Enum.Parse(propertyInfo.PropertyType, value);
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj + "\" to " + value + " (not a valid " + propertyInfo.PropertyType + ")", e);
return false;
}
propertyInfo.SetValue(obj, enumVal);
}
else
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj + "\" to " + value);
DebugConsole.ThrowError("(Type not supported)");
return false;
}
}
switch (typeName)
{
case "bool":
propertyInfo.SetValue(obj, value.ToLowerInvariant() == "true", null);
break;
case "int":
int intVal;
if (int.TryParse(value, out intVal))
{
propertyInfo.SetValue(obj, intVal, null);
}
break;
case "float":
float floatVal;
if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out floatVal))
{
propertyInfo.SetValue(obj, floatVal, null);
}
break;
case "string":
propertyInfo.SetValue(obj, value, null);
break;
case "vector2":
propertyInfo.SetValue(obj, XMLExtensions.ParseVector2(value));
break;
case "vector3":
propertyInfo.SetValue(obj, XMLExtensions.ParseVector3(value));
break;
case "vector4":
propertyInfo.SetValue(obj, XMLExtensions.ParseVector4(value));
break;
case "color":
propertyInfo.SetValue(obj, XMLExtensions.ParseColor(value));
break;
case "rectangle":
propertyInfo.SetValue(obj, XMLExtensions.ParseRect(value));
break;
}
return true;
}
public bool TrySetValue(object value)
{
if (value == null || obj == null || propertyDescriptor == null) return false;
try
{
string typeName;
if (!supportedTypes.TryGetValue(propertyDescriptor.PropertyType, out typeName))
{
if (propertyDescriptor.PropertyType.IsEnum)
{
object enumVal;
try
{
enumVal = Enum.Parse(propertyInfo.PropertyType, value.ToString());
}
catch (Exception e)
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj + "\" to " + value + " (not a valid " + propertyInfo.PropertyType + ")", e);
return false;
}
propertyInfo.SetValue(obj, enumVal);
}
else
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj + "\" to " + value);
DebugConsole.ThrowError("(Type not supported)");
return false;
}
}
if (value.GetType() == typeof(string))
{
switch (typeName)
{
case "string":
propertyInfo.SetValue(obj, value, null);
return true;
case "vector2":
propertyInfo.SetValue(obj, XMLExtensions.ParseVector2((string)value));
return true;
case "vector3":
propertyInfo.SetValue(obj, XMLExtensions.ParseVector3((string)value));
return true;
case "vector4":
propertyInfo.SetValue(obj, XMLExtensions.ParseVector4((string)value));
return true;
case "color":
propertyInfo.SetValue(obj, XMLExtensions.ParseColor((string)value));
return true;
case "rectangle":
propertyInfo.SetValue(obj, XMLExtensions.ParseColor((string)value));
return true;
default:
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj.ToString() + "\" to " + value.ToString());
DebugConsole.ThrowError("(Cannot convert a string to a " + propertyDescriptor.PropertyType.ToString() + ")");
return false;
}
}
else if (propertyDescriptor.PropertyType != value.GetType())
{
DebugConsole.ThrowError("Failed to set the value of the property \"" + Name + "\" of \"" + obj.ToString() + "\" to " + value.ToString());
DebugConsole.ThrowError("(Non-matching type, should be " + propertyDescriptor.PropertyType + " instead of " + value.GetType() + ")");
return false;
}
propertyInfo.SetValue(obj, value, null);
return true;
}
catch
{
return false;
}
}
public bool TrySetValue(float value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(bool value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public bool TrySetValue(int value)
{
try
{
propertyInfo.SetValue(obj, value, null);
}
catch
{
return false;
}
return true;
}
public object GetValue()
{
if (obj == null || propertyDescriptor == null) return false;
try
{
return propertyInfo.GetValue(obj, null);
}
catch
{
return false;
}
}
public static List<SerializableProperty> GetProperties<T>(ISerializableEntity obj)
{
List<SerializableProperty> editableProperties = new List<SerializableProperty>();
foreach (var property in obj.SerializableProperties.Values)
{
if (property.Attributes.OfType<T>().Any()) editableProperties.Add(property);
}
return editableProperties;
}
public static Dictionary<string, SerializableProperty> GetProperties(ISerializableEntity obj)
{
var properties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
Dictionary<string, SerializableProperty> dictionary = new Dictionary<string, SerializableProperty>();
foreach (var property in properties)
{
dictionary.Add(property.Name.ToLowerInvariant(), new SerializableProperty(property, obj));
}
return dictionary;
}
public static Dictionary<string, SerializableProperty> DeserializeProperties(ISerializableEntity obj, XElement element)
{
var properties = TypeDescriptor.GetProperties(obj.GetType()).Cast<PropertyDescriptor>();
Dictionary<string, SerializableProperty> dictionary = new Dictionary<string, SerializableProperty>();
foreach (var property in properties)
{
SerializableProperty objProperty = new SerializableProperty(property, obj);
dictionary.Add(property.Name.ToLowerInvariant(), objProperty);
//set the value of the property to the default value if there is one
foreach (var ini in property.Attributes.OfType<Serialize>())
{
objProperty.TrySetValue(ini.defaultValue);
break;
}
}
if (element != null)
{
//go through all the attributes in the xml element
//and set the value of the matching property if it is initializable
foreach (XAttribute attribute in element.Attributes())
{
SerializableProperty property = null;
if (!dictionary.TryGetValue(attribute.Name.ToString().ToLowerInvariant(), out property)) continue;
if (!property.Attributes.OfType<Serialize>().Any()) continue;
property.TrySetValue(attribute.Value);
}
}
return dictionary;
}
public static void SerializeProperties(ISerializableEntity obj, XElement element, bool saveIfDefault = false)
{
var saveProperties = GetProperties<Serialize>(obj);
foreach (var property in saveProperties)
{
object value = property.GetValue();
if (value == null) continue;
if (!saveIfDefault)
{
//only save
// - if the attribute is saveable and it's different from the default value
// - or can be changed in-game or in the editor
bool save = false;
foreach (var attribute in property.Attributes.OfType<Serialize>())
{
if ((attribute.isSaveable && !attribute.defaultValue.Equals(value)) ||
property.Attributes.OfType<Editable>().Any())
{
save = true;
break;
}
}
if (!save) continue;
}
string stringValue;
string typeName;
if (!supportedTypes.TryGetValue(value.GetType(), out typeName))
{
if (property.PropertyType.IsEnum)
{
stringValue = value.ToString();
}
else
{
DebugConsole.ThrowError("Failed to serialize the property \"" + property.Name + "\" of \"" + obj + "\" (type " + property.PropertyType + " not supported)");
continue;
}
}
else
{
switch (typeName)
{
case "float":
//make sure the decimal point isn't converted to a comma or anything else
stringValue = ((float)value).ToString("G", CultureInfo.InvariantCulture);
break;
case "vector2":
stringValue = XMLExtensions.Vector2ToString((Vector2)value);
break;
case "vector3":
stringValue = XMLExtensions.Vector3ToString((Vector3)value);
break;
case "vector4":
stringValue = XMLExtensions.Vector4ToString((Vector4)value);
break;
case "color":
stringValue = XMLExtensions.ColorToString((Color)value);
break;
case "rectangle":
stringValue = XMLExtensions.RectToString((Rectangle)value);
break;
default:
stringValue = value.ToString();
break;
}
}
element.Add(new XAttribute(property.Name.ToLowerInvariant(), stringValue));
}
}
}
}
@@ -192,7 +192,7 @@ namespace Barotrauma
string val = element.Attribute(name).Value; string val = element.Attribute(name).Value;
return ParseToVector2(val); return ParseVector2(val);
} }
public static Vector3 GetAttributeVector3(this XElement element, string name, Vector3 defaultValue) public static Vector3 GetAttributeVector3(this XElement element, string name, Vector3 defaultValue)
@@ -201,7 +201,7 @@ namespace Barotrauma
string val = element.Attribute(name).Value; string val = element.Attribute(name).Value;
return ParseToVector3(val); return ParseVector3(val);
} }
public static Vector4 GetAttributeVector4(this XElement element, string name, Vector4 defaultValue) public static Vector4 GetAttributeVector4(this XElement element, string name, Vector4 defaultValue)
@@ -210,7 +210,7 @@ namespace Barotrauma
string val = element.Attribute(name).Value; string val = element.Attribute(name).Value;
return ParseToVector4(val); return ParseVector4(val);
} }
public static string ElementInnerText(this XElement el) public static string ElementInnerText(this XElement el)
@@ -223,8 +223,40 @@ namespace Barotrauma
return str.ToString(); return str.ToString();
} }
public static string Vector2ToString(Vector2 vector)
{
return vector.X.ToString("G", CultureInfo.InvariantCulture) + "," + vector.Y.ToString("G", CultureInfo.InvariantCulture);
}
public static Vector2 ParseToVector2(string stringVector2, bool errorMessages = true) public static string Vector3ToString(Vector3 vector, string format = "G")
{
return vector.X.ToString(format, CultureInfo.InvariantCulture) + "," +
vector.Y.ToString(format, CultureInfo.InvariantCulture) + "," +
vector.Z.ToString(format, CultureInfo.InvariantCulture);
}
public static string Vector4ToString(Vector4 vector, string format = "G")
{
return vector.X.ToString(format, CultureInfo.InvariantCulture) + "," +
vector.Y.ToString(format, CultureInfo.InvariantCulture) + "," +
vector.Z.ToString(format, CultureInfo.InvariantCulture) + "," +
vector.W.ToString(format, CultureInfo.InvariantCulture);
}
public static string ColorToString(Color color)
{
return (color.R / 255.0f).ToString("G", CultureInfo.InvariantCulture) + "," +
(color.G / 255.0f).ToString("G", CultureInfo.InvariantCulture) + "," +
(color.B / 255.0f).ToString("G", CultureInfo.InvariantCulture) + "," +
(color.A / 255.0f).ToString("G", CultureInfo.InvariantCulture);
}
public static string RectToString(Rectangle rect)
{
return rect.X + "," + rect.Y + "," + rect.Width + "," + rect.Height;
}
public static Vector2 ParseVector2(string stringVector2, bool errorMessages = true)
{ {
string[] components = stringVector2.Split(','); string[] components = stringVector2.Split(',');
@@ -237,18 +269,13 @@ namespace Barotrauma
return vector; return vector;
} }
Single.TryParse(components[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.X); float.TryParse(components[0], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.X);
Single.TryParse(components[1], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.Y); float.TryParse(components[1], NumberStyles.Any, CultureInfo.InvariantCulture, out vector.Y);
return vector; return vector;
} }
public static string Vector2ToString(Vector2 vector) public static Vector3 ParseVector3(string stringVector3, bool errorMessages = true)
{
return vector.X.ToString("G", CultureInfo.InvariantCulture) + "," + vector.Y.ToString("G", CultureInfo.InvariantCulture);
}
public static Vector3 ParseToVector3(string stringVector3, bool errorMessages = true)
{ {
string[] components = stringVector3.Split(','); string[] components = stringVector3.Split(',');
@@ -268,7 +295,7 @@ namespace Barotrauma
return vector; return vector;
} }
public static Vector4 ParseToVector4(string stringVector4, bool errorMessages = true) public static Vector4 ParseVector4(string stringVector4, bool errorMessages = true)
{ {
string[] components = stringVector4.Split(','); string[] components = stringVector4.Split(',');
@@ -289,7 +316,7 @@ namespace Barotrauma
return vector; return vector;
} }
public static Color ParseToColor(string stringColor, bool errorMessages = true) public static Color ParseColor(string stringColor, bool errorMessages = true)
{ {
string[] strComponents = stringColor.Split(','); string[] strComponents = stringColor.Split(',');
@@ -311,15 +338,29 @@ namespace Barotrauma
return new Color(components[0], components[1], components[2], components[3]); return new Color(components[0], components[1], components[2], components[3]);
} }
public static string Vector4ToString(Vector4 vector, string format = "G") public static Color ParseRect(string stringColor, bool errorMessages = true)
{ {
return vector.X.ToString(format, CultureInfo.InvariantCulture) + "," + string[] strComponents = stringColor.Split(',');
vector.Y.ToString(format, CultureInfo.InvariantCulture) + "," +
vector.Z.ToString(format, CultureInfo.InvariantCulture) + "," + Color color = Color.White;
vector.W.ToString(format, CultureInfo.InvariantCulture);
if (strComponents.Length < 3)
{
if (errorMessages) DebugConsole.ThrowError("Failed to parse the string \"" + stringColor + "\" to Color");
return Color.White;
}
float[] components = new float[4] { 1.0f, 1.0f, 1.0f, 1.0f };
for (int i = 0; i < 4 && i < strComponents.Length; i++)
{
float.TryParse(strComponents[i], NumberStyles.Float, CultureInfo.InvariantCulture, out components[i]);
}
return new Color(components[0], components[1], components[2], components[3]);
} }
public static float[] ParseArrayToFloat(string[] stringArray) public static float[] ParseFloatArray(string[] stringArray)
{ {
if (stringArray == null || stringArray.Length == 0) return null; if (stringArray == null || stringArray.Length == 0) return null;