From 33ec343460857dc64a136a7ab1912018a395571f Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 24 Dec 2019 12:41:27 +0100 Subject: [PATCH] ZoneCodeGenerator: Add possibility to specify a custom array count to signalize how many entries of a static array should be loaded --- src/ZoneCode/Game/T6/T6_Commands.txt | 6 +- .../Domain/ReferenceTypeArray.cs | 2 + .../MemberReferenceComputations.cs | 7 +- .../Templates/Loading/DynamicArray.stg | 4 +- .../Generating/Templates/Loading/Embedded.stg | 14 +++- .../CommandFile/Impl/CommandParserState.cs | 15 ++-- .../CommandFile/Tests/TestArrayCount.cs | 82 +++++++++++++++++++ src/ZoneLoading/Game/T6/ContentLoaderT6.cpp | 2 +- 8 files changed, 118 insertions(+), 14 deletions(-) create mode 100644 src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestArrayCount.cs diff --git a/src/ZoneCode/Game/T6/T6_Commands.txt b/src/ZoneCode/Game/T6/T6_Commands.txt index 2d5e6318..0956f1c6 100644 --- a/src/ZoneCode/Game/T6/T6_Commands.txt +++ b/src/ZoneCode/Game/T6/T6_Commands.txt @@ -1345,8 +1345,10 @@ set string localization; use XGlobals; set string name; set name name; -//set count gumps gumpsCount; -//set count overlays overlayCount; +set arraycount gumps gumpsCount; +set condition gumps gumpsCount >= 0 && gumpsCount <= 32; +set arraycount overlays overlayCount; +set condition overlays overlayCount >= 0 && overlayCount <= 32; // gump_info_t set string gump_info_t::name; diff --git a/src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs b/src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs index b4bf5d16..70399de3 100644 --- a/src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs +++ b/src/ZoneCodeGenerator/Domain/ReferenceTypeArray.cs @@ -7,11 +7,13 @@ namespace ZoneCodeGenerator.Domain public int ArraySize { get; } public IEvaluation DynamicSize { get; set; } + public IEvaluation DynamicCount { get; set; } public ReferenceTypeArray(int arraySize) { ArraySize = arraySize; DynamicSize = null; + DynamicCount = null; } } } diff --git a/src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs b/src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs index 8e9da8e0..c41c8c22 100644 --- a/src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs +++ b/src/ZoneCodeGenerator/Generating/Computations/MemberReferenceComputations.cs @@ -29,6 +29,11 @@ namespace ZoneCodeGenerator.Generating.Computations public bool IsArray => Reference is ReferenceTypeArray; public int ArraySize => Reference is ReferenceTypeArray array ? array.ArraySize : 0; + public bool HasDynamicArrayCount => Reference is ReferenceTypeArray array && array.DynamicCount != null; + + public IEvaluation DynamicArrayCountEvaluation => + Reference is ReferenceTypeArray array ? array.DynamicCount : null; + public IEnumerable ArrayEntries => Enumerable.Range(0, ArraySize) .Select(i => new MemberReferenceComputations(information, referenceIndices.Concat(new[] {i}))); @@ -64,7 +69,7 @@ namespace ZoneCodeGenerator.Generating.Computations public bool IsDynamicArray => Reference is ReferenceTypeArray referenceTypeArray && referenceTypeArray.DynamicSize != null; - public IEvaluation DynamicArrayCountEvaluation => Reference is ReferenceTypeArray referenceTypeArray + public IEvaluation DynamicArraySizeEvaluation => Reference is ReferenceTypeArray referenceTypeArray ? referenceTypeArray.DynamicSize : null; diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/DynamicArray.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/DynamicArray.stg index 3690972a..51bb61ba 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/Loading/DynamicArray.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/Loading/DynamicArray.stg @@ -6,11 +6,11 @@ LoadDynamicArray_Load(context, structure, member, reference) ::= <% $if(member.StructureType && !member.StructureType.IsLeaf)$ $TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ -LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.DynamicArrayCountEvaluation)$); +LoadArray_$member.Member.VariableType.Type.Name$(true, $PrintEvaluation(reference.DynamicArraySizeEvaluation)$); $else$ -m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $PrintEvaluation(reference.DynamicArrayCountEvaluation)$); +m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $PrintEvaluation(reference.DynamicArraySizeEvaluation)$); $endif$ %> diff --git a/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg b/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg index 4ce29d5a..991133af 100644 --- a/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg +++ b/src/ZoneCodeGenerator/Generating/Templates/Loading/Embedded.stg @@ -2,6 +2,14 @@ delimiters "$", "$" // Everything related to loading an embedded reference +ArrayCount(reference) ::= <% +$if(reference.HasDynamicArrayCount)$ +$PrintEvaluation(reference.DynamicArrayCountEvaluation)$ +$else$ +$reference.ArraySize$ +$endif$ +%> + LoadEmbedded_Load(context, structure, member, reference) ::= << $if(!member.IsLeaf)$ $TypeVarName(member.Member.VariableType.Type)$ = &$TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$; @@ -38,16 +46,16 @@ $LoadEmbedded_Block(context, structure, member, reference)$ LoadEmbeddedArray_Load(context, structure, member, reference) ::= << $if(!member.IsLeaf)$ $TypeVarName(member.Member.VariableType.Type)$ = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$; -LoadArray_$member.Member.VariableType.Type.Name$($if(member.Computations.IsAfterPartialLoad)$true$else$false$endif$, $reference.ArraySize$);$\\$ +LoadArray_$member.Member.VariableType.Type.Name$($if(member.Computations.IsAfterPartialLoad)$true$else$false$endif$, $ArrayCount(reference)$);$\\$ $elseif(member.Computations.IsAfterPartialLoad)$ -m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $reference.ArraySize$);$\\$ +m_stream->Load<$TypeDeclaration(member.Member.VariableType)$$PrintFollowingReferences(reference.FollowingReferences)$>($TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$, $ArrayCount(reference)$);$\\$ $endif$ >> LoadEmbeddedArray_TypeCheck(context, structure, member, reference) ::= <% $if(member.IsScriptString)$ varScriptString = $TypeVarName(structure.Type)$->$member.Member.Name$$PrintArrayIndices(reference)$;$\n$ -LoadScriptStringArray(false, $reference.ArraySize$); +LoadScriptStringArray(false, $ArrayCount(reference)$); $else$ $LoadEmbeddedArray_Load(context, structure, member, reference)$ $endif$ diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs index 7d4e0d3f..b2a1b999 100644 --- a/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Impl/CommandParserState.cs @@ -13,7 +13,9 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl { class CommandParserState : ICommandParserState { - private static readonly ITokenTest[] tests = { + private static readonly ITokenTest[] tests = + { + new TestArrayCount(), new TestArraySize(), new TestAsset(), new TestBlock(), @@ -58,7 +60,8 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl return true; } - private bool FindTypenameParts(string[] parts, out DataTypeWithMembers dataTypeWithMembers, out int typeNamePartCount) + private bool FindTypenameParts(string[] parts, out DataTypeWithMembers dataTypeWithMembers, + out int typeNamePartCount) { typeNamePartCount = 1; while (typeNamePartCount <= parts.Length) @@ -70,7 +73,8 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl { if (!(foundDataType is DataTypeWithMembers foundDataTypeWithMembers)) { - throw new TestFailedException($"Referenced type '{currentTypeName}' needs to be a data type with members to be used in an evaluation."); + throw new TestFailedException( + $"Referenced type '{currentTypeName}' needs to be a data type with members to be used in an evaluation."); } dataTypeWithMembers = foundDataTypeWithMembers; @@ -84,7 +88,8 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl return false; } - public bool GetMembersFromParts(string[] parts, StructureInformation baseType, out List members) + public bool GetMembersFromParts(string[] parts, StructureInformation baseType, + out List members) { members = new List(); var currentStructure = baseType; @@ -129,4 +134,4 @@ namespace ZoneCodeGenerator.Parsing.CommandFile.Impl return GetMembersFromParts(memberParts, typeInformation, out members); } } -} +} \ No newline at end of file diff --git a/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestArrayCount.cs b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestArrayCount.cs new file mode 100644 index 00000000..59a23c64 --- /dev/null +++ b/src/ZoneCodeGenerator/Parsing/CommandFile/Tests/TestArrayCount.cs @@ -0,0 +1,82 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using ZoneCodeGenerator.Domain; +using ZoneCodeGenerator.Domain.Information; +using ZoneCodeGenerator.Parsing.Matching; +using ZoneCodeGenerator.Parsing.Matching.Matchers; +using ZoneCodeGenerator.Parsing.Testing; + +namespace ZoneCodeGenerator.Parsing.CommandFile.Tests +{ + class TestArrayCount : TestWithEvaluation + { + private StructureInformation referencedType; + private const string TypeNameToken = "typeName"; + + // set count ; + private static readonly TokenMatcher[] matchers = + { + new MatcherLiteral("set"), + new MatcherLiteral("arraycount"), + new MatcherTypename().WithName(TypeNameToken), + new MatcherWithTag(TagEvaluation), + new MatcherLiteral(";") + }; + + public TestArrayCount() : base(matchers) + { + } + + protected override void ProcessMatch(ICommandParserState state) + { + var typeName = NextMatch(TypeNameToken); + var typeNameParts = typeName.Split(new[] { "::" }, StringSplitOptions.None); + if (state.DataTypeInUse != null + && state.GetMembersFromParts(typeNameParts, state.DataTypeInUse, out var typeMembers)) + { + referencedType = state.DataTypeInUse; + } + else if (state.GetTypenameAndMembersFromParts(typeNameParts, out referencedType, out typeMembers)) + { + // Do nothing + } + else + { + throw new TestFailedException($"Could not find type/members '{typeName}'"); + } + + if (typeMembers == null + || !typeMembers.Any()) + { + throw new TestFailedException("Can only set array size for members and not for types."); + } + + if (!NextTag().Equals(TagEvaluation)) + throw new Exception("Expected first array size tag to be a calculation statement"); + + var evaluation = ProcessEvaluation(state); + + var referencedMember = typeMembers.Last(); + var reference = referencedMember.Member.VariableType.References.OfType() + .FirstOrDefault(); + + if (reference != null) + reference.DynamicCount = evaluation; + else + throw new TestFailedException( + $"Member '{referencedMember.Member.Name}' of type '{referencedMember.Member.VariableType.Type.FullName}' cannot have its array count set due to it not having an array reference"); + } + + protected override IEnumerable GetUsedTypes(ICommandParserState state) + { + if (state.DataTypeInUse != null + && state.DataTypeInUse != referencedType) + { + return new[] { state.DataTypeInUse, referencedType }; + } + + return new[] { referencedType }; + } + } +} \ No newline at end of file diff --git a/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp b/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp index 6ecf0f73..24ee1e7c 100644 --- a/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp +++ b/src/ZoneLoading/Game/T6/ContentLoaderT6.cpp @@ -145,7 +145,7 @@ void ContentLoaderT6::LoadXAsset(const bool atStreamStart) LOAD_ASSET(ASSET_TYPE_RAWFILE, RawFile, rawfile); LOAD_ASSET(ASSET_TYPE_STRINGTABLE, StringTable, stringTable); LOAD_ASSET(ASSET_TYPE_LEADERBOARD, LeaderboardDef, leaderboardDef); - // LOAD_ASSET(ASSET_TYPE_XGLOBALS, XGlobals, xGlobals); + LOAD_ASSET(ASSET_TYPE_XGLOBALS, XGlobals, xGlobals); LOAD_ASSET(ASSET_TYPE_DDL, ddlRoot_t, ddlRoot); LOAD_ASSET(ASSET_TYPE_GLASSES, Glasses, glasses); LOAD_ASSET(ASSET_TYPE_EMBLEMSET, EmblemSet, emblemSet);