RPGツクールXP/VX用のRGSS素材です。
一部英語版対応です。
(A few materials can be used for English RPG MAKER XP/VX.)
競合率はルファーの独断と偏見なのでたまにハズレます。
#==============================================================================
# ■ セーブデータのチェック
#------------------------------------------------------------------------------
# セーブ失敗やデータ改ざんの対策です。
# (C) ルファー
# WebSite https://tkoolerlufar.pages.dev/
#==============================================================================
=begin
=対応RGSS
1 2
=必要なライブラリ
ルファー作スクリプト素材共通ライブラリ
=他の素材との競合の可能性
!.. セーブファイルの名前や保存先を変更していない限りは大丈夫
=RPGツクールXPでの導入方法
Scene_Save より下に新セクションを作成して、
このプログラムをそこにコピーする
=セーブファイルの扱いについて
セーブに失敗したりデータを改ざんされたりすると、
セーブデータの中身がおかしくなってしまいます。
それを検知した場合、そのファイルを削除して
バックアップファイルから元のファイルを復元します。
大体256壊のうち255壊くらい検知できます。
バックアップファイルの名前は「Save0(ファイル番号).rxdata」となります。
名前がこのようになっているのは、「ゲームデータの圧縮」を行う際に
デバッグ時のセーブデータのバックアップが
圧縮データに含まれないようにするためです。
=セーブファイルの最大数を増やしてる方へ
61行目にある「SAVEFILES_MAX」という定数の値を変更すれば、
その数のセーブファイルに対応できます。
大きすぎてもエラーにはなりませんが、
処理が遅くなるので最大数ちょうどになるように指定してください。
=更新履歴
2010/03/01 公開
=再定義しているメソッド (RPGツクールXPのみ)
Scene_File#main (エイリアス使用)
Scene_Save#on_decision (エイリアス使用)
Scene_Save#write_save_data (エイリアス使用)
=再定義しているメソッド (RPGツクールVXのみ)
Scene_File#start (エイリアス使用)
Scene_File#do_save (エイリアス使用)
Scene_File#write_save_data (エイリアス使用)
=新規定義しているメソッド
なし
=end
#----------------------------------------------------------------------------
# ◇ Lufar モジュール
#----------------------------------------------------------------------------
module Lufar
#--------------------------------------------------------------------------
# ○ 定数
#--------------------------------------------------------------------------
SAVEFILES_MAX = 4 ## 最大ファイル数
#--------------------------------------------------------------------------
# ◇ File クラス
#--------------------------------------------------------------------------
class File < ::File
#------------------------------------------------------------------------
# ○ ファイルのコピー
# source : コピー元のファイル名
# destination : コピー先のファイル名
#------------------------------------------------------------------------
def self.copy(source, destination)
unless source.instance_of?(String) and destination.instance_of?(String)
raise(TypeError, sprintf(
"Lufar::File.copy の引数の型が異常です:\nsource=%s\ndestination=%s",
source.inspect, destination.inspect
), caller)
end
begin
file1 = self.open(source, "rb")
begin
file2 = self.open(destination, "wb")
rescue
file1.close
raise
end
file2.write(file1.read())
file1.close
file2.close
nil
rescue SystemCallError
$@ = caller
raise
end
end
end
#--------------------------------------------------------------------------
# ◇ SafeFile モジュール
#--------------------------------------------------------------------------
module SafeFile
module_function
##-----------------------------------------------------------------------
## ○ ファイル名の作成
## file_index : セーブファイルのインデックス (0~)
##-----------------------------------------------------------------------
def make_filename(file_index)
return sprintf("Save%d.r%cdata", file_index + 1, rpgxp? ? ?x : ?v)
end
##-----------------------------------------------------------------------
## ○ バックアップファイル名の作成
## file_index : セーブファイルのインデックス (0~)
##-----------------------------------------------------------------------
def make_backup_filename(file_index)
return sprintf("Save0%d.r%cdata", file_index + 1, rpgxp? ? ?x : ?v)
end
#------------------------------------------------------------------------
# ○ パリティチェック
#------------------------------------------------------------------------
def check_parity(file)
unless file.kind_of?(::File)
raise(TypeError, sprintf(
"パリティチェックはファイルストリームのみ可能です(%s)",
file.class.to_s), caller)
end
begin
parity_byte = 0xFF
file.rewind
file.each_byte do |byte|
parity_byte ^= byte
end
return parity_byte == 0
rescue SystemCallError
$@ = caller
raise
end
end
#------------------------------------------------------------------------
# ○ バックアップの作成
#------------------------------------------------------------------------
def make_backup(file_index)
begin
File.copy(make_filename(file_index), make_backup_filename(file_index))
rescue SystemCallError
$@ = caller
raise
end
end
#------------------------------------------------------------------------
# ○ バックアップの復元
#------------------------------------------------------------------------
def restore_backup(file_index)
begin
File.copy(make_backup_filename(file_index), make_filename(file_index))
rescue SystemCallError
$@ = caller
raise
end
end
#------------------------------------------------------------------------
# ○ セーブファイルの破損・改ざんチェック
#------------------------------------------------------------------------
def check_savefiles
## パリティチェック
## セーブファイル破損・改造の可能性があれば削除
## このときバックアップがあれば復元
for i in 0...SAVEFILES_MAX
filename = make_filename(i)
## 空きファイルなら次へ
next if !FileTest.file?(filename)
file = File.open(filename, "rb")
flg = check_parity(file)
file.close
## 正常なら次へ
next if flg
File.delete(filename)
filename = make_backup_filename(i)
## バックアップファイルが無ければ次へ
next if !FileTest.file?(filename)
## バックアップも破損・改造の可能性があれば削除
file = File.open(filename, "rb")
flg = check_parity(file)
file.close
if flg
restore_backup(i)
else
File.delete(filename)
end
end
end
#------------------------------------------------------------------------
# ○ パリティバイトの書き込み
#------------------------------------------------------------------------
def write_parity_byte(file)
unless file.kind_of?(::File)
raise(TypeError, sprintf(
"パリティバイトの書き込みはファイルストリームのみ可能です(%s)",
file.class.to_s), caller)
end
begin
file.reopen(file.path, "r+b")
parity_byte = 0xFF
file.each_byte do |byte|
parity_byte ^= byte
end
file.putc(parity_byte)
rescue SystemCallError
$@ = caller
raise
end
end
end
end
#----------------------------------------------------------------------------
# ◆ Scene_File クラス
#----------------------------------------------------------------------------
class Scene_File
if rpgxp?
#------------------------------------------------------------------------
# ● メイン処理
#------------------------------------------------------------------------
alias _Lufar_Backup_old_main main
def main
Lufar::SafeFile.check_savefiles
_Lufar_Backup_old_main
end
else
#------------------------------------------------------------------------
# ● 開始処理
#------------------------------------------------------------------------
alias _Lufar_Backup_old_start start
def start
Lufar::SafeFile.check_savefiles
_Lufar_Backup_old_start
end
end
end
if rpgxp?
#--------------------------------------------------------------------------
# ◆ Scene_Save クラス
#--------------------------------------------------------------------------
class Scene_Save < Scene_File
#------------------------------------------------------------------------
# ● 決定時の処理
#------------------------------------------------------------------------
alias _Lufar_Backup_old_od on_decision
def on_decision(filename)
## 決定時の処理
_Lufar_Backup_old_od(filename)
## セーブデータのバックアップ
Lufar::SafeFile.make_backup(@file_index)
end
#------------------------------------------------------------------------
# ● セーブデータの書き込み
# file : 書き込み用ファイルオブジェクト (オープン済み)
#------------------------------------------------------------------------
alias _Lufar_Backup_old_wsd write_save_data
def write_save_data(file)
## セーブデータの書き込み
_Lufar_Backup_old_wsd(file)
## パリティバイトの書き込み
Lufar::SafeFile.write_parity_byte(file)
end
end
else
#--------------------------------------------------------------------------
# ◆ Scene_File クラス
#--------------------------------------------------------------------------
class Scene_File
#------------------------------------------------------------------------
# ● セーブの実行
#------------------------------------------------------------------------
alias _Lufar_Backup_old_ds do_save
def do_save
## 決定時の処理
_Lufar_Backup_old_ds
## セーブデータのバックアップ
Lufar::SafeFile.make_backup(@index)
end
#------------------------------------------------------------------------
# ● セーブデータの書き込み
# file : 書き込み用ファイルオブジェクト (オープン済み)
#------------------------------------------------------------------------
alias _Lufar_Backup_old_wsd write_save_data
def write_save_data(file)
## セーブデータの書き込み
_Lufar_Backup_old_wsd(file)
## パリティバイトの書き込み
Lufar::SafeFile.write_parity_byte(file)
end
end
end
戻る