HenryEx icon

updateStructFromMonoClass

HenryEx | PRO | 08/18/26 01:12:46 PM UTC | 0 ⭐ | 3558 👁️ | Never ⏰ | []
Lua |

4.92 KB

|

Source Code

|

0 👍

/

0 👎

--- 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

Comments