我找到了一个解决方案,完全避免使用Cygwin不可靠的命名管道实现。Windows有自己的命名管道设施,甚至有一个名为
win32-pipe的Ruby Gem使用它。
不幸的是,在RGSS脚本中似乎没有使用Ruby Gems的方法。但是通过分解win32-pipe gem,我能够将相同的想法合并到RGSS游戏中。这段代码是实时记录游戏事件到后端通道所需的最少量,但对于深度调试非常有用。
我在“Main”之前添加了一个新的脚本页面,并添加了以下内容:
module PipeLogger
PIPE_NAME = "RGSSPipe"
PIPE_DEFAULT_MODE = 0
PIPE_ACCESS_DUPLEX = 0x00000003
PIPE_UNLIMITED_INSTANCES = 255
PIPE_BUFFER_SIZE = 1024
PIPE_TIMEOUT = 5000
INVALID_HANDLE_VALUE = 0xFFFFFFFF
def self.make_APIs
$CreateNamedPipe = Win32API.new('kernel32', 'CreateNamedPipe', 'PLLLLLLL', 'L')
$FlushFileBuffers = Win32API.new('kernel32', 'FlushFileBuffers', 'L', 'B')
$DisconnectNamedPipe = Win32API.new('kernel32', 'DisconnectNamedPipe', 'L', 'B')
$WriteFile = Win32API.new('kernel32', 'WriteFile', 'LPLPP', 'B')
$CloseHandle = Win32API.new('kernel32', 'CloseHandle', 'L', 'B')
end
def self.setup_pipe
make_APIs
@@name = "\\\\.\\pipe\\" + PIPE_NAME
@@pipe_mode = PIPE_DEFAULT_MODE
@@open_mode = PIPE_ACCESS_DUPLEX
@@pipe = nil
@@buffer = 0.chr * PIPE_BUFFER_SIZE
@@size = 0
@@bytes = [0].pack('L')
@@pipe = $CreateNamedPipe.call(
@@name,
@@open_mode,
@@pipe_mode,
PIPE_UNLIMITED_INSTANCES,
PIPE_BUFFER_SIZE,
PIPE_BUFFER_SIZE,
PIPE_TIMEOUT,
0
)
if @@pipe == INVALID_HANDLE_VALUE
print "WARNING -- Unable to create named pipe: " + PIPE_NAME
@@pipe = nil
else
print "Please launch the RGSSMonitor.rb script"
end
end
def self.write_to_pipe(msg)
if @@pipe
@@buffer = msg
@@size = msg.size
$WriteFile.call(@@pipe, @@buffer, @@buffer.size, @@bytes, 0)
end
end
def self.close_pipe
if @@pipe
@@buffer = "!!GAMEOVER!!"
@@size = @@buffer.size
$WriteFile.call(@@pipe, @@buffer, @@buffer.size, @@bytes, 0)
$FlushFileBuffers.call(@@pipe)
$DisconnectNamedPipe.call(@@pipe)
$CloseHandle.call(@@pipe)
@@pipe = nil
end
end
end
要使用此功能,您只需要确保在编写事件之前调用
PipeLogger :: setup_pipe ,并在游戏退出之前调用PipeLogger :: close_pipe 。(我将设置调用放在“Main”开头,并添加了一个 ensure 子句以调用 close_pipe 。)之后,您可以在任何脚本的任何点上添加对 PipeLogger :: write_to_pipe(“msg”)的调用,并使用任何字符串为“msg”写入管道。
我已经使用RPG Maker XP测试了此代码;它也应该适用于RPG Maker VX及更高版本。
您还需要一些内容来从管道中读取。 有许多方法可以做到这一点,但简单的方法是使用标准的Ruby安装程序,win32-pipe Ruby Gem和此脚本:
require 'rubygems'
require 'win32/pipe'
include Win32
PIPE_NAME = "RGSSPipe"
Thread.new { loop { sleep 0.01 } }
pipe = Pipe::Client.new(PIPE_NAME)
continue = true
while continue
msg = pipe.read.to_s
puts msg
continue = false if msg.chomp == "!!GAMEOVER!!"
end
我使用Windows版Ruby 1.8.7和上述提到的win32-pipe gem(安装gem的好参考请见这里)。将上述内容保存为“RGSSMonitor.rb”,并在命令行中调用ruby RGSSMonitor.rb
。
注意事项:
- 上面列出的RGSS代码很脆弱;特别是,它不能处理无法打开命名管道的情况。这在你自己的开发机器上通常不是问题,但我不建议使用此代码进行发布。
- 我没有测试过,但我怀疑如果您在没有运行读取管道的进程(例如
RGSSMonitor.rb
)的情况下向日志中写入大量内容,您将会遇到问题。Windows命名管道具有固定大小(我在此处设置为1K),默认情况下,一旦管道被填满,写入操作将会阻塞(因为没有进程通过读取来“释放压力”)。不幸的是,RPGXP引擎将会杀死一个已经停止运行10秒钟的Ruby脚本。(我听说RPGVX已经消除了这个看门狗功能--在这种情况下,游戏将挂起而不是突然终止。)