Flash存档生成机制及应对方案

对外链接:SS同盟
给Flash游戏留个纪念。
 
常规生成机制
Adobe Flash存档在固定位置,总体讲就是在C:\Users\a\AppData\Roaming\Macromedia\Flash Player\#SharedObjects目录下,不会根据本地文件或网页进行变动(本文主要针对本地文件),#SharedObjects内存储的sol文件,即为真实的存档。可以在运行输入%appdata%,直接进入Roaming文件夹,或将#SharedObjects文件夹生成快捷方式。以上内容均可百度,不赘述。
下面分析一下Flash的存档机制,由于Flash载体以网页为主,其存档方式更接近于网页缓存。在#SharedObjects中(下称“根目录”),一级文件夹由8字符随机命名(大写字母+数字,例如SU33B8NB),每当一级文件夹被删除或重命名,Flash存档会生成全新一级文件夹(随机命名),旧一级文件夹失效。

f:id:Soki_Arra:20210417015550p:plain

一级文件夹下固定存在localhost文件夹,从localhost开始,Flash存档位置正式分流。

f:id:Soki_Arra:20210417015630p:plain

localhost内的路径结构(sol的存储路径),是模拟本地文件路径或网页生成的。假设我们执行C:\temp_game\finalizer\DenZel - simseh 1 Hornbrook v1.0.swf并存档。

f:id:Soki_Arra:20210417015655p:plain

localhost内会生成temp_game\finalizer\DenZel - simseh 1 Hornbrook v1.0.swf\finalizer.sol。

f:id:Soki_Arra:20210417015729p:plain

棘手的地方在于,sol文件和路径必须要正确对应本地文件路径才能生效,若将本地文件移动,则必须在localhost内生成新的存档路径与之对应,但sol文件可以通用。所以常规办法为,结束游戏后单独保存sol文件,如果环境变化,先运行游戏,存档,生成一次localhost文件夹路径和新sol文件,再将sol文件覆盖掉。
 
不规则情况
上述可以覆盖大多情况,但Flash也经常不按套路出牌,主要分为两大类。
其一,Flash在localhost内生成#开头随机命名文件夹,内部直接存储sol文件,通常命名为00000001.sol(出现重名情况自动生成00000002.sol),完全无视结构规则。

f:id:Soki_Arra:20210417015729p:plain

从经验判断,此类大概率是本地文件路径过长超出系统位数,或存在无法读取的字符导致。用该方式生成的存档,sol自身的命名和路径都写在文件内部,可控性较差,环境变化后很难复现存档。规避此类问题主要靠简化本地文件路径,例如在C盘自建文件夹运行游戏。
其二,部分制作者考虑到Flash游戏读档困难,在游戏逻辑内固定了localhost内部路径。常见为直接存储至localhost根目录,或localhost\xxx\下,不需要根据本地文件路径生成对应路径。与其一的区别是,此类存档有自己独立的命名,且无需考虑本地文件的位置,存档路径都是固定通用的,可以理解为升级版的常规存档。

f:id:Soki_Arra:20210417015832j:plain

 

应对方案
为了避开各种雷区,最稳妥的方式为:先创建临时游戏文件,然后存档一次生成localhost路径,最后把自己的sol存档覆盖过去。一套流程下来很繁琐,这里提供一版BAT方案,简单快捷。新建TXT粘贴,自定义路径信息,使用ANSI编码。后面解析一下BAT代码内容,方便进行自定义。
附赠实例游戏:提取码cdtj
 
 
布置临时的游戏文件和存档:
@ echo off(命令行不显示命令代码)
@cd/d"%~dp0"&(cacls "%SystemDrive%\System Volume Information" >nul 2>nul)||(start "" mshta vbscript:CreateObject^("Shell.Application"^).ShellExecute^("%~nx0"," %*","","runas",1^)^(window.close^)&exit /b)(判断是否需要管理员权限运行)
echo 1.获取管理员权限(主动输出文字)
 
 
set original_game=%~dp0a(%~dp0a指和bat同目录的a文件夹,里面额外存储了完整的游戏文件,用来作复制源)
set original_save=%~dp0finalizer.sol(%~dp0finalizer.sol指和bat同目录的finalizer.sol,保存进度的存档,用来作复制源)
set temp_game=C:\temp_game\finalizer(C盘的临时游戏位置)
set temp_save=%AppData%\Macromedia\Flash Player\#SharedObjects\WFH2Q2X2\localhost\temp_game\finalizer\DenZel - simseh 1 Hornbrook v1.0.swf(常规存档路径)
echo 2.读取预设路径
(自定义内容主要都在这部,可以自行更改路径位置)
 
md "%temp_game%" > nul(生成临时游戏位置)
xcopy "%original_game%" "%temp_game%" /s/y > nul(把游戏文件复制到临时位置)
echo 3.创建游戏临时位置
 
md "%AppData%\Macromedia\Flash Player\#SharedObjects" > nul(生成#SharedObjects文件夹,该文件夹若不存在影响下述操作)
rd "%AppData%\Macromedia\Flash Player\#SharedObjects" /s/q > nul(清空#SharedObjects文件夹)
echo 4.初始化Flash存档位置
 
md "%temp_save%" > nul(生成常规存档路径)
copy "%original_save%" "%temp_save%\finalizer.sol" > nul(将保存进度的存档复制到该位置)
echo 5.创建存档临时位置
 
start "" "C:\temp_game\finalizer\DenZel - simseh 1 Hornbrook v1.0.swf"(运行临时位置的游戏文件)
echo 6.运行游戏
 
@echo.
echo 该窗口3秒后自动关闭...
ping 127.1 -n 4 >nul
 
清除临时的游戏文件:
@ echo off(命令行不显示命令代码)
@cd/d"%~dp0"&(cacls "%SystemDrive%\System Volume Information" >nul 2>nul)||(start "" mshta vbscript:CreateObject^("Shell.Application"^).ShellExecute^("%~nx0"," %*","","runas",1^)^(window.close^)&exit /b)(判断是否需要管理员权限运行)
echo 1.获取管理员权限(主动输出文字)
 
set temp_game=C:\temp_game(指定清除路径)
echo 2.读取预设路径
 
rd "%temp_game%" /s/q > nul(清除该路径下的全部文件)
echo 3.删除游戏临时文件
 
@echo.
echo 该窗口3秒后自动关闭...
ping 127.1 -n 4 >nul