rpgmaker-linux/mkxp-z/Kawariki-patches/ports/testencode.rb
2024-11-21 15:53:35 +02:00

1080 lines
46 KiB
Ruby

# ===========================================================================
# ★ WF-RGSS Scripts ★
# 共通スクリプト(XP/VX/VXAce両対応版)
# バージョン : rev-29 (2013-3-26)
# 作者 : A Crying Minister (WHITE-FLUTE)
# サポート先URI: http://www.whiteflute.org/wfrgss/
# ---------------------------------------------------------------------------
# 機能:
# ・このセクションより後ろのスクリプトでSyntaxError が発生しても
# 別の例外にすりかえられるため、詳細情報が削除されなくなります。
# (VXAceでは標準で削除されなくなりました。)
# ・SyntaxErrorの情報をファイルに書き出します。
# ・不用意なデバッグモードへの遷移を防止します。
# (元からデバッグモードの場合は問題ありません。)
# ・不正なデバッグモードへの遷移を阻害します。
# ・デバッグコンソールを表示しデバッグしやすくします。
# ---------------------------------------------------------------------------
# 影響:
# ・外部コマンド実行など一部の組み込み関数が未定義になります。
# ・例外 SyntaxError は作成できません。(XP/VX)
# (※ ScriptSyntaxError にすりかえられます。)
# ---------------------------------------------------------------------------
# 設置場所:一番最初のセクション(Game_Temp(XP)/モジュール(VX/VXAce)よりも前)
# 必要スクリプト:
# ・共通実行スクリプト(VXAce は、Exit-EXで置き換える事ができます。)
# 注意事項:
# 共通実行スクリプトをMainセクションに上書きして利用することを推奨します。
# ===========================================================================
BEGIN {
module WFRGSS
# -------------------------------------------------------------------------
# ● 調整ポイント
# -------------------------------------------------------------------------
# デバッグモード遷移を阻害するかを設定します。
# 確実に保護できるわけではありませんので過信は禁物です。
DEBUG_CHECK = true
# -------------------------------------------------------------------------
# デバッグモード時、デバッグコンソールを表示します。
# (VXAceでは設定に関わらず標準装備されています。)
DEBUG_CONSOLE = false
# -------------------------------------------------------------------------
# リリースモード時、デバッグメッセージを消去します。
DELETE_DEBUG_MESSAGE = false
# -------------------------------------------------------------------------
# XPのみ。 デバッグフラグをVX/VXAce準拠に修正するか?
# (!)スクリプト対応が必要となります。
DEBUG_FLAG_CHANGE = false
# -------------------------------------------------------------------------
# 調整ポイント終わり
# -------------------------------------------------------------------------
end
# ---------------------------------------------------------------------------
# ● 例外定義
# ---------------------------------------------------------------------------
# 継承例外
class InheritanceError < Exception;end
# Mix-in 例外
class IncludeError < Exception;end
# 仮想クラス、メソッドの使用
class AbstractError < NotImplementedError;end
# ◆ バグ検出
# バグ以外、絶対にありえない状態になったときに発生させてください。
# ※ バグ報告を行うためのものなので途中で破棄してはいけません。
class BugDetected < Exception;end
# ◆ 内部バグ報告用
# これは、WFRGSS でバグしかありえない状態に陥ったときに発生します。
# ※ バグ報告を行うためのものなので途中で破棄してはいけません。
class InternalBugDetected < BugDetected;end
# イベント階層が深すぎる場合
class EventDeepError < SystemStackError;end
# 初期化失敗
class InitializeError < TypeError;end
# アサーション失敗
class AssertionError < Exception;end
# ◆ 例外 Hangup
# ハングアップしたとみなされたときに投げられる例外。
# 深い階層からでは捉えられないことがあるため、注意が必要
# RPGVX/VXAceにはありませんが、XPとの互換性を保つため、設定しています。
class Hangup < Exception;end
# ◆ 例外 Reset
# Graphics.update の呼び出し時にF12が押されていると投げられる例外。(XP)
# F12 が押されていると投げられる例外(VX)
# これがセクション外に出ると
# 最初のセクションから再び実行をやり直そうとします。
# この操作は、組み込みクラスのメソッドにて、
# alias や undef が使われていると
# 不具合の元になります。
class Reset < Exception;end
# セキュリティ違反
class SecurityHazard < Exception;end
# RPGXP互換性のため
if WFRGSS::DEBUG_FLAG_CHANGE
$TEST = $DEBUG
$DEBUG = false
else
$TEST = false unless $TEST
end
module WFRGSS
@@debug = ($TEST or $DEBUG)
def self.check
debug = ($TEST or $DEBUG)
if debug != @@debug or (@@debug and
(FileTest.file?("Game.rgssad") or FileTest.file?("Game.rgss2a") or
FileTest.file?("Game.rgss3a")))
raise(SecurityHazard ,"Insecure - debug flag can't be change.")
end
end
end
# ---------------------------------------------------------------------------
# ◆◆ デバッグモード阻止対策
# ---------------------------------------------------------------------------
# デバッグモード防止策
if defined? untrace_var
undef untrace_var
# デバッグモードでない場合、デバッグモードへの遷移を禁止する
proc = Proc.new {
if $DEBUG
$DEBUG = false
$TEST = false
$BTEST = false
raise(SecurityHazard ,"Insecure - debug flag can't be change.", caller(1))
end
}
trace_var( :$DEBUG , proc )
trace_var( :$-d , proc ) # $DEBUG の別名
proc = nil
# デバッグモードでない場合、デバッグモードへの遷移を禁止する
proc = Proc.new {
if $TEST
$DEBUG = false
$TEST = false
$BTEST = false
raise(SecurityHazard ,"Insecure - debug flag can't be change.", caller(1))
end
}
trace_var( :$TEST , proc ) # RPGVX デバッグフラグ
proc = nil
# 戦闘テストで無い場合、戦闘テストへの遷移を禁止する
proc = Proc.new {
if $BTEST
$DEBUG = false
$TEST = false
$BTEST = false
raise(SecurityHazard ,"Insecure - battle test flag can't be change.",
caller(1))
end
}
trace_var( :$BTEST , proc )
proc = nil
end
unless defined? ScriptSyntaxError
# RGSSでは、本来持っているSyntaxErrorの詳細情報をすべて削除してしまい、
# デバッグが非常に困難になってしまいます。
# そのために用意されている例外です。
# ※特にイベントスクリプト上でSyntaxErrorを出すととても悲惨なことに…
# 「スクリプト実行中に SyntaxError が発生しました。」だけで
# すぐに修正できるのでしょうか?
class ScriptSyntaxError < Exception;end
# -------------------------------------------------------------------------
# ◆ 組み込み例外クラス SyntaxError <obsolete>
# -------------------------------------------------------------------------
# RGSSでは、本来持っているSyntaxErrorの詳細情報をすべて削除してしまうため、
# SyntaxError のコンストラクタを乗っ取って別の例外にすりかえています。
# ※ SyntaxError のインスタンスは作成できません。
class SyntaxError < ScriptError
ERROR = Hash.new
end
class << SyntaxError
#--------------------------------------------------------------------------
# ◆ (!※継承禁止※!)
#--------------------------------------------------------------------------
def SyntaxError.inherited( subclass )
raise( InheritanceError ,
"can't inherit class #{subclass} from #{self}" , caller(1) )
end
private_class_method(:inherited)
unless defined? BasicObject
undef allocate
undef new
#------------------------------------------------------------------------
# ◆ 強制的に別の例外にすりかえる
#------------------------------------------------------------------------
def new( errors , *args )
error_message = make_error_message(errors)
error_message_dump(error_message)
ScriptSyntaxError.new(error_message)
end
else
alias __wfrgss__new__ new unless $!
def new( errors , *args )
error_message = make_error_message(errors)
error_message_dump(error_message)
__wfrgss__new__(errors)
end
end
private
#----------------------------------------------------------------------------
# ◆(内部専用)◆ エラーメッセージ作成
#----------------------------------------------------------------------------
def make_error_message( error_message )
extra = ""
unless (error_message[/^(?:Section)?{?(\d+)}?:(\d+):/]).nil?
nums = $1.to_i # セクションを拾い出した場合
extra = $RGSS_SCRIPTS.at(nums).at(1)
unless $2.nil?
lines = $2.to_i
unless ($RGSS_SCRIPTS.at(nums).at(3)).nil?
details = show_details_source_code( nums , lines )
unless details.empty?
error_message += "\n** script source code:\n#{details}"
else
error_message +=
"\n** script source code:#{lines} unknown data.\n"
end
end
end
end
error_message.gsub!(/^(?:Section)?{?(\d+)}?:/){"( #{extra} ):#{$1}:lines "}
error_message
end
#--------------------------------------------------------------------------
# ◆(内部専用)◆ 情報を書きこみ
#--------------------------------------------------------------------------
def error_message_dump(error_message)
e = Zlib::crc32(error_message)
return if SyntaxError::ERROR[e]
SyntaxError::ERROR[e] = true
File.open("syntaxerror.txt","a") do | file |
file.write("*SyntaxError - " +
(Time.now).strftime("%Y-%m-%d %H:%M:%S (%A)") + "\n")
file.write( "#{error_message}\n" )
end
end
#--------------------------------------------------------------------------
# ◆(内部専用)◆ ソースコード位置読み込み
#--------------------------------------------------------------------------
def show_details_source_code( nums , lines )
details = ""
splitstr = ($RGSS_SCRIPTS.at(nums).at(3)).split(/\r\n/)
if lines < 4
ranges = ( 0...( lines + 3 ))
else
ranges = (( lines - 4 )...( lines + 3 ))
end
for i in ranges
unless (splitstr.at(i)).nil?
if i != (lines - 1)
details += "|" + splitstr.at(i) + "\n"
else
details += ">" + splitstr.at(i) + "\n"
end
else
details += "[End of File]\n"
break
end
end
splitstr = nil
rpgvxace? ? details.force_encoding("UTF-8") : details
end
end
# -------------------------------------------------------------------------
# ◆ RGSS 組み込みモジュール Graphics
# -------------------------------------------------------------------------
class << Graphics
#------------------------------------------------------------------------
# ◆ リセットを無視する Graphics.update
#------------------------------------------------------------------------
def Graphics.safe_update
begin
update
rescue Reset
# リセット操作を無視する。
# ただしカーソルアニメーションなどが巻き戻される。
nil
end
end
if WFRGSS::DEBUG_CHECK
#------------------------------------------------------------------------
# ◆ Graphics.update にチェックを加える
#------------------------------------------------------------------------
alias ___original__update___ update
def Graphics.update
WFRGSS.check
___original__update___
end
private(:___original__update___)
end
end
module Graphics
# -----------------------------------------------------------------------
# ◆ クラス変数
# -----------------------------------------------------------------------
@@rate = 0
@@count = 0
# -----------------------------------------------------------------------
# ◆ フレームレートを一時的に変更
# -----------------------------------------------------------------------
def self.frame_workset( frame_rates )
@@rate = Graphics.frame_rate
@@count = Graphics.frame_count
Graphics.frame_rate = frame_rates
end
# -----------------------------------------------------------------------
# ◆ フレームレートを元に戻す
# -----------------------------------------------------------------------
def self.frame_restore
cnt = Graphics.frame_count - @@count
cnt *= @@rate
cnt /= Graphics.frame_rate
Graphics.frame_count = @@count + cnt
Graphics.frame_rate = @@rate
end
# -----------------------------------------------------------------------
# ◆ 解像度横の幅(VX/VXAceでは無視される)
# -----------------------------------------------------------------------
unless defined? Graphics.width
def self.width
640
end
end
# -----------------------------------------------------------------------
# ◆ 解像度縦の幅(VX/VXAceでは無視される)
# -----------------------------------------------------------------------
unless defined? Graphics.height
def self.height
480
end
end
end
end
# ---------------------------------------------------------------------------
# ◆ 組み込みモジュール GC
# ---------------------------------------------------------------------------
module GC
module_function
#--------------------------------------------------------------------------
# ◆ 安全にガーベージコレクションを行う
#--------------------------------------------------------------------------
def update_start
Graphics.safe_update
start
Graphics.safe_update
end
end
}
unless defined? Abstract
# -----------------------------------------------------------------------------
# ◆◆ 組み込みクラス Class
# -----------------------------------------------------------------------------
class Class
# ---------------------------------------------------------------------------
# ◆ クラス変数
# ---------------------------------------------------------------------------
@@_abstract_class = Hash.new
# ---------------------------------------------------------------------------
# ◆ 抽象クラス追加
# ---------------------------------------------------------------------------
def self.abstract_class( klass )
__failure_type_call__( klass ) unless klass.is_a?(Class)
unless @@_abstract_class[klass.__id__]
@@_abstract_class[klass.__id__] = klass
end
end
# ---------------------------------------------------------------------------
# ◆ 抽象クラス判定
# ---------------------------------------------------------------------------
def self.abstract?( klass )
@@_abstract_class[klass.__id__]
end
end
module Abstract
# ---------------------------------------------------------------------------
# ◆ 抽象化
# ---------------------------------------------------------------------------
def self.included( klass )
if klass.include?(FinalClass)
# FinalClass モジュールが既にインクルードされている
raise( IncludeError ,
"can't include #{klass} from #{self}" , caller(1) )
end
Class.abstract_class( klass )
klass.extend(Abstract_Class__)
end
private_class_method(:included)
end
# ---------------------------------------------------------------------------
# ◆ 抽象化 ※ 特異メソッド専用 ※
# ---------------------------------------------------------------------------
module Abstract_Class__
# -------------------------------------------------------------------------
# ◆ ※ 抽象クラス
# -------------------------------------------------------------------------
def allocate
return super unless Class.abstract?( self )
raise( AbstractError ,
"class #{self} cannot use it because of the abstraction class.",
caller(1) )
end
# -------------------------------------------------------------------------
# ◆ ※ 抽象クラス
# -------------------------------------------------------------------------
def new( *args )
return super unless Class.abstract?( self )
raise( AbstractError ,
"class #{self} cannot use it because of the abstraction class.",
caller(1) )
end
# -------------------------------------------------------------------------
# ◆ ※ Mix-in 制限
# -------------------------------------------------------------------------
def self.included( klass )
unless self.is_a?(Class)
raise( IncludeError ,
"can't include #{klass} from #{self}" , caller(1) )
end
end
end
module FinalClass
# ---------------------------------------------------------------------------
# ◆ 継承できないクラス
# ---------------------------------------------------------------------------
def self.included( klass )
if Class.abstract?( klass )
# Abstract モジュールが既にインクルードされている
raise( IncludeError ,
"can't include #{klass} from #{self}" , caller(1) )
end
klass.module_eval(<<-End)
def self.inherited( subclass )
raise( InheritanceError ,
sprintf(\"can't inherit class %s from %s\",subclass.inspect,
self.inspect ) , caller(1) )
end
private_class_method(:inherited)
End
end
private_class_method(:included)
end
# ---------------------------------------------------------------------------
# ◆ 組み込みモジュール Kernel
# ---------------------------------------------------------------------------
module Kernel
# ---------------------------------------------------------------------------
# ◆ 危険な関数を未定義に設定
# ---------------------------------------------------------------------------
# 外部コマンド読み込みなど危険な操作は明示的に禁止にします。
# ※ これらのコマンドの必要性が(通常は)ないうえ、
# 危険(システム破壊をもたらすことがある)なため取り外しています。
# ※ もし、これらを使用する場合は、効果と危険性を考慮してください。
# ---------------------------------------------------------------------------
# 外部コマンドを実行する。
undef ` #` # 外部コマンドを実行する。
undef exec # 外部コマンドを実行する 制御を返さない。
undef fork # サブシェルを生成する。
undef system # 外部コマンドを実行する。
undef abort # 後処理を行わずに強制終了する。後処理が必要な時に困る。
undef exit! # abort と同じ。
undef open # コマンドが実行できる。(ファイルを開くならIO.openを用いる)
#--------------------------------------------------------------------------
private
#--------------------------------------------------------------------------
# ◆ RPGVX/VXAce かどうか
#--------------------------------------------------------------------------
def rpgvx?
defined? Graphics.resize_screen
end
#--------------------------------------------------------------------------
# ◆ RPGVXAce かどうか
#--------------------------------------------------------------------------
def rpgvxace?
defined? BasicObject
end
#--------------------------------------------------------------------------
# ◆ RGSSのバージョン
#--------------------------------------------------------------------------
def rgss_version
rpgvx? ? (rpgvxace? ? 3 : 2 ) : 1
end
#--------------------------------------------------------------------------
# ◆ テストモードかどうか
#--------------------------------------------------------------------------
def debug?
$DEBUG or $TEST
end
#--------------------------------------------------------------------------
# ◆ デバッグコンソール
#--------------------------------------------------------------------------
if WFRGSS::DEBUG_CONSOLE and debug? and (not rpgvxace?)
unless $@
$VERBOSE = true
alias wfrgss_p p
Win32API.new("kernel32","AllocConsole",'v','l').call
$stdout.reopen("conout$","w")
def p(*a)
a.each{|v|$stdout.puts(String.utf82ansi(v.inspect))}
end
end
elsif WFRGSS::DELETE_DEBUG_MESSAGE
unless $@
alias display_p p
def p(*a)
# 何も出力しない
end
end
end
#--------------------------------------------------------------------------
# ◆ 例外セット
# 例外を発生させます。
#--------------------------------------------------------------------------
# ◆ method_missing と同様
#--------------------------------------------------------------------------
def __failure_method_call__( method_name , *args )
raise( NoMethodError ,
"undefined method `#{method_name}' for #{self}" , caller(2) )
end
#--------------------------------------------------------------------------
# ◆ オーバーライドが必要
#--------------------------------------------------------------------------
def __override_required_call__( method_name , *args )
raise( AbstractError ,
"It is necessary to do override to use method `#{method_name}'" +
" of this class #{self}. " +
"(or, it tried to call the method of a super-class.)" , caller(2))
end
#--------------------------------------------------------------------------
# ◆ 例外 TypeErrorを発生させる
#--------------------------------------------------------------------------
def __failure_type_call__( object_type )
e = ( object_type.class ).to_s
raise( TypeError , "no implicit conversion from #{e}" , caller(2) )
end
#--------------------------------------------------------------------------
# ◆ 例外 RangeErrorを発生させる ( num が Numeric でない場合はBugDetected )
#--------------------------------------------------------------------------
def __outof_range_call__( num , str , call_value = 2 )
if num.is_a?(Numeric)
if str.is_a?(String)
raise( RangeError , "#{num} out of range of #{str}",caller(call_value))
else
e = ( str.class ).to_s
raise(TypeError,"no implicit conversion from #{e}",caller(call_value))
end
else
e = ( num.class ).to_s
raise( BugDetected, "[BUG] no implicit conversion from #{e} (TypeError)",
caller(1))
end
end
#--------------------------------------------------------------------------
# ◆ 例外 ArgumentErrorを発生させる ( str が String でない場合はBugDetected )
#--------------------------------------------------------------------------
def __invalid_value_call__( str , value , call_value = 2 )
if str.is_a?(String)
raise( ArgumentError , "invalid #{str} for #{value.to_s}")
else
e = ( str.class ).to_s
raise( BugDetected, "[BUG] no implicit conversion from #{e} (TypeError)",
caller(1))
end
end
#--------------------------------------------------------------------------
# ◆ 例外 SecurityErrorを発生させる ( str が String でない場合はBugDetected )
#--------------------------------------------------------------------------
def __insecure_call__( str )
if str.is_a?(String)
raise( SecurityError , "Insecure operation - #{str}" , caller(2) )
else
e = ( str.class ).to_s
raise( BugDetected, "[BUG] no implicit conversion from #{e} (TypeError)",
caller(1))
end
end
#--------------------------------------------------------------------------
# ◆ バグを報告する。 ( str が String でない場合も BugDetected )
#--------------------------------------------------------------------------
def __report_bug( str )
if str.is_a?(String)
raise( BugDetected , str , caller(1))
else
e = ( str.class ).to_s
raise( BugDetected ,
"[BUG] no implicit conversion from #{e} (TypeError)" , caller(1) )
end
end
#--------------------------------------------------------------------------
# ◆ バグを報告する。(異常な値を検出)
#--------------------------------------------------------------------------
def __report_bug_invalid_value( value )
raise( BugDetected , "[BUG] invalid value for #{value}", caller(1))
end
#--------------------------------------------------------------------------
# ◆※!※◆ WF-RGSS の バグを報告する。
# ※ このメソッドは WF-RGSS 内部バグを報告するためのものです。
# ※ カスタマイズ時にバグを報告したい場合は、
# __report_bug( str ) を使用してください。
#--------------------------------------------------------------------------
def __report_internal_bug( str )
if str.is_a?(String)
raise( InternalBugDetected , str , caller(1))
else
e = ( str.class ).to_s
raise( InternalBugDetected ,
"[BUG] no implicit conversion from #{e} (TypeError)" , caller(1) )
end
end
#--------------------------------------------------------------------------
# ◆ チェック関連メソッド
# 型や範囲をチェックします。
#--------------------------------------------------------------------------
# ◆ 型が合わない場合、例外 TypeErrorを発生させる
# (※ klass が異常な場合はBugDetected )
#--------------------------------------------------------------------------
def _type_check_( object_type , klass , call_value = 2 )
begin
return if object_type.is_a?(klass)
e = ( object_type.class ).to_s
raise( TypeError,"no implicit conversion from #{e}")
rescue TypeError => errobj
# 例外の報告位置をすりかえる
if errobj.message[/^no/].nil?
raise( BugDetected , "[BUG] #{errobj.message} (TypeError)",caller(1))
else
raise( TypeError , errobj.message , caller(call_value))
end
end
end
#--------------------------------------------------------------------------
# ◆ Fixnum の範囲を検証する ※範囲が異常なら例外を発生させる
#--------------------------------------------------------------------------
def _fixnum_range_check( value , minimum , maximum )
__failure_type_call__( value , 3 ) unless value.is_a?(Fixnum)
unless value >= minimum and value <= maximum
# 範囲外のため、例外を発生させる
call_ary = caller(1)
if call_ary.size > 0
sections = call_ary.at(0)
str = sections + " ( range #{minimum} .. #{maximum} )"
else
str = "caller method (unknown) ( range #{minimum} .. #{maximum} )"
end
__outof_range_call__( value , str , 3 )
end
end
#--------------------------------------------------------------------------
# ◆ Integer の範囲にまとめる (※処理速度が求められる箇所では用いない)
# ※異常範囲が認められていない場合は、↑のメソッドを用いること
#--------------------------------------------------------------------------
def _integer_range_value( value , minimum , maximum )
__failure_type_call__( value , 3 ) unless value.is_a?(Integer)
if value < minimum
return minimum
elsif value > maximum
return maximum
else
return value
end
end
# ---------------------------------------------------------------------------
# 可視性を変更
public
# これ以降はモジュール関数として定義
module_function
# ---------------------------------------------------------------------------
# ◆ 真 を検証
# ---------------------------------------------------------------------------
def assert_if( value )
unless value
raise(AssertionError,"Assertion Failed (false for true)",caller(1))
end
end
# ---------------------------------------------------------------------------
# ◆ 偽 を検証
# ---------------------------------------------------------------------------
def assert_unless( value )
if value
raise(AssertionError,"Assertion Failed (true for false)",caller(1))
end
end
end
# ---------------------------------------------------------------------------
# ◆ 組み込みクラス Object
# ---------------------------------------------------------------------------
class Object
# 可視性を変更
private
#--------------------------------------------------------------------------
# ◆ Mix-in禁止を実装
#--------------------------------------------------------------------------
def self.__cannot_mixin( klass )
raise( IncludeError ,
"can't include #{klass} from #{self}" , caller(2) )
end
#--------------------------------------------------------------------------
# ◆ 継承禁止を実装
#--------------------------------------------------------------------------
def self.__cannot_inherited( subclass )
raise( InheritanceError ,
"can't inherit class #{subclass} from #{self}" , caller(2) )
end
#--------------------------------------------------------------------------
# ◆ 抽象クラス (かならず継承が必要となる)
#--------------------------------------------------------------------------
def __abstract_class( target )
klass = self.class
unless target.is_a?(Class) or target.is_a?(Module)
__report_bug("[BUG] class or modules required (TypeError)")
end
until ( klass = klass.superclass ) == Object
return if klass == target
end
raise( AbstractError ,
"class #{target} cannot use it because of the abstraction class.",
caller(2) )
end
end
# ---------------------------------------------------------------------------
# ◆ 組み込みクラス String
# ---------------------------------------------------------------------------
class String
# ---------------------------------------------------------------------------
# ◆ 定数
# ---------------------------------------------------------------------------
CP_ACP = 0 # ANSI コード
CP_UTF7 = 65000 # UTF-7 コード
CP_UTF8 = 65001 # UTF-8 コード
EMPTY_STR = "".freeze
#--------------------------------------------------------------------------
# ◆ クラス変数
#--------------------------------------------------------------------------
@@rm = Win32API.new('kernel32','RtlZeroMemory',%w(p l),'l').freeze
# 文字列をワイド文字列(Unicode)にマップするAPI
@@mb2wc = Win32API.new('kernel32',
'MultiByteToWideChar', %w(i l p i p i), 'l').freeze
# ワイド文字列を新しい文字列にマップするAPI
@@wc2mb = Win32API.new('kernel32',
'WideCharToMultiByte', %w(i l p i p i p p), 'l').freeze
#--------------------------------------------------------------------------
# ◆ クリア
#--------------------------------------------------------------------------
unless rpgvxace?
def clear
@@rm.call( self , self.size )
self.replace("")
end
end
#--------------------------------------------------------------------------
# ◆ エンコード
#--------------------------------------------------------------------------
def encode_by_
for i in 0...self.size
self[i] = 256 - self[i]
end
end
#--------------------------------------------------------------------------
# ◆ UTF-8 → ANSI 変換
#--------------------------------------------------------------------------
unless rpgvxace?
def self.utf82ansi(str)
to_multibyte(to_widechar(str, CP_UTF8), CP_ACP)
end
else
def self.utf82ansi(str)
result = to_multibyte(to_widechar(str, CP_UTF8), CP_ACP)
result.empty? ? result : result.force_encoding("ASCII-8BIT")
end
end
#--------------------------------------------------------------------------
# ◆ ANSI → UTF-8 変換
#--------------------------------------------------------------------------
unless rpgvxace?
def self.ansi2utf8( str )
to_multibyte( to_widechar( str , CP_ACP ) , CP_UTF8 )
end
else
def self.ansi2utf8( str )
to_multibyte(to_widechar(str,CP_ACP),CP_UTF8).force_encoding("UTF-8")
end
end
private # 可視性を private に変更
#--------------------------------------------------------------------------
# ◆(内部専用)◆ ワイド文字列( Unicode ) へ変換
#--------------------------------------------------------------------------
def self.to_widechar(str, codepage)
puts "vvvvxzz"
# Convert the string from the specified encoding to UTF-16 (which is Ruby's default wide character encoding)
return ""
end
private_class_method(:to_widechar)
#--------------------------------------------------------------------------
# ◆(内部専用)◆ ワイド文字列( Unicode ) から 文字列を取得する
#--------------------------------------------------------------------------
def self.to_multibyte(str, codepage)
# Convert a wide character string (UTF-16) to a multi-byte encoding (e.g., UTF-8 or Windows-1252)
return ""
end
private_class_method(:to_multibyte)
end
# ---------------------------------------------------------------------------
# ◆ モジュール ErrorLogWriter
# ---------------------------------------------------------------------------
module ErrorLogWriter
#--------------------------------------------------------------------------
# ◆(内部専用)◆ Mix-in 禁止
#--------------------------------------------------------------------------
def self.included( klass )
__cannot_mixin( klass )
end
private_class_method(:included)
ERROR_SECTION_NUM = (/^(?:Section)?{?(\d+)}?:/).freeze
ERROR_SECTION = (/^(?:Section)?{?\d+}?:/).freeze
DOUBLE_CRLF = (/\n\n/).freeze
# -------------------------------------------------------------------------
# ◆ エラー情報を記録 ( DEBUG のみ )
# -------------------------------------------------------------------------
def self.write( errobj )
return unless debug?
begin
begin
Graphics.safe_update
rescue SecurityHazard
end
sleep(0.1)
File.open("errors.txt","a") do | file |
file.write("*Error - " +
(Time.now).strftime("%Y-%m-%d %H:%M:%S (%A)") + "\n")
file.write( "Exception : #{errobj.class}\n" )
file.write( errobj.message )
unless $@.nil? and $@.empty?
backtrace = ""
for str in $@.dup
unless (str[ERROR_SECTION_NUM]).nil?
extra = $RGSS_SCRIPTS.at($1.to_i).at(1)
str.gsub!(ERROR_SECTION) { "( " + extra + " ):" }
end
backtrace += str
end
file.write( "\ntrace:\n" + $@.inspect + "\n" )
end
end
rescue Exception => errs
raise( errs ,
errs.message + "\n (" + (errobj.class).to_s + " )\n" + errobj.message )
end
end
end
end
def hook_exit(arg,arg2,arg3,arg4)
# puts arg,arg2,arg3,arg4
puts "Exporting [#{arg}] ##{arg2}: #{arg3} #{arg4}"
# Simulate what the hookExit function might do
# puts "Simulated hookExit called with parameter:"
# You can add more simulated behavior here, like logging, altering global variables, etc.
end
module MessageBox
#----------------------------------------------------------------------------
# ◆(内部専用)◆ Mix-in 禁止
#----------------------------------------------------------------------------
def self.included( klass )
raise( IncludeError , "can't include #{klass} from #{self}" , caller(1) )
end
private_class_method(:included)
# ---------------------------------------------------------------------------
# ◆ 定数
# ---------------------------------------------------------------------------
MB_OK = 0x0 #
MB_OKCANCEL = 0x1 #
MB_ABORTRETRYIGNORE = 0x2 #
MB_YESNOCANCEL = 0x3 #
MB_YESNO = 0x4 #
MB_RETRYCANCEL = 0x5 #
MB_ICONERROR = 0x10 # エラー
MB_ICONQUESTION = 0x20 # 問い合わせ
MB_ICONWARNING = 0x30 # 警告
MB_ICONINFORMATION = 0x40 # 情報
MB_SYSTEMMODAL = 0x1000 # システムモーダル
MB_TASKMODAL = 0x2000 # タスクモーダル
MB_TOPMOST = 0x040000 # 最前面
MB_FATAL = 0x042010 # 致命的エラー用
MB_WARN = 0x042030 # 警告
IDOK = 1
IDCANCEL = 2
IDABORT = 3
IDRETRY = 4
IDIGNORE = 5
IDYES = 6
IDNO = 7
# ---------------------------------------------------------------------------
# ◆ 内部使用定数
# ---------------------------------------------------------------------------
ERROR_SECTION_NUM = (/^(?:Section)?{?(\d+)}?:/).freeze
ERROR_SECTION = (/^(?:Section)?{?\d+}?:/).freeze
DOUBLE_CRLF = (/\n\n/).freeze
begin
# メッセージボックス
@@mb = method(:hook_exit)
rescue Exception
# 取得失敗
Script_Deleter.finalizer
raise( LoadError , "cannot read modules.(user32.dll)",caller(0))
end
begin
# ini ファイルから、セクションのキーを取得するAPI
@@gpps = Win32API.new('kernel32',
'GetPrivateProfileStringA',%w(p p p p l p),'l').freeze
rescue Exception
# 取得失敗
Script_Deleter.finalizer
raise( LoadError , "cannot read modules.(kernel32.dll)",caller(0))
end
#--------------------------------------------------------------------------
# ◆(!要注意メソッド!)◆ メッセージボックスを表示
# ※警告 :例外 Hangup 対策をかならず行うこと!
#--------------------------------------------------------------------------
def self.messagebox( message , title , type )
begin
# 停止対策用
begin
Graphics.safe_update
rescue SecurityHazard
end
@@mb.call(0, String.utf82ansi( message ), String.utf82ansi( title ),type)
rescue Hangup
nil # !※例外時にここを通過せずに外部に投げられる恐れあり
ensure
# !※例外時にここを通過せずに外部に投げられる恐れあり
begin
Graphics.safe_update
rescue SecurityHazard
end
end
end
#--------------------------------------------------------------------------
# ◆(!特定外使用禁止!)◆ 致命的エラーを通知
# ※警告 :例外 Hangup 対策をかならず行うこと!
#--------------------------------------------------------------------------
def self.fatalerror( errobj )
begin
ErrorLogWriter.write( errobj )
error_message , tracer = error_message_setup( errobj )
# 瞬間消去
Graphics.transition(0)
Audio.bgm_stop
Audio.bgs_stop
Audio.me_stop
Audio.se_stop
if debug? and ( not (tracer[/^(?:Section)?{?(\d+)}?:(\d+)/]).nil? )
# セクションを拾い出した場合
nums = $1.to_i
extra = $RGSS_SCRIPTS.at(nums).at(1)
lines = $2.to_i
tracer = "#{extra}#{lines} 行目で、\n"
error_message = tracer + error_message
end
title = "\x00" * 256
@@gpps.call( 'Game' , 'Title' , '' , title , 255 , '.\\Game.ini' )
title = String.ansi2utf8(title)
title.tr("\x00","")
# マウスカーソルを表示
Input.mouse_show if Input.method_defined?(:mouse_show)
# メッセージボックス
puts error_message , title , MB_FATAL
messagebox( error_message , title , MB_FATAL )
rescue Hangup
nil # !※例外時にここを通過せずに外部に投げられる恐れあり
end
rescue Hangup
nil
end
# ---------------------------------------------------------------------------
# ◆ 異常終了のメッセージを整形
# ---------------------------------------------------------------------------
def self.error_message_setup( errobj )
Graphics.freeze
begin
Graphics.safe_update
rescue SecurityHazard
end
_message = ""
# バックトレースを記憶する
unless $@.nil? or ($@.at(0)).nil?
tracer = ($@.at(0)).dup
# バックトレースを解析する
backtrace = ""
i = 0
for str in $@.dup
unless (str[ERROR_SECTION_NUM]).nil?
extra = $RGSS_SCRIPTS.at($1.to_i).at(1)
str.gsub!(ERROR_SECTION) { "( " + extra + " ):" }
end
backtrace += str
end
unless errobj.is_a?(SystemStackError)
if rpgvxace?
_message = errobj.message.force_encoding("UTF-8") +
"\n** backtrace:\n" + backtrace
else
_message = errobj.message + "\n** backtrace:\n" + backtrace
end
end
else
tracer = "" # バックトレース取得失敗
if rpgvxace?
_message = errobj.message.force_encoding("UTF-8")
else
_message = errobj.message
end
end
until (_message[DOUBLE_CRLF]).nil?
_message.gsub!(DOUBLE_CRLF){ "\n" }
end
if debug?
_message = "解決できない例外 " + (errobj.class).inspect +
" が発生したため、処理を継続できません。\n" +
_message
else
_message = "解決できない例外 " + (errobj.class).inspect +
" が発生したため、処理を継続できませんでした。\n" +
"お手数をおかけして申し訳ありません。\n\n詳細情報:\n" +
_message
end
return _message, tracer
end
end
# RGSS2 環境だと、リセットは阻止できない。
if $@ and WFRGSS::DEBUG_CONSOLE and debug?
p "例外 Reset が外部へ投げられました。"
end