예제 #1
0
        public override Task GenerateInRegistration(ObjectGeneration obj, FileGeneration fg)
        {
            var objData = obj.GetObjectData();

            GenerateConverterMember(fg, obj.BaseClass, objData.BaseRecordTypeConverter, "Base");
            foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true))
            {
                LoquiType loquiType = field as LoquiType;
                if (loquiType == null)
                {
                    switch (field)
                    {
                    case WrapperType wrapper:
                        loquiType = wrapper.SubTypeGeneration as LoquiType;
                        if (loquiType != null)
                        {
                            break;
                        }
                        continue;

                    default:
                        continue;
                    }
                }
                var fieldData = loquiType.GetFieldData();
                GenerateConverterMember(fg, loquiType.TargetObjectGeneration, fieldData.RecordTypeConverter, field.Name);
            }
            return(base.GenerateInRegistration(obj, fg));
        }
 public bool NeedsHeaderProcessing(LoquiType loquiGen)
 {
     if (!loquiGen.Singleton &&
         loquiGen.TargetObjectGeneration != null &&
         loquiGen.GetFieldData().HasTrigger &&
         !loquiGen.TargetObjectGeneration.Abstract &&
         loquiGen.TargetObjectGeneration.GetObjectData().TriggeringSource == null)
     {
         return(true);
     }
     return(false);
 }
예제 #3
0
        public static async Task AddAsSubLoquiType(this LoquiType loqui, IEnumerable <ObjectGeneration> objGens)
        {
            var data = loqui.GetFieldData();

            foreach (var subObj in objGens)
            {
                var subRecs = await subObj.TryGetTriggeringRecordTypes();

                if (subRecs.Failed)
                {
                    continue;
                }
                foreach (var subRec in subRecs.Value)
                {
                    data.SubLoquiTypes.TryCreateValue(subRec).Add(subObj);
                }
            }
        }
        public override async Task GenerateWrapperRecordTypeParse(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor locationAccessor,
            Accessor packageAccessor,
            Accessor converterAccessor)
        {
            LoquiType loqui = typeGen as LoquiType;
            var       data  = loqui.GetFieldData();

            switch (data.BinaryOverlayFallback)
            {
            case BinaryGenerationType.Normal:
                break;

            case BinaryGenerationType.NoGeneration:
                return;

            case BinaryGenerationType.Custom:
                using (var args = new ArgsWrapper(fg,
                                                  $"{typeGen.Name}CustomParse"))
                {
                    args.Add("stream");
                    args.Add("finalPos");
                    args.Add("offset");
                }
                return;

            default:
                throw new NotImplementedException();
            }

            string accessor;

            if (loqui.Singleton ||
                !loqui.Nullable)
            {
                accessor = $"_{typeGen.Name}";
            }
            else
            {
                accessor = typeGen.Name;
            }
            if (data.MarkerType.HasValue)
            {
                fg.AppendLine($"stream.Position += {packageAccessor}.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)}.SubConstants.HeaderLength; // Skip marker");
            }

            if (!loqui.TargetObjectGeneration.IsTypelessStruct() && (loqui.GetFieldData()?.HasTrigger ?? false))
            {
                fg.AppendLine($"_{typeGen.Name}Location = new {GetLocationObjectString(objGen)}({locationAccessor}, finalPos);");
                var severalSubTypes = data.GenerationTypes
                                      .Select(i => i.Value)
                                      .WhereCastable <TypeGeneration, LoquiType>()
                                      .Where(loqui => !loqui?.TargetObjectGeneration?.Abstract ?? true)
                                      .CountGreaterThan(1);
                if (severalSubTypes)
                {
                    fg.AppendLine($"_{typeGen.Name}Type = type;");
                }
            }
            else
            {
                if (NeedsHeaderProcessing(loqui))
                {
                    fg.AppendLine($"stream.Position += _package.{nameof(BinaryOverlayFactoryPackage.MetaData)}.{nameof(ParsingBundle.Constants)}.SubConstants.HeaderLength;");
                }
                using (var args = new ArgsWrapper(fg,
                                                  $"this.{accessor} = {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory"))
                {
                    args.Add($"stream: stream");
                    args.Add($"package: {packageAccessor}");
                    if (loqui.TargetObjectGeneration.IsVariableLengthStruct())
                    {
                        args.AddPassArg($"finalPos");
                    }
                    args.Add($"recordTypeConverter: {converterAccessor}");
                }
            }
        }
        public override async Task GenerateWrapperFields(
            FileGeneration fg,
            ObjectGeneration objGen,
            TypeGeneration typeGen,
            Accessor dataAccessor,
            int?currentPosition,
            string passedLengthAccessor,
            DataType dataType)
        {
            LoquiType loqui = typeGen as LoquiType;
            var       data  = typeGen.GetFieldData();

            switch (data.BinaryOverlayFallback)
            {
            case BinaryGenerationType.Normal:
                break;

            case BinaryGenerationType.NoGeneration:
                return;

            case BinaryGenerationType.Custom:
                await this.Module.CustomLogic.GenerateForCustomFlagWrapperFields(
                    fg,
                    objGen,
                    typeGen,
                    dataAccessor,
                    currentPosition,
                    passedLengthAccessor,
                    dataType);

                return;

            default:
                throw new NotImplementedException();
            }

            string DataAccessor(Accessor accessor, string positionStr, string lenStr)
            {
                if (objGen.GetObjectType() == ObjectType.Mod)
                {
                    return($"{nameof(BinaryOverlay)}.{nameof(BinaryOverlay.LockExtractMemory)}({accessor}, {positionStr}, {lenStr})");
                }
                else
                {
                    return($"{accessor}.Slice({positionStr})");
                }
            }

            string recConverter = $"default({nameof(RecordTypeConverter)})";

            if (loqui.GetFieldData()?.RecordTypeConverter != null &&
                loqui.GetFieldData().RecordTypeConverter.FromConversions.Count > 0)
            {
                recConverter = $"{objGen.RegistrationName}.{loqui.Name}Converter";
            }

            var isRequiredRecord = !loqui.Nullable && data.HasTrigger;

            if (dataType == null)
            {
                if (loqui.GetFieldData()?.HasTrigger ?? false)
                {
                    if (loqui.TargetObjectGeneration.IsTypelessStruct())
                    {
                        if (loqui.Singleton ||
                            isRequiredRecord)
                        {
                            fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)}? _{typeGen.Name};");
                        }
                        else if (loqui.Nullable)
                        {
                            fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)}? {typeGen.Name} {{ get; private set; }}");
                        }
                    }
                    else
                    {
                        var severalSubTypes = data.GenerationTypes
                                              .Select(i => i.Value)
                                              .WhereCastable <TypeGeneration, LoquiType>()
                                              .Where(loqui => !loqui?.TargetObjectGeneration?.Abstract ?? true)
                                              .CountGreaterThan(1);
                        if (severalSubTypes)
                        {
                            fg.AppendLine($"private {nameof(RecordType)} _{typeGen.Name}Type;");
                        }
                        fg.AppendLine($"private {GetLocationObjectString(objGen)}? _{typeGen.Name}Location;");
                        using (new LineWrapper(fg))
                        {
                            if (loqui.IsNullable)
                            {
                                fg.Append($"public ");
                            }
                            else
                            {
                                fg.Append($"private ");
                            }
                            fg.Append($"{loqui.Interface(getter: true, internalInterface: true)}{(typeGen.CanBeNullable(getter: true) ? "?" : null)} ");
                            if (!loqui.IsNullable ||
                                isRequiredRecord)
                            {
                                fg.Append("_");
                            }
                            fg.Append($"{typeGen.Name}");
                            if (!severalSubTypes)
                            {
                                fg.Append($" => _{typeGen.Name}Location.HasValue ? ");
                                fg.Append($"{this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{typeGen.Name}Location!.Value.Min", $"_{typeGen.Name}Location!.Value.Max")}, _package), _package");
                                if (!recConverter.StartsWith("default("))
                                {
                                    fg.Append($", {recConverter}");
                                }
                                fg.Append($") ");
                                fg.Append($": default;");
                            }
                        }
                        if (severalSubTypes)
                        {
                            using (new BraceWrapper(fg))
                            {
                                fg.AppendLine("get");
                                using (new BraceWrapper(fg))
                                {
                                    fg.AppendLine($"if (!_{typeGen.Name}Location.HasValue) return default;");
                                    fg.AppendLine($"switch (_{typeGen.Name}Type.TypeInt)");
                                    using (new BraceWrapper(fg))
                                    {
                                        foreach (var gen in data.GenerationTypes)
                                        {
                                            if (!(gen.Value is LoquiType subLoq))
                                            {
                                                continue;
                                            }
                                            if (subLoq?.TargetObjectGeneration?.Abstract ?? false)
                                            {
                                                continue;
                                            }
                                            foreach (var trigger in gen.Key)
                                            {
                                                fg.AppendLine($"case 0x{trigger.TypeInt.ToString("X")}: // {trigger.Type}");
                                            }
                                            using (new DepthWrapper(fg))
                                                using (new LineWrapper(fg))
                                                {
                                                    fg.Append($"return {this.Module.BinaryOverlayClassName(subLoq)}.{subLoq.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{subLoq.Name}Location!.Value.Min", $"_{subLoq.Name}Location!.Value.Max")}, _package), _package");
                                                    if (!loqui.Singleton)
                                                    {
                                                        fg.Append($", {recConverter}");
                                                    }
                                                    fg.Append($");");
                                                }
                                        }
                                        fg.AppendLine("default:");
                                        using (new DepthWrapper(fg))
                                        {
                                            fg.AppendLine("throw new ArgumentException();");
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                else
                {
                    if (!loqui.Singleton)
                    {
                        fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)} {typeGen.Name} => {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({dataAccessor}.Slice({passedLengthAccessor ?? "0x0"}), _package), _package, {recConverter});");
                    }
                    else
                    {
                        fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)} _{typeGen.Name} {{ get; private set; }}");
                    }
                }
            }
            else
            {
                isRequiredRecord = true;
                DataBinaryTranslationGeneration.GenerateWrapperExtraMembers(fg, dataType, objGen, typeGen, passedLengthAccessor);
                fg.AppendLine($"private {loqui.Interface(getter: true, internalInterface: true)}? _{typeGen.Name} => _{typeGen.Name}_IsSet ? {this.Module.BinaryOverlayClassName(loqui)}.{loqui.TargetObjectGeneration.Name}Factory(new {nameof(OverlayStream)}({DataAccessor(dataAccessor, $"_{typeGen.Name}Location", null)}, _package), _package) : default;");
            }

            if (loqui.Singleton ||
                isRequiredRecord)
            {
                fg.AppendLine($"public {loqui.Interface(getter: true, internalInterface: true)} {typeGen.Name} => _{typeGen.Name} ?? new {loqui.DirectTypeName}({(loqui.ThisConstruction ? "this" : null)});");
            }
        }
        public override Task GenerateInRegistration(ObjectGeneration obj, FileGeneration fg)
        {
            var objData = obj.GetObjectData();

            GenerateConverterMember(fg, obj.BaseClass, objData.BaseRecordTypeConverter, "Base");
            foreach (var field in obj.IterateFields(expandSets: SetMarkerType.ExpandSets.FalseAndInclude, nonIntegrated: true))
            {
                LoquiType loquiType = field as LoquiType;
                if (loquiType == null)
                {
                    switch (field)
                    {
                    case WrapperType wrapper:
                        loquiType = wrapper.SubTypeGeneration as LoquiType;
                        if (loquiType != null)
                        {
                            break;
                        }
                        continue;

                    default:
                        continue;
                    }
                }
                var fieldData = loquiType.GetFieldData();
                GenerateConverterMember(fg, loquiType.TargetObjectGeneration, fieldData.RecordTypeConverter, field.Name);
            }
            if (objData.GameReleaseConverters != null)
            {
                foreach (var kv in objData.GameReleaseConverters)
                {
                    GenerateConverterMember(fg, obj, kv.Value, kv.Key.ToString());
                }
                using (var args = new FunctionWrapper(fg,
                                                      $"public static {nameof(RecordTypeConverter)}? Get"))
                {
                    args.Add($"{nameof(GameRelease)} release");
                }
                using (new BraceWrapper(fg))
                {
                    fg.AppendLine($"return release switch");
                    using (new BraceWrapper(fg)
                    {
                        AppendSemicolon = true
                    })
                    {
                        using (var comma = new CommaWrapper(fg))
                        {
                            foreach (var kv in objData.GameReleaseConverters)
                            {
                                comma.Add($"{nameof(GameRelease)}.{kv.Key} => {kv.Key}Converter");
                            }
                            comma.Add($"_ => default({nameof(RecordTypeConverter)})");
                        }
                    }
                }
            }
            if (objData.VersionConverters != null)
            {
                foreach (var kv in objData.VersionConverters)
                {
                    GenerateConverterMember(fg, obj, kv.Value, $"Version{kv.Key}");
                }
                using (var args = new FunctionWrapper(fg,
                                                      $"public static {nameof(RecordTypeConverter)}? Get"))
                {
                    args.Add($"int? version");
                }
                using (new BraceWrapper(fg))
                {
                    bool first = true;
                    fg.AppendLine($"if (version == null) return default({nameof(RecordTypeConverter)});");
                    foreach (var kv in objData.VersionConverters.OrderBy(kv => kv.Key))
                    {
                        fg.AppendLine($"{(first ? null : "else ")}if (version.Value >= {kv.Key})");
                        using (new BraceWrapper(fg))
                        {
                            fg.AppendLine($"return Version{kv.Key}Converter;");
                        }
                        first = false;
                    }
                    fg.AppendLine($"return default({nameof(RecordTypeConverter)});");
                }
            }
            return(base.GenerateInRegistration(obj, fg));
        }