Commit graph

14 commits

Author SHA1 Message Date
Kamron Batman
510d2e006b
fix(codegen): Fixes bulk order deed hue and codegens (#647)
- [X] Codegens some Bulk Order stuff
- [X] Fixes deserializing with a class that requires the parent as a constructor argument


Closes #641
Closes #623
2021-06-11 19:51:03 -07:00
Kamron Batman
75db56edc4
fix(core): Fixes accounts and moves it to codegen (#644)
- [X] Fixes TimeSpan not working with codegen
- [X] Fixes bad check for generic classes with a serialize method and deserialize ctor
- [X] Moves Accounts to codegen so it is versioned
- [X] Fixes deserialization of old Accounts with no version variable.
- [X] Fixes deserialize seek not doing anything. 🙈 
- [X] Adds Email to serialization
2021-06-05 19:39:16 -07:00
Kamron Batman
803b4a33cb
fix(codegen): Adds access modifiers to serializable fields (#633)
- [X] Adds options for SerializableField.

Example:
```cs
[SerializableField(0, getter: "protected", setter: "protected", isVritual: true)]
private int _someField;
```

Defaults: `getter: "public", setter: "public", isVirtual: false`
2021-06-01 22:53:51 -07:00
Kamron Batman
ac3958a0b8
fix(codegen): Fixes codegen on VS2019 (#629)
- [X] Fixes code gen on VS2019
- [X] Fixes schema generator not iterating through all nodes
- [X] Fixes errors with building the actual code gen
2021-05-31 16:30:17 -07:00
Kamron Batman
b6779a7c09
fix(codegen): Creates multiple steps for serialization source generator (#628)
Roslyn Source generators are not supposed to access I/O. To get around this we have to use `AdditionalFiles` to give the analyzer access to read/load the schema files.
To write the schema files we have to use a separate program altogether.

- [X] Adds SerializationSchemaGenerator
- [X] Splits out the SerializationGenerator code
2021-05-31 11:54:59 -07:00
Kamron Batman
6e9108302a
fix(content): Converts Holiday objects to codegen (#622)
- Fixes an issue with source generators
- Source generates holiday objects.
2021-05-27 11:06:03 -07:00
Kamron Batman
90dc5e742c
fix(codegen): Reverts adding dirty checking. We are not ready for this. (#620) 2021-05-26 22:01:58 -07:00
Kamron Batman
312e3873f1
fix(core): Fixes encoded int. Adds dirty checking opt-out (#619)
### Additions
- Automatically opts-out `Item/Mobile/Guild/Accounts` from dirty checking with a new property `UseDirtyChecking`
- Codegen now enables `UseDirtyChecking` via getter. This requires that the property is `virtual` for derived types.

### Fixes
- Fixes `EncodedInt` being broken
- Fixes issues with new custom serializable types that are not derived from Item/Mobile/etc.
- Removes double dirty checking.

### Example of a brand new serializable type that isn't an Item/Mobile/etc.
User created code:
```cs
using System;

namespace Server.Items
{
    [Serializable(0)]
    public partial class NewTestEntityObject : ISerializable
    {
        [EncodedInt]
        [SerializableField(0)]
        private int _someProperty;

        public NewTestEntityObject()
        {
            SetTypeRef(GetType());
            // Add to serial tracking like World.Item
            /*
            Serial = World.NewEntity;
            World.AddEntity(this);
            */
        }

        [AfterDeserialization]
        private void AfterDeserialization()
        {
            Console.WriteLine("This ran!");
        }

        public int TypeRef { get; }
        public Serial Serial { get; }
        public void Delete()
        {
        }

        public bool Deleted { get; set; }
        public void SetTypeRef(Type type)
        {
            // Type tracking for persistence goes here
            /*
            TypeRef = World.NewEntityTypes.IndexOf(type);
            if (TypeRef == -1)
            {
                World.NewEntityTypes.Add(type);
                TypeRef = World.NewEntityTypes.Count - 1;
            }
            */
        }
    }
}
```

Generated code:
```cs
namespace Server.Items
{
    public partial class NewTestEntityObject
    {
#pragma warning disable 0414
        private const int _version = 0;
#pragma warning restore 0414

        public int SomeProperty
        {
            get => _someProperty;
            set
            {
                if (value != _someProperty)
                {
                    _someProperty = value;
                    ((ISerializable)this).MarkDirty();
                }
            }
        }

        long ISerializable.SavePosition { get; set; } = -1;
        BufferWriter ISerializable.SaveBuffer { get; set; }
        bool ISerializable.UseDirtyChecking => true;

        public NewTestEntityObject(Serial serial)
        {
            Serial = serial;
            SetTypeRef(typeof(NewTestEntityObject));
        }

        public void Serialize(IGenericWriter writer)
        {

            writer.WriteEncodedInt(_version);

            writer.WriteEncodedInt(SomeProperty);
        }

        public void Deserialize(IGenericReader reader)
        {
            var version = reader.ReadEncodedInt();

            SomeProperty = reader.ReadEncodedInt();

            Timer.DelayCall(AfterDeserialization);
        }
    }
}
```
2021-05-26 19:25:05 -07:00
Kamron Batman
3c6356e8fa
feat(codegen): Adds support for partial opt-in with already existing properties (#617)
- [X] Fixes an issue with ordering of properties in serialization.
- [X] Adds opt-in with existing properties.

Example:
```cs
private int _myExistingField;

[SerializableField(1)]
public int MyExistingProperty
{
    get => _myExistingField;
    set
    {
        if (value == 0)
        {
            Parent = null;
        }
        
        if (value != _myExistingField)
        {
            ((ISerializable)this).MarkDirty();
            _myExistingField = value;
        }
    }
}
```
2021-05-26 13:20:52 -07:00
Kamron Batman
1ac91c3998
feat(codegen): Adds InvalidateProperties (#616)
Adds invalidate properties to code genned fields.

Example:
```cs
[InvalidateProperties]
[EncodedInt]
private int _number; // Cliloc
```

Generates:
```cs
public int Number
{
    get => _number;
    set
    {
        if (value != _number)
        {
            _number = value;
            ((ISerializable)this).MarkDirty();
            InvalidateProperties();
        }
    }
}
```
2021-05-24 22:49:00 -07:00
Kamron Batman
b20f3df595
feat(codegen): Adds AfterDeserialization support (#615)
Added the ability to execute arbitrary code after deserialization.

Example, let's say you want to delete an item after you deserialize it:
```cs
        [AfterDeserialization]
        private void OnAfterDeserialization()
        {
            Delete();
        }
```

Generates this:
```cs
        public override void Deserialize(IGenericReader reader)
        {
            base.Deserialize(reader);

            var version = reader.ReadEncodedInt();

            Timer.DelayCall(OnAfterDeserialization);
        }
```
2021-05-24 22:30:13 -07:00
Kamron Batman
ca5a06e9a2
fix(codegen): Adds string intern, encoded int, enum and legacy version support (#613)
- [X] Adds Enum migration rule
- [X] Adds legacy version (writing full int for version field)
- [X] Adds encoded int attribute
- [X] Adds intern string attribute
- [X] Fixes missing base deserialize/serialize
2021-05-24 01:01:56 -07:00
Kamron Batman
99c46f1b11
fix(codegen): Removes extra rule arg for primitive serialization (#611) 2021-05-23 23:47:12 -07:00
Kamron Batman
9afa4e4cab
feat: Source generated Serialization/Deserialization (#550)
### Features
* Fully abstracts serialization by using compile-time attributes.
* Supports serializing the following:
  - Primitives (integers, strings, etc)
  - IP Addresses
  - BigDecimal
  - DateTime, Delta DateTimes
  - TimeSpan
  - Server.Race
  - Server.Map
  - Point2D, Point3D, Rect2D, Rect3D
  - Existing/New `ISerializable` references
  - Lists/Sets of serializable types
  - Type with a `Serialize` method and constructor that takes an `IGenericReader`
* Supports forward-only migration
* Supports existing RunUO deserialization for older versions by changing to the following signature:
  - `public void OldDeserialize(IGenericReader reader, int version)`
  - Must remove deserializing the version since this is already done
* Supports serializing from private fields or custom made properties.
* Types do not require inheriting Item/Mobile. Code gen will fully create `ISerializable` information.
  - This is not recommended yet, since it requires wiring to `Persistence` which will cause lots of unresolved symbol errors until code gen is built.

### Example
```cs
using System.Collections.Generic;

namespace Server.Items
{
    [Serializable(1)]
    public partial class TestItem1 : Item
    {
        [SerializableField(1)]
        [SerializableFieldAttr("[CommandProperty(AccessLevel.Administrator)]")]
        private List<Item> _someProperty;

        private void Deserialize(IGenericReader reader, int version)
        {
        }
    }
}
```

Generates this:
```cs
namespace Server.Items
{
    public partial class TestItem1
    {
#pragma warning disable 0414
        private const int _version = 1;
#pragma warning restore 0414

        [CommandProperty(AccessLevel.Administrator)]
        public System.Collections.Generic.List<Server.Item> SomeProperty
        {
            get => _someProperty;
            set
            {
                if (value != _someProperty)
                {
                    ((ISerializable)this).MarkDirty();
                    _someProperty = value;
                }
            }
        }

        public TestItem1(Serial serial) : base(serial)
        {
        }

        public override void Serialize(IGenericWriter writer)
        {
            var savePosition = ((Server.ISerializable)this).SavePosition;
            if (savePosition > -1)
            {
                writer.Seek(savePosition, System.IO.SeekOrigin.Begin);
                return;
            }
            writer.WriteEncodedInt(_version);
            writer.Write(_someProperty);
        }

        public override void Deserialize(IGenericReader reader)
        {
            var version = reader.ReadEncodedInt();
            if (version < 1)
            {
                OldDeserialize(reader, version);
                ((Server.ISerializable)this).MarkDirty();
                return;
            }
            SomeProperty = reader.ReadEntityList<Server.Item>();
        }
    }
}
```

And this:
```json
{
  "version": 1,
  "type": "TestItem1",
  "properties": [
    {
      "name": "SomeProperty",
      "type": "System.Collections.Generic.List\u003CServer.Item\u003E",
      "rule": "ListMigrationRule",
      "ruleArguments": [
        "Server.Item",
        "SerializableInterfaceMigrationRule"
      ]
    }
  ]
}
```
2021-05-23 21:06:23 -07:00