def save(self): fn = self._filename with open(fn + ".new", "wb") as f: dump(self, f) try: os.rename(fn + ".new", fn) except Exception: os.unlink(fn) os.rename(fn + ".new", fn)
def dump(o, f): if renpy.config.use_cpickle: cPickle.dump(o, f, cPickle.HIGHEST_PROTOCOL) else: pickle.dump(o, f, pickle.HIGHEST_PROTOCOL)
def save(slotname, extra_info='', mutate_flag=False): """ :doc: loadsave :args: (filename, extra_info='') Saves the game state to a save slot. `filename` A string giving the name of a save slot. Despite the variable name, this corresponds only loosely to filenames. `extra_info` An additional string that should be saved to the save file. Usually, this is the value of :var:`save_name`. :func:`renpy.take_screenshot` should be called before this function. """ # Update persistent file, if needed. This is for the web and mobile # platforms, to make sure the persistent file is updated whenever the # game is saved. (But not auto-saved, for performance reasons.) if not mutate_flag: renpy.persistent.update() if mutate_flag: renpy.revertable.mutate_flag = False roots = renpy.game.log.freeze(None) if renpy.config.save_dump: save_dump(roots, renpy.game.log) logf = io.BytesIO() try: dump((roots, renpy.game.log), logf) except Exception: t, e, tb = sys.exc_info() if mutate_flag: reraise(t, e, tb) try: bad = find_bad_reduction(roots, renpy.game.log) except Exception: reraise(t, e, tb) if bad is None: reraise(t, e, tb) if e.args: e.args = (e.args[0] + ' (perhaps {})'.format(bad), ) + e.args[1:] reraise(t, e, tb) if mutate_flag and renpy.revertable.mutate_flag: raise SaveAbort() screenshot = renpy.game.interface.get_screenshot() json = { "_save_name": extra_info, "_renpy_version": list(renpy.version_tuple), "_version": renpy.config.version } for i in renpy.config.save_json_callbacks: i(json) json = json_dumps(json) sr = SaveRecord(screenshot, extra_info, json, logf.getvalue()) location.save(slotname, sr) location.scan() clear_slot(slotname)