def merge_player_and_revert(self, fnames): """ Apply the source's face onto the target file and then revert. The target should be identical before and after. """ for fname1, fname2 in fnames: with open(fname1, 'rb') as f: rawsourcedata = f.read() with open(fname2, 'rb') as f: rawtargetdata = f.read() # First get the source for the face sourcegame, sourcedata = extract.parse_savedata(rawsourcedata) sourcecf = extract.parse_changeforms(sourcedata['changeforms']) rawsourceplayer = sourcecf['playerdata'] sourceplayer = extract.parse_player(rawsourceplayer, sourcecf['playerchangeflags'], sourcegame) # Then get the target data targetgame, targetdata = extract.parse_savedata(rawtargetdata) targetcf = extract.parse_changeforms(targetdata['changeforms']) rawtargetplayer = targetcf['playerdata'] targetplayer = extract.parse_player(rawtargetplayer, targetcf['playerchangeflags'], targetgame) # Merge the source and target mergedplayer, mergedflags = extract.merge_player( sourceplayer, sourcecf['playerchangeflags'], targetplayer, targetcf['playerchangeflags'], targetgame ) # Make sure the mergedplayer is valid rawmergedplayer = extract.encode_player(mergedplayer, targetgame) extract.parse_player(rawmergedplayer, mergedflags, targetgame) # Then get a new copy of the target, just to be sure target2game, target2data = extract.parse_savedata(rawtargetdata) rawtarget2cf = target2data['changeforms'] target2cf = extract.parse_changeforms(rawtarget2cf) rawtarget2player = target2cf['playerdata'] target2player = extract.parse_player(rawtarget2player, target2cf['playerchangeflags'], target2game) # Revert the face, aka put the newly read target face # onto the old target's data (which atm has source's face) revertedplayer, revertedflags = extract.merge_player( target2player, target2cf['playerchangeflags'], targetplayer, targetcf['playerchangeflags'], targetgame ) # Encode the target again and compare rawrevertedplayer = extract.encode_player(revertedplayer, targetgame) self.assertEqual(rawtargetplayer, rawrevertedplayer) # Encode the changeforms and compare targetcf['playerdata'] = rawrevertedplayer targetcf['playerchangeflags'] = revertedflags rawrevertedcf = extract.encode_changeforms(targetcf) self.assertEqual(rawtarget2cf, rawrevertedcf) # Encode the whole file and compare targetdata['changeforms'] = rawrevertedcf rawreverteddata = extract.encode_savedata(targetdata) self.assertEqual(rawtargetdata, rawreverteddata)
def decode_and_encode_player(self, root): for path, _, fnames in os.walk(root): for fname in fnames: with open(os.path.join(path, fname), 'rb') as f: rawdata = f.read() game, data = extract.parse_savedata(rawdata) cf = extract.parse_changeforms(data['changeforms']) rawplayer1 = cf['playerdata'] player = extract.parse_player(rawplayer1, cf['playerchangeflags'], game) rawplayer2 = extract.encode_player(player, game) self.assertEqual(rawplayer1, rawplayer2)
def transfer_face(sourcefname: str, targetfname: str): """ Copy facial data from one save file to another. This function should be the main entry point for the UI. """ with open(sourcefname, 'rb') as f: sourcerawdata = f.read() with open(targetfname, 'rb') as f: targetrawdata = f.read() sourcegame, sourcedata = extract.parse_savedata(sourcerawdata) targetgame, targetdata = extract.parse_savedata(targetrawdata) if sourcegame != targetgame: raise Exception('Saves are not from the same game!') if sourcedata['playersex'] != targetdata['playersex']: raise Exception('Characters must have the same gender!') if sourcedata['playerraceeditorid'] != targetdata['playerraceeditorid']: raise Exception('Characters must be the same race!') # Get the player data from the source save sourcecfdata = extract.parse_changeforms(sourcedata['changeforms']) sourceplayer = extract.parse_player(sourcecfdata['playerdata'], sourcecfdata['playerchangeflags'], sourcegame) # Get the data from target save targetcfdata = extract.parse_changeforms(targetdata['changeforms']) targetplayer = extract.parse_player(targetcfdata['playerdata'], targetcfdata['playerchangeflags'], targetgame) # Merge players, return target player with source's face newplayer, newflags = extract.merge_player( sourceplayer, sourcecfdata['playerchangeflags'], targetplayer, targetcfdata['playerchangeflags'], sourcegame ) # Encode and put the new face and flags in the target changeform data targetcfdata['playerdata'] = extract.encode_player(newplayer, sourcegame) targetcfdata['playerchangeflags'] = newflags # Encode the changeform data and put it in the target main data targetdata['changeforms'] = extract.encode_changeforms(targetcfdata) # Then encode the whole file newrawdata = extract.encode_savedata(targetdata) # Write to disk i = 0 while os.path.isfile(targetfname+'.facebak'+str(i)): i += 1 rename(targetfname, targetfname+'.facebak'+str(i)) with open(targetfname, 'wb') as f: f.write(newrawdata) return True
def transfer_face(sourcefname: str, targetfname: str): """ Copy facial data from one save file to another. This function should be the main entry point for the UI. """ with open(sourcefname, 'rb') as f: sourcerawdata = f.read() with open(targetfname, 'rb') as f: targetrawdata = f.read() sourcegame, sourcedata = extract.parse_savedata(sourcerawdata) targetgame, targetdata = extract.parse_savedata(targetrawdata) if sourcegame != targetgame: raise Exception('Saves are not from the same game!') if sourcedata['playersex'] != targetdata['playersex']: raise Exception('Characters must have the same gender!') if sourcedata['playerraceeditorid'] != targetdata['playerraceeditorid']: raise Exception('Characters must be the same race!') # Get the player data from the source save sourcecfdata = extract.parse_changeforms(sourcedata['changeforms']) sourceplayer = extract.parse_player(sourcecfdata['playerdata'], sourcecfdata['playerchangeflags'], sourcegame) # Get the data from target save targetcfdata = extract.parse_changeforms(targetdata['changeforms']) targetplayer = extract.parse_player(targetcfdata['playerdata'], targetcfdata['playerchangeflags'], targetgame) # Merge players, return target player with source's face newplayer, newflags = extract.merge_player( sourceplayer, sourcecfdata['playerchangeflags'], targetplayer, targetcfdata['playerchangeflags'], sourcegame) # Encode and put the new face and flags in the target changeform data targetcfdata['playerdata'] = extract.encode_player(newplayer, sourcegame) targetcfdata['playerchangeflags'] = newflags # Encode the changeform data and put it in the target main data targetdata['changeforms'] = extract.encode_changeforms(targetcfdata) # Then encode the whole file newrawdata = extract.encode_savedata(targetdata) # Write to disk i = 0 while os.path.isfile(targetfname + '.facebak' + str(i)): i += 1 rename(targetfname, targetfname + '.facebak' + str(i)) with open(targetfname, 'wb') as f: f.write(newrawdata) return True