我找到了一个解决方案,可以完全避免使用 Cygwin 不可靠的命名管道实现。 Windows 有自己的命名管道工具,甚至还有一个名为win32管道 http://rubygems.org/gems/win32-pipe使用它的。
不幸的是,似乎无法在 RGSS 脚本中使用 Ruby Gems;但通过剖析 win32-pipe gem,我能够将相同的想法融入到 RGSS 游戏中。此代码是将游戏事件实时记录到后台通道所需的最低限度的代码,但它对于深度调试非常有用。
我在“Main”之前添加了一个新的脚本页面,并添加了以下内容:
module PipeLogger
# -- Change THIS to change the name of the pipe!
PIPE_NAME = "RGSSPipe"
# Constant Defines
PIPE_DEFAULT_MODE = 0 # Pipe operation mode
PIPE_ACCESS_DUPLEX = 0x00000003 # Pipe open mode
PIPE_UNLIMITED_INSTANCES = 255 # Number of concurrent instances
PIPE_BUFFER_SIZE = 1024 # Size of I/O buffer (1K)
PIPE_TIMEOUT = 5000 # Wait time for buffer (5 secs)
INVALID_HANDLE_VALUE = 0xFFFFFFFF # Retval for bad pipe handle
#-----------------------------------------------------------------------
# make_APIs
#-----------------------------------------------------------------------
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
#-----------------------------------------------------------------------
# setup_pipe
#-----------------------------------------------------------------------
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
# If we could not open the pipe, notify the user
# and proceed quietly
print "WARNING -- Unable to create named pipe: " + PIPE_NAME
@@pipe = nil
else
# Prompt the user to open the pipe
print "Please launch the RGSSMonitor.rb script"
end
end
#-----------------------------------------------------------------------
# write_to_pipe ('msg' must be a string)
#-----------------------------------------------------------------------
def self.write_to_pipe(msg)
if @@pipe
# Format data
@@buffer = msg
@@size = msg.size
$WriteFile.call(@@pipe, @@buffer, @@buffer.size, @@bytes, 0)
end
end
#------------------------------------------------------------------------
# close_pipe
#------------------------------------------------------------------------
def self.close_pipe
if @@pipe
# Send kill message to RGSSMonitor
@@buffer = "!!GAMEOVER!!"
@@size = @@buffer.size
$WriteFile.call(@@pipe, @@buffer, @@buffer.size, @@bytes, 0)
# Close down the pipe
$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
# -- Change THIS to change the name of the pipe!
PIPE_NAME = "RGSSPipe"
Thread.new { loop { sleep 0.01 } } # Allow Ctrl+C
pipe = Pipe::Client.new(PIPE_NAME)
continue = true
while continue
msg = pipe.read.to_s
puts msg
continue = false if msg.chomp == "!!GAMEOVER!!"
end
I use 适用于 Windows 的 Ruby 1.8.7 http://rubyinstaller.org/和win32-管道 gem http://rubygems.org/gems/win32-pipe上面提到过(参见here http://docs.rubygems.org/read/book/1有关安装 gem 的良好参考)。将以上内容保存为“RGSSMonitor.rb”并从命令行调用它ruby RGSSMonitor.rb
.
CAVEATS:
- 上面列出的 RGSS 代码很脆弱;特别是,它不处理打开命名管道的失败。在您自己的开发机器上,这通常不是问题,但我不建议发布此代码。
- 我还没有测试过它,但我怀疑如果您向日志写入很多内容而不运行读取管道的进程(例如
RGSSMonitor.rb
)。 Windows 命名管道具有固定大小(我在这里将其设置为 1K),默认情况下,一旦管道被填满,写入就会阻塞(因为没有进程通过读取来“缓解压力”)。不幸的是,RPGXP 引擎会杀死停止运行 10 秒的 Ruby 脚本。 (我听说 RPGVX 已经取消了这个看门狗功能——在这种情况下,游戏将挂起而不是突然终止。)