a
    VŸ$c"9  ã                   @   s  d dl mZmZmZmZmZ d dlmZmZm	Z	m
Z
mZmZmZmZmZmZmZmZ d dlZd dlZd dlZd dlZd dlZd dlmZmZ d dlZe ¡ Zd dlZdeee ¡ ƒƒ d Z G dd„ de!ƒZ"G d	d
„ d
e!ƒZ#da$da%e &¡ Z'dd„ Z(dd„ Z)dd„ Z*dS )é    )ÚdivisionÚabsolute_importÚwith_statementÚprint_functionÚunicode_literals)ÚPY2Ú
basestringÚbchrÚbordÚchrÚopenÚpystrÚrangeÚroundÚstrÚtobytesÚunicodeN)Ú
clear_slotÚsafe_renameÚ.z.tmpc                   @   s    e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&S )'ÚFileLocationz=
    A location that saves files to a directory on disk.
    c                 C   sÒ   || _ zt | j ¡ W n ty(   Y n0 tj | j ¡ zXtj | j d¡}t	|dƒ}| 
d¡ W d   ƒ n1 st0    Y  t |¡ d| _W n ty¨   d| _Y n0 i | _tj | j d¡| _d| _d | _d S )Nztext.txtÚwzTest.TFÚ
persistentr   )Ú	directoryÚosÚmakedirsÚ	ExceptionÚrenpyÚutilÚexpose_directoryÚpathÚjoinr   ÚwriteÚunlinkÚactiveÚmtimesr   Úpersistent_mtimeÚpersistent_data)Úselfr   ÚfnÚf© r+   úrenpy/savelocation.pyÚ__init__7   s$    (

zFileLocation.__init__c                 C   s   t j | jtj |tj ¡¡S )z8
        Given a slot name, returns a filename.
        )r   r    r!   r   r   ÚexportsÚfsencodeÚsavegame_suffix©r(   Úslotnamer+   r+   r,   Úfilename[   s    zFileLocation.filenamec                 C   s   t jrddl}| ¡  dS )zJ
        Called to indicate that the HOME filesystem was changed.
        r   N)r   Ú
emscriptenÚsyncfs)r(   r4   r+   r+   r,   Úsyncb   s    zFileLocation.syncc           
   
   C   sV  | j s
dS t0 | j}i }tj}t|ƒ}t | j¡D ]R}| 	|¡sFq6|d| … }z tj
 tj
 | j|¡¡||< W q6 ty†   Y q60 q6|| _| ¡ D ] \}}| |d¡|kr˜t|ƒ q˜|D ]}||vr¾t|ƒ q¾| jd | jfD ]L}tj
 |¡rätj
 |¡}|| jkrätj |¡}	|	durä|| _|	| _ q2qäW d  ƒ n1 sH0    Y  dS )z;
        Scan for files that are added or removed.
        Nú.new)r$   Ú	disk_lockr%   r   r0   Úlenr   Úlistdirr   Úendswithr    Úgetmtimer!   r   ÚitemsÚgetr   r   Úexistsr&   Úloadr'   )
r(   Ú
old_mtimesÚ
new_mtimesÚsuffixÚ
suffix_lenr)   r2   ÚmtimeÚpfnÚdatar+   r+   r,   Úscank   s>    
 


zFileLocation.scanc                 C   sX   |   |¡}t | |¡ W d  ƒ n1 s.0    Y  tj |¡ |  ¡  |  ¡  dS )z4
        Saves the save record in slotname.
        N)r3   r8   Ú
write_filer   r   Úexpose_filer6   rH   )r(   r2   Úrecordr3   r+   r+   r,   Úsave›   s    
(zFileLocation.savec                 C   s
   t | jƒS )za
        Returns a list of all slots with savefiles in them, in arbitrary
        order.
        )Úlistr%   ©r(   r+   r+   r,   rM   ª   s    zFileLocation.listc                 C   s   | j  |d¡S )z…
        For a slot, returns the time the object was saved in that
        slot.

        Returns None if the slot is empty.
        N)r%   r>   r1   r+   r+   r,   rE   ²   s    zFileLocation.mtimec              
   C   s6  t  zæ|  |¡}t |d¡¼}z8| d¡}t |¡}|W W  d  ƒ W W  d  ƒ S  tyl   Y n0 z8| d¡ d¡}d|iW W  d  ƒ W W  d  ƒ S  ty¸   Y n0 i W  d  ƒ W W  d  ƒ S 1 sâ0    Y  W n" ty   Y W d  ƒ dS 0 W d  ƒ n1 s(0    Y  dS )za
        Returns the JSON data for slotname.

        Returns None if the slot is empty.
        ÚrÚjsonNÚ
extra_infozutf-8Ú
_save_name)	r8   r3   ÚzipfileÚZipFileÚreadrP   Úloadsr   Údecode)r(   r2   r3   ÚzfrG   rQ   r+   r+   r,   rP   ¼   s$    


$(6zFileLocation.jsonc              
   C   s  t  ð |  |¡}|du r*W d  ƒ dS zn|  |¡}t |d¡D}zd}| d¡ W n  tyv   d}| d¡ Y n0 W d  ƒ n1 sŒ0    Y  W n  ty¸   Y W d  ƒ dS 0 |rÒtjj	 
|d|¡}ntjj	 
|d|¡}|W  d  ƒ S 1  sþ0    Y  dS )z{
        Returns a displayable that show the screenshot for this slot.

        Returns None if the slot is empty.
        NrO   Fzscreenshot.tgaTzscreenshot.png)r8   rE   r3   rS   rT   Úgetinfor   r   ÚdisplayÚimÚZipFileImage)r(   r2   rE   r3   rX   ÚpngÚ
screenshotr+   r+   r,   r^   Ù   s&    

2zFileLocation.screenshotc              	   C   sl   t T |  |¡}t |d¡}| d¡}W d  ƒ n1 s<0    Y  |W  d  ƒ S 1 s^0    Y  dS )zi
        Returns the log component of the file found in `slotname`, so it
        can be loaded.
        rO   ÚlogN)r8   r3   rS   rT   rU   )r(   r2   r3   rX   Úrvr+   r+   r,   r@   ú   s
    
(zFileLocation.loadc                 C   sX   t @ |  |¡}tj |¡r&t |¡ |  ¡  |  ¡  W d  ƒ n1 sJ0    Y  dS )z/
        Deletes the file in slotname.
        N)r8   r3   r   r    r?   r#   r6   rH   )r(   r2   r3   r+   r+   r,   r#   	  s    

zFileLocation.unlinkc                 C   s   t x |  |¡}|  |¡}tj |¡s6W d  ƒ dS |t }t||ƒ t||ƒ tj 	|¡ |  
¡  |  ¡  W d  ƒ n1 s‚0    Y  dS )z3
        If old exists, renames it to new.
        N)r8   r3   r   r    r?   Útmpr   r   r   rJ   r6   rH   )r(   ÚoldÚnewÚold_tmpr+   r+   r,   Úrename  s    



zFileLocation.renamec                 C   s€   t h |  |¡}|  |¡}tj |¡s6W d  ƒ dS t ||¡ tj 	|¡ |  
¡  |  ¡  W d  ƒ n1 sr0    Y  dS )z9
        Copies `old` to `new`, if `old` exists.
        N)r8   r3   r   r    r?   ÚshutilÚcopyfiler   r   rJ   r6   rH   )r(   rb   rc   r+   r+   r,   Úcopy,  s    

zFileLocation.copyc                 C   s   | j r| j| j fgS g S dS )z½
        Returns a list of (mtime, persistent) tuples loaded from the
        persistent file. This should return quickly, with the actual
        load occuring in the scan thread.
        N)r'   r&   rN   r+   r+   r,   Úload_persistent>  s    zFileLocation.load_persistentc              	   C   s¾   t ¦ | jsW d  ƒ dS | j}|t }|d }t|dƒ}| |¡ W d  ƒ n1 s\0    Y  t||ƒ t||ƒ tj 	|¡| _
tj |¡ |  ¡  W d  ƒ n1 s°0    Y  dS )zƒ
        Saves `data` as the persistent data. Data is a binary string giving
        the persistent data in python format.
        Nr7   Úwb)r8   r$   r   ra   r   r"   r   r   r    r<   r&   r   r   rJ   r6   )r(   rG   r)   Úfn_tmpÚfn_newr*   r+   r+   r,   Úsave_persistentJ  s    (

zFileLocation.save_persistentc                 C   s:   | j s
d S zt | j¡ |  ¡  W n ty4   Y n0 d S ©N)r$   r   r#   r   r6   r   rN   r+   r+   r,   Úunlink_persistentf  s    zFileLocation.unlink_persistentc                 C   s   t |tƒsdS | j|jkS ©NF)Ú
isinstancer   r   ©r(   Úotherr+   r+   r,   Ú__eq__r  s    
zFileLocation.__eq__c                 C   s
   | |k S rn   r+   rr   r+   r+   r,   Ú__ne__x  s    zFileLocation.__ne__N)Ú__name__Ú
__module__Ú__qualname__Ú__doc__r-   r3   r6   rH   rL   rM   rE   rP   r^   r@   r#   re   rh   ri   rm   ro   rt   ru   r+   r+   r+   r,   r   2   s&   $	0
!r   c                   @   s¨   e Zd ZdZdd„ Zdd„ Zdd„ Zdd	„ Zd
d„ Zdd„ Z	dd„ Z
dd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zdd„ Zd d!„ Zd"d#„ Zd$d%„ Zd&d'„ Zd(S ))ÚMultiLocationzš
    A location that saves in multiple places. When loading or otherwise
    accessing a file, it loads the newest file found for the given slotname.
    c                 C   s
   g | _ d S rn   ©Ú	locationsrN   r+   r+   r,   r-   ‚  s    zMultiLocation.__init__c                 C   s   dd„ | j D ƒS )Nc                 S   s   g | ]}|j r|‘qS r+   )r$   )Ú.0Úir+   r+   r,   Ú
<listcomp>†  ó    z2MultiLocation.active_locations.<locals>.<listcomp>r{   rN   r+   r+   r,   Úactive_locations…  s    zMultiLocation.active_locationsc                 C   sB   d}d}| j D ].}|jsq| |¡}|dur||kr|}|}q|S )z€
        Returns the location containing the slotname with the newest
        mtime. Returns None if the slot is empty.
        éÿÿÿÿN)r|   r$   rE   )r(   r2   rE   ÚlocationÚlÚ
slot_mtimer+   r+   r,   Únewestˆ  s    

zMultiLocation.newestc                 C   s   || j v rdS | j  |¡ dS )z&
        Adds a new location.
        N)r|   Úappend)r(   rƒ   r+   r+   r,   Úaddž  s    
zMultiLocation.addc                 C   s2   d}|   ¡ D ]}| ||¡ d}q|s.tdƒ‚d S )NFTz$Not saved - no valid save locations.)r   rL   r   )r(   r2   rK   Úsavedr„   r+   r+   r,   rL   ¨  s    zMultiLocation.savec                 C   s*   t ƒ }|  ¡ D ]}| | ¡ ¡ qt|ƒS rn   )Úsetr   ÚupdaterM   ©r(   r`   r„   r+   r+   r,   rM   ³  s    zMultiLocation.listc                 C   s    |   |¡}|d u rd S | |¡S rn   )r†   rE   ©r(   r2   r„   r+   r+   r,   rE   »  s    
zMultiLocation.mtimec                 C   s    |   |¡}|d u rd S | |¡S rn   )r†   rP   r   r+   r+   r,   rP   Ã  s    
zMultiLocation.jsonc                 C   s    |   |¡}|d u rd S | |¡S rn   )r†   r^   r   r+   r+   r,   r^   Ë  s    
zMultiLocation.screenshotc                 C   s   |   |¡}| |¡S rn   )r†   r@   r   r+   r+   r,   r@   Ó  s    
zMultiLocation.loadc                 C   s   |   ¡ D ]}| |¡ qd S rn   )r   r#   r   r+   r+   r,   r#   ×  s    zMultiLocation.unlinkc                 C   s   |   ¡ D ]}| ||¡ qd S rn   )r   re   ©r(   rb   rc   r„   r+   r+   r,   re   Û  s    zMultiLocation.renamec                 C   s   |   ¡ D ]}| ||¡ qd S rn   )r   rh   rŽ   r+   r+   r,   rh   ß  s    zMultiLocation.copyc                 C   s$   g }|   ¡ D ]}| | ¡ ¡ q|S rn   )r   Úextendri   rŒ   r+   r+   r,   ri   ã  s    zMultiLocation.load_persistentc                 C   s   |   ¡ D ]}| |¡ qd S rn   )r   rm   )r(   rG   r„   r+   r+   r,   rm   ë  s    zMultiLocation.save_persistentc                 C   s   |   ¡ D ]}| ¡  qd S rn   )r   ro   ©r(   r„   r+   r+   r,   ro   ð  s    zMultiLocation.unlink_persistentc                 C   s   | j D ]}| ¡  qd S rn   )r|   rH   r   r+   r+   r,   rH   õ  s    
zMultiLocation.scanc                 C   s   t |tƒsdS | j|jkS rp   )rq   rz   r|   rr   r+   r+   r,   rt   ü  s    
zMultiLocation.__eq__c                 C   s
   | |k S rn   r+   rr   r+   r+   r,   ru     s    zMultiLocation.__ne__N)rv   rw   rx   ry   r-   r   r†   rˆ   rL   rM   rE   rP   r^   r@   r#   re   rh   ri   rm   ro   rH   rt   ru   r+   r+   r+   r,   rz   |  s(   
rz   Fc                   C   s`   da t s\ztjj ¡  W n ty*   Y n0 t t d¡ W d   ƒ q1 sP0    Y  qd S )NFg      @)Úquit_scan_threadr   Úloadsaverƒ   rH   r   Úscan_thread_conditionÚwaitr+   r+   r+   r,   Úrun_scan_thread  s    r•   c                   C   sD   t  dat  ¡  W d   ƒ n1 s&0    Y  td ur@t ¡  d S )NT)r“   r‘   Ú
notify_allÚscan_threadr!   r+   r+   r+   r,   Úquit   s
    &r˜   c                  C   sl   t ƒ } |  ttjjƒ¡ tjsDtjsDtj	 
tjjd¡}|  t|ƒ¡ |  ¡  | tj_tjtdat ¡  d S )NÚsaves)Útarget)rz   rˆ   r   r   ÚconfigÚsavedirÚmobileÚmacappr   r    r!   ÚgamedirrH   r’   rƒ   Ú	threadingÚThreadr•   r—   Ústart)rƒ   r    r+   r+   r,   Úinit+  s    r£   )+Ú
__future__r   r   r   r   r   Úrenpy.compatr   r   r	   r
   r   r   r   r   r   r   r   r   r   rS   rP   r   r    Úrenpy.loadsaver   r   rf   ÚRLockr8   ÚtimeÚintra   Úobjectr   rz   r—   r‘   Ú	Conditionr“   r•   r˜   r£   r+   r+   r+   r,   Ú<module>   s,   8  L 