Commit graph

15 commits

Author SHA1 Message Date
Kamron Batman
862e868cf0
fix: Fixes codegenning nested classes (#738) 2021-08-27 19:08:04 -07:00
Kamron Batman
ca5e9342a0
fix(codegen): Adds default codegen option for save flags. Fixes world load issues. (#707) 2021-08-19 22:51:44 -07:00
Kamron Batman
f7e7fa424b
fix(codegen): Codegens books (#697) 2021-08-17 22:38:48 -07:00
Kamron Batman
c8a2605c0d
fix(codegen): Code gens base armor and fixes code genning of other armors. (#696)
* Fixes code gen of save flags
* Code gens rest of armor
* Fixes some existing code genned armors
* Code gens BaseArmor
2021-08-17 17:52:15 -07:00
Kamron Batman
2c8097f707
fix(codegen): Fixes various code gen issues. Adds better embedded serialization support (#688)
* Adds save flag support (see `ElvenGlasses` for an example)
* Updates AOSAttributes so they are code genned
* Fixes embedded object support by adding an `IRawSerializable`
* Fixes various inconsistencies in serializing with codegen
2021-08-17 02:43:52 -07:00
Kamron Batman
1323162628
fix(codegen): Adds codegen for embedded objects and timer fields (#686)
* Adds code genning for embedded objects. See `AquariumState` as an example.
* Adds code genning for fields that are `Timer`. See `Aquarium` as an example.
* Codegens aquariums
* Fixes missing option for most primitive field types.
2021-08-16 14:48:18 -07:00
Kamron Batman
360143478a
feat: Adds tidy option for serialization. Codegens ballotbox. Fixes pooled timer leaking (#681)
* Fixes pooled timer leaking
* Fixes `[dumptimers` command so it outputs properly, adds spacing, and stacktraces
* Adds `[Tidy]` for serializing Lists. This will remove deleted entities during world save before serializing the list.
* Adds helpers for managing Lists/Sets/Dictionaries


### New API

```cs
// Creates the list if it is null, then adds
Utility.Add(ref list, value);
Utility.Add(ref set, value);
Utility.Add(ref dict, key, value);

// Nulls the variable if the count is zero
Utility.Remove(ref list, value);
Utility.Remove(ref set, value);
Utility.Remove(ref dict, key);

// Marks entity as dirty in addition to doing the action
entity.Add(list, value);
// Marks entity as dirty, and will create list if it doesn't exist
entity.Add(ref list, value);

// Marks entity as dirty in addition to doing the action
entity.Remove(list, value);
// Marks entity as dirty, and will null the list count is zero
entity.Remove(ref list, value);
```


### Updates to [dumptimers
<img width="825" alt="Screen Shot 2021-08-14 at 2 55 10 AM" src="https://user-images.githubusercontent.com/3953314/129442449-ccf7fe14-29d6-4f3f-9366-c8eb7b9828a7.png">
2021-08-14 03:02:53 -07:00
Kamron Batman
679e8100f4
cleanup: Fixes bugs and cleans up code (#660) 2021-07-19 20:49:59 -07:00
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
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
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
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