--- Update existing CE structure with with new offset / fields from a Mono class -- Allows you to update structure offsets wtihout losing changes to existing fields -- like structure pointers and local structures -- @param idx_struct: integer index of CE Structure you want updated -- @param className: string containing the mono class you want to take fields from -- @param doDelete: Optional bool, deletes struct entries that don't correspond to current class fields -- @param verbose: Optional integer; >0 prints info on structure changes, >1 prints all actions -- @return true if structure was changed, false if not function updateStructFromMonoClass( idx_struct, className, doDelete, verbose ) if not idx_struct or not className then error('ERROR updateStructFromMonoClass: arguments malformed or missing!') end if idx_struct + 1 > getStructureCount() then error('ERROR updateStructFromMonoClass: structure index out of bounds!') end local classId = mono_findClass('', className) if not classId then error('ERROR updateStructFromMonoClass: no class ID found for given class name!') end verbose = type(verbose) == 'number' and verbose or 0 local ver1 = verbose > 0 and true or false local ver2 = verbose > 1 and true or false local changed = false local st = getStructure(idx_struct) local st_name = st.getName() if ver1 then print( string.format('== Updating structure %s with mono class %s ==',st_name, className) ) end local st_count = st.Count local st_entry = {} for i = 1, st_count do st_entry[i] = st.getElement(i-1) end local st2 = monoform_exportStructInternal(createStructure(''), classId, true --[[recursive]], false --[[not static]], {'some struct map thing'}, false --[[not global]]) local st2_count = st2.Count local st2_entry = {} for i = 1, st2_count do st2_entry[i] = st2.getElement(i-1) end local st2_tName = {} local st2_tOffset = {} for i = 1, st2_count do st2_tName[ st2_entry[i].Name ] = st2_entry[i].Offset end for i = 1, st2_count do st2_tOffset[ st2_entry[i].Offset ] = st2_entry[i].Name end -- simple offset adjust for existing fields st.beginUpdate() for i = 1, st_count do local ename = st_entry[i].Name if st2_tName[ename] then local newoff = st2_tName[ename] if st_entry[i].Offset ~= newoff then if ver1 then print( string.format('Updated offset of %s from %X to %X',ename,st_entry[i].Offset,newoff) ) end st_entry[i].Offset = newoff changed = true else if ver2 then print( string.format('Offset of %s unchanged from %X',ename,newoff) ) end end elseif doDelete then if ver1 then print( string.format( 'Entry %s not found, removed from structure', ename ) ) end st_entry[i].destroy() else if ver1 then print( string.format( 'Entry %s not found in new field list', ename ) ) end end end st.endUpdate() if st.Count ~= st_count then -- refresh if struct changed if ver2 then print('> Structure size changed, updating tables') end st_entry = {} st_count = st.Count for i = 1, st_count do st_entry[i] = st.getElement(i-1) end changed = true end local st_tName = {} for i = 1, st_count do st_tName[ st_entry[i].Name ] = st_entry[i].Offset end st.beginUpdate() for _,v in ipairs(st2_entry) do if not st_tName[v.Name] then -- check if new entry is in old struct if ver1 then print( string.format('Field %s not found, adding as new entry',v.Name) ) end local e = st.addElement() e.setName( v.getName() ) e.setOffset( v.getOffset() ) e.setVartype( v.getVartype() ) e.setBytesize( v.getBytesize() ) changed = true end end st.endUpdate() return changed end --- Bonus function to update all structures at once. -- @param doDelete: Optional bool, deletes struct entries that don't correspond to current class fields -- @param verbose: Optional integer; >0 prints info on structure changes, >1 prints all actions function updateAllMonoStructs( doDelete, verbose ) verbose = type(verbose) == 'number' and verbose or 0 local numStructs = getStructureCount() local numMonos = 0 local numChanged = 0 for i=0, numStructs-1 do repeat -- workaround to continue for loop on break local stName = getStructure(i).Name local classId = mono_findClass('', stName) if not classId or stName == 'String' then break end numMonos = numMonos + 1 local changed = updateStructFromMonoClass(i, stName, doDelete, verbose) if changed then numChanged = numChanged + 1 if verbose > 0 then print(string.format('CHANGED: %s\n',stName)) end else if verbose > 0 then print(string.format('UNCHANGED: %s\n',stName)) end end until true end if verbose > 0 then print('Number of Mono Structures found:', numMonos) end if verbose > 0 then print('Number of Structures updated:', numChanged) end end