HenryEx Expert Cheater
  Reputation: 2
  Joined: 18 Dec 2011 Posts: 100
 
  | 
		
			
				 Posted: Thu Jan 30, 2025 12:01 pm    Post subject: Update CE structures with new fields/offsets from Mono | 
				       | 
			 
			
				
  | 
			 
			
				function updateStructFromMonoClass( idx_struct, className, doDelete, verbose )
 
 
Tried of deleting and recreating your dissect structures after game updates, when offsets have shifted? Don't want to assign all your structure pointers anew and recreate all the local structures you've made?
 
 
Well, i was and wrote a simple function to automatically compare a current structure to a certain mono class and update the structure entries with new offsets, or add any entirely new fields into the structure.
 
 
This assumes that your structure entry name is identical to the class' field. If a field name changes between updates or you changed the structure entry name, a new entry will be created. You have the option to automatically delete any 'orphaned' structure entries upon update.
 
 
idx_struct is the integer index of the structure you want to update.
 
className is a string of the mono class to compare against.
 
doDelete == true will delete any entries that don't match the class fields
 
verbose  is an integer, set to 1 or 2 for console output on what the function does
 
 
 
Put this into your autorun folder or paste it into your table's LUA script:
 
 
 	  | Code: | 	 		  --- 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 | 	  
 
 
 
 
As a bonus, a small function to automatically update all table structures with the same name as a mono class, using the above function. The "doDelete" and "verbose" parameters get passed on to the above function.
 
Intentionally skips the "String" structure that gets auto-created by CE's mono features.
 
 
 	  | Code: | 	 		  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
 
 | 	  
 
 
 
edit: changed calling syntax from ':' to '.', since the former breaks the script in newer versions of CE. Hmmm.
 | 
			 
		  |