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
Exemple #4
0
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