Commit f8d64192 authored by 神楽坂玲奈's avatar 神楽坂玲奈

linux fix

parent 5b522cc2
source http://rubygems.org source 'http://rubygems.org'
ruby '1.9.3' ruby '1.9.3'
gem 'rubysdl', :platform => :ruby gem 'rubysdl', :platform => :ruby
......
...@@ -11,6 +11,56 @@ module Association ...@@ -11,6 +11,56 @@ module Association
Win32::Registry::HKEY_CLASSES_ROOT.create('.ydk') { |reg| reg[nil] = 'mycard' } Win32::Registry::HKEY_CLASSES_ROOT.create('.ydk') { |reg| reg[nil] = 'mycard' }
Win32::Registry::HKEY_CLASSES_ROOT.create('.yrp') { |reg| reg[nil] = 'mycard' } Win32::Registry::HKEY_CLASSES_ROOT.create('.yrp') { |reg| reg[nil] = 'mycard' }
Win32::Registry::HKEY_CLASSES_ROOT.create('.deck') { |reg| reg[nil] = 'mycard' } Win32::Registry::HKEY_CLASSES_ROOT.create('.deck') { |reg| reg[nil] = 'mycard' }
else
require 'fileutils'
FileUtils.mkdir_p("#{ENV['HOME']}/.local/share/applications") unless File.directory?("#{ENV['HOME']}/.local/share/applications")
open("#{ENV['HOME']}/.local/share/applications/mycard.desktop", 'w') { |f| f.write <<EOF
#!/usr/bin/env xdg-open
[Desktop Entry]
Name=Mycard
Name[zh_CN]=Mycard - 萌卡
Comment=a card game platform
Comment[zh_CN]=卡片游戏对战客户端
Exec=/usr/bin/env ruby -KU lib/main.rb %u
Terminal=false
Icon=#{Dir.pwd}/graphics/system/icon.png
Type=Application
Categories=Game
Path=#{Dir.pwd}
URL=http://my-card.in/
MimeType=x-scheme-handler/mycard;application/x-ygopro-deck;application/x-ygopro-replay'
EOF
}
FileUtils.mkdir_p("#{ENV['HOME']}/.local/share/mime/packages") unless File.directory?("#{ENV['HOME']}/.local/share/mime/packages")
open("#{ENV['HOME']}/.local/share/mime/packages/application-x-ygopro-deck.xml", 'w') { |f| f.write <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-ygopro-deck">
<comment>ygopro deck</comment>
<icon name="application-x-ygopro-deck"/>
<glob-deleteall/>
<glob pattern="*.ydk"/>
</mime-type>
</mime-info>
EOF
}
open("#{ENV['HOME']}/.local/share/mime/packages/application-x-ygopro-replay.xml", 'w') { |f| f.write <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">
<mime-type type="application/x-ygopro-replay">
<comment>ygopro replay</comment>
<icon name="application-x-ygopro-replay"/>
<glob-deleteall/>
<glob pattern="*.yrp"/>
</mime-type>
</mime-info>
EOF
}
system("install -D #{Dir.pwd}/graphics/system/icon.png ~/.icons/application-x-ygopro-deck.png")
system("install -D #{Dir.pwd}/graphics/system/icon.png ~/.icons/application-x-ygopro-replay.png")
system("xdg-mime default mycard.desktop application/x-ygopro-deck application/x-ygopro-replay x-scheme-handler/mycard")
system("update-mime-database #{ENV['HOME']}/.local/share/mime")
system("update-desktop-database #{ENV['HOME']}/.local/share/applications")
end end
end end
...@@ -23,8 +73,8 @@ module Association ...@@ -23,8 +73,8 @@ module Association
end end
def need? def need?
return false unless Windows
return false if $config['no_assoc'] return false if $config['no_assoc']
if Windows
path, command, icon = paths path, command, icon = paths
require 'win32/registry' require 'win32/registry'
begin begin
...@@ -37,6 +87,9 @@ module Association ...@@ -37,6 +87,9 @@ module Association
rescue rescue
return true return true
end end
else
true #how to detect?
end
end end
def request def request
...@@ -51,11 +104,17 @@ module Association ...@@ -51,11 +104,17 @@ module Association
end end
end end
end end
def start def start
if need? if need?
if Windows
request do request do
register rescue Dialog.uac("ruby/bin/rubyw.exe", "-KU lib/main.rb register_association") register rescue Dialog.uac("ruby/bin/rubyw.exe", "-KU lib/main.rb register_association")
end end
else
register
end
end end
end end
end end
\ No newline at end of file
module Dialog module Dialog
module_function
if Windows
#选择文件对话框 #选择文件对话框
require 'win32api' require 'win32api'
GetOpenFileName = Win32API.new("comdlg32.dll", "GetOpenFileNameW", "p", "i") GetOpenFileName = Win32API.new("comdlg32.dll", "GetOpenFileNameW", "p", "i")
...@@ -12,10 +15,10 @@ module Dialog ...@@ -12,10 +15,10 @@ module Dialog
#打开网页 #打开网页
require 'win32ole' require 'win32ole'
Shell = WIN32OLE.new('Shell.Application') Shell = WIN32OLE.new('Shell.Application')
end
module_function
def get_open_file(title="选择文件", filter = {"所有文件 (*.*)" => "*.*"}, save=nil) def get_open_file(title="选择文件", filter = {"所有文件 (*.*)" => "*.*"}, save=nil)
if Windows
szFile = (0.chr * 20481).encode("UTF-16LE") szFile = (0.chr * 20481).encode("UTF-16LE")
szFileTitle = 0.chr * 2049 szFileTitle = 0.chr * 2049
szTitle = (title+"\0").encode("UTF-16LE") szTitle = (title+"\0").encode("UTF-16LE")
...@@ -62,13 +65,22 @@ module Dialog ...@@ -62,13 +65,22 @@ module Dialog
end end
end end
result result
else
[]
end
end end
def web(url) def web(url)
if Windows
Shell.ShellExecute url Shell.ShellExecute url
else
system('xdg-open ' + url)
end
end end
def uac(command, *args) def uac(command, *args)
if Windows
Shell.ShellExecute File.expand_path(command), args.join(' '), Dir.pwd, "runas" Shell.ShellExecute File.expand_path(command), args.join(' '), Dir.pwd, "runas"
end end
end
end end
This diff is collapsed.
class Game_Event
def self.parse(info)
info =~ /^\$([A-Z])\|(.*)$/m
case $1
when "A"
Error
when "B"
Login
when "C"
AllUsers
when "F"
Join
when "Q"
NewRoom
when "G"
Watch
when "H", "M"
Leave
when "J"
Action
when "K"
WatchAction
when 'N'
PrivateChat
when "O"
Chat
when "P"
AllRooms
when "R"
QROOMOK #卡表
else
Unknown
end.parse($2)
end
class Login
def self.parse(info)
info = info.split(",")
#>> $B|201629,zh99997,5da9e5fa,Level-1 (总经验:183),,20101118
info[3] =~ /Level-(\d)+ \(总经验:(\d+)\)/
result = self.new User.new(info[0].to_i, info[1], $1.to_i, $2.to_i)
$game.get_friends
$game.session = info[2]
$game.key = ($game.user.id - 0x186a0) ^ 0x22133
result
end
end
class AllUsers
def self.parse(info)
self.new info.split(',').collect{|user|User.parse(user)}
end
end
class AllRooms
def self.parse(info)
info = info.split("|")
rooms = []
templist = rooms
empty = false
info.each do |room|
if room == '~~'
empty = true
templist = []
else
room = room.split(",")
room = if empty
Room.new(room[0].to_i, room[1], User.parse(room[2]), nil, room[3]=="1", Room::Color[room[4].to_i], nil, room[6])
else
Room.new(room[0].to_i, room[3], User.parse(room[1]), User.parse(room[2]), false, Room::Color[room[5].to_i], room[3])
end
room.name = room.name[1,room.name.size-1] #iduel服务器发来的消息中,房名前有一空格
templist << room
end
end
rooms = templist + rooms
self.new rooms
end
end
class NewUser
def self.parse(info)
p info
#super
#@args = @args.collect do |user|
# User.new(user)
#end
end
end
class MissingUser
def self.parse(info)
p info
#super
#@args = @args.collect do |user|
# User.new(user)
#end
end
end
class Join
def self.parse(info)
self.new Room.new(info.to_i)
end
end
class Leave
def self.parse(info)
self.new
end
end
class NewRoom
def self.parse(info)
id, x, player1, player2 = info.split(",", 4)
room = Room.new(id.to_i)
room.player1 = User.parse(player1)
room.player2 = User.parse(player2)
room.name = room.name[1,room.name.size-1] #iduel服务器发来的消息中,房名前有一空格
self.new room
end
end
#"Q"
#"273,1,zh99998(201448),zh99997(201629)"
class Watch
def self.parse(info)
id, name = info.split(",", 2)
name = name[1,name.size-1] #iduel服务器发来的消息中,房名前有一空格
self.new Room.new(id.to_i, name)
end
end
class Action
def self.parse(info)
info =~ /(.*)▊▊▊.*?$/m
info = $1
info["◎"] = "●" if info["◎"]
self.new ::Action.parse(info), info
end
end
class Leave
end
class Chat
def self.parse(info)
user, content = info.split(",", 2)
user = user == "System" ? User.new(100000, "iDuel管理中心") : User.parse(user)
content.gsub!('@@@@', ',')
self.new(ChatMessage.new(user, content, :lobby))
end
end
class Error
def self.parse(info)
title, message,fatal = case info.to_i
when 0x00
["网络错误", "网络连接中断",true]
when 0x65
["出错啦~", "服务器程序出现未知错误,请记录好出现错误的事件,并联系管理员。",true]
when 0x66
["错误", "通信验证错误",true]
when 0x67
["错误", "通信钥匙错误",true]
when 0xc9
["登录失败", "错误的帐号名或密码",true]
when 0xca
["登录失败", "你的账号还未激活",true]
when 0xcb
["登录失败", "你的账号被系统封锁",true]
when 0x12d
["错误", "房间已满",false]
when 0x12e
["错误", "房间密码错误",false]
when 0x12f
["错误", "你没有权限给房间上密码",false]
when 0x130
["错误", "你已经加入房间,请不要重新加入",false]
when 0x131
["加入房间", "你未达到房间要求的等级限制。",false]
when 0x132
["观战错误", "所请求的房间无效,或未开始决斗",false]
when 0x133
["观战错误", "你已经在该房间观战",false]
when 0x134
["发送信息错误", "你还未加入房间",false]
when 0x135
["错误", "请求的房间无效",false]
end
self.new title, message, fatal
end
end
class Unknown
def self.parse(*args)
$log.info '--------Unknown iDuel Event-------'
p $1, $2, args
end
end
#以下iDuel专有
class WatchAction < Action
attr_reader :user
def initialize(action, str, user)
@user = user
super(action, str)
if $game.room.nil? #通常是由于断线重连引起的
Game_Event.push Watch.new(Room.new(0, @user, User.new(0,"")))
#$game.refresh
end
@action.from_player = @user == $game.room.player1
end
def self.parse(info)
info =~ /(.+)\((\d+)\), (.*)/m
self.new ::Action.parse($3), $3, User.new($2.to_i, $1)
end
end
class QROOMOK < Game_Event
def self.parse(info)
end
end
class PrivateChat < Chat
def self.parse(info)
user, content = info.split(",", 2)
user = User.parse(user)
content.gsub!('@@@@', ',')
self.new(ChatMessage.new(user, content, user))
end
end
end
\ No newline at end of file
#encoding: UTF-8
load 'lib/iduel/window_login.rb'
require 'open-uri'
class Iduel < Game
Version = "20110131"
Server = "iduel.ocgsoft.cn"
Register_Url = 'http://www.duelcn.com/member.php?mod=join_id'
Port = 38522
RS = "¢"
attr_accessor :session
attr_accessor :key
def initialize
super
require 'digest/md5'
load 'lib/iduel/action.rb'
load 'lib/iduel/event.rb'
load 'lib/iduel/user.rb'
load 'lib/iduel/replay.rb'
end
def rename
##8|241019,测试改昵称,5b58559aaf8869282fe3cb9585ffa909¢
#$N|iDuel系统,您的改名请求已经提交,重新登录后即可看到效果。¢
end
def login(username, password)
connect
md5 = Digest::MD5.hexdigest(password)
send(0, username, md5, checknum("LOGINMSG", username, md5), Version)
end
def refresh
send(1, @key, checknum("UPINFOMSG", @session))
end
def host(name, password="", lv=0, color = 0)
end
def host(room_name, room_config)
password = ""
color = 0
lv = 0
send(6, @key, room_name, password, checknum("JOINROOMMSG", @session + room_name + password + "0"), 0, color, lv, 0, 0, 0) #TODO:v.ak, v.al
end
def join(room, password="")
send(6, @key, room.id, password, checknum("JOINROOMMSG", @session + room.id.to_s + password + "1"),1)
end
def watch(room, password="")
send(5, @key, room.id, password, checknum("WATCHROOMMSG", "#{@session}#{room.id}#{password}"))
end
def leave
return unless @room
if @room.include? @user
send(10, @key, room.id, checknum("QROOM", @session + room.id.to_s))
else
send(9, @key, checknum("QUITWATCHROOM", @session))
end
end
def action(action)
send(2, "#{checknum("RMSG", @session)}@#{@key}", "#{action.escape}▊▊▊mycard") #消息校验字串,为了防止由于mycard开源造成外挂泛滥扰乱正常iduel秩序,这里不模仿iduel计算校验字串,直接发送mycard供iduel识别
end
def exit
@recv.exit if @recv
if @conn
leave
send(11, @key, checknum("ULO", "#{@session}"))
@conn.close
@conn = nil
end
super
end
def recv(info)
if info.nil?
@conn.close
@conn = nil
$log.error 'socket已中断'
Game_Event.push Game_Event::Error.parse(0)
else
info.chomp!(RS)
info.delete!("\r")
$log.info ">> #{info}"
Game_Event.push Game_Event.parse info
end
end
#def qroom(room)
# send(10, @key, room.id, checknum("QROOM", @session + room.id.to_s))
#end
def chat(chatmessage)
msg = chatmessage.message.gsub(",", "@@@@")
case chatmessage.channel
when :lobby
send(4, @key, msg, checknum("CHATP", @session))
when User #私聊
send(3, @key, "#{chatmessage.channel.name}(#{chatmessage.channel.id})", msg, checknum("CHATX", @session + "X" + "#{chatmessage.channel.name}(#{chatmessage.channel.id})"))
when Room #房间消息:向双方分别私聊
channel = chatmessage.channel
chatmessage.channel = channel.player1
chat chatmessage
if channel.player2
chatmessage.channel = channel.player2
chat chatmessage
end
chatmessage.channel = channel
end
#4|241019,test,2368c6b89b3e2eedb92e1b624a2a157c
end
def get_friends
$config['iDuel']['friends'] ||= []
$config['iDuel']['friends'].each {|id|User.new(id).friend = true}
Thread.new do
begin
open("http://www.duelcn.com/home.php?mod=space&uid=#{@user.id-100000}&do=friend&view=me&from=space") do |file|
$config['iDuel']['friends'].each {|id|User.new(id).friend = false}
$config['iDuel']['friends'].clear
file.set_encoding "GBK", "UTF-8"
file.read.scan(/<a href="home.php\?mod=space&amp;uid=(\d+)" title=".*" target="_blank">.*<\/a>/) do |uid, others|
id = uid.to_i + 100000
User.new(id).friend = true
$config['iDuel']['friends'] << id
end
Config.save
end
rescue Exception => exception
$log.error('读取好友信息') {[exception.inspect, *exception.backtrace].collect{|str|str.encode("UTF-8")}.join("\n")}
end
end
end
def show_chat_self
true
end
private
def connect
require 'socket'
begin
@conn = TCPSocket.new(Server, Port) #TODO: 阻塞优化,注意login。下面注释掉的两句实现connect无阻塞,但是login依然会阻塞所以只优化这里没有意义
#@conn = Socket.new(:INET, :STREAM)
@conn.set_encoding "GBK", "UTF-8", :invalid => :replace, :undef => :replace
Thread.abort_on_exception=true
@recv = Thread.new do
begin
#@conn.connect Socket.pack_sockaddr_in(Port, Server)
recv @conn.gets(RS) while @conn
rescue => exception
$log.error('iduel-connect-1') {[exception.inspect, *exception.backtrace].collect{|str|str.encode("UTF-8")}.join("\n")}
Game_Event.push Game_Event::Error.new(exception.class.to_s, exception.message)
ensure
self.exit
end
end
rescue => exception
$log.error('iduel-connect-2') {[exception.inspect, *exception.backtrace].collect{|str|str.encode("UTF-8")}.join("\n")}
Game_Event.push Game_Event::Error.new("网络错误", "连接服务器失败")
end
end
def checknum(head, *args)
Digest::MD5.hexdigest("[#{head}]_#{args.join('_')}_SCNERO".gsub("\n", "\r\n").encode("GBK"))
end
def send(head, *args)
return unless @conn
info = "##{head.to_s(16).upcase}|#{args.join(',')}" + RS
$log.info "<< #{info}"
info.gsub!("\n", "\r\n")
(@conn.write info) rescue Game_Event.push Game_Event::Error.new($!.class.to_s, $!.message)
end
def self.get_announcements
#公告
$config['iDuel']['announcements'] ||= [Announcement.new("正在读取公告...", nil, nil)]
Thread.new do
begin
open('http://www.duelcn.com/topic-Announce.html') do |file|
announcements = []
file.read.scan(/<li><a href="(.*?)" title="(.*?)" target="_blank">/).each do |url, title|
announcements << Announcement.new(title.encode("UTF-8"), "http://www.duelcn.com/#{url}", nil)
end
$config['iDuel']['announcements'].replace announcements
Config.save
end
rescue Exception => exception
$log.error('公告') {[exception.inspect, *exception.backtrace].collect{|str|str.encode("UTF-8")}.join("\n")}
end
end
end
get_announcements
end
name: iDuel
\ No newline at end of file
class Replay
User_Filter = /(.+?)(?:\((\d+)\))?(?:\(\d+:\d+:\d+\))?(?:: |:) */
Delimiter = /^#{User_Filter}\n ?/
Player_Filter = /#{Delimiter}\[\d+\] ◎→/
Opponent_Filter =/#{Delimiter}\[\d+\] ●→/
HTML_Player_Filter = /<font color=blue><strong>#{User_Filter}<\/strong>/
HTML_Opponent_Filter = /<font color=red><strong>#{User_Filter}<\/strong>/
attr_accessor :room, :player1, :player2, :actions
def add(action)
# user = action.from_player ? $game.player1 : $game.player2
# @file.write("#{user.name}(#{user.id}):\r\n#{action.escape}\r\n")
end
def self.load(filename)
#TODO:效率优化
file = open(filename)
file.set_encoding "GBK", "UTF-8", :invalid => :replace, :undef => :replace
result = self.new(file)
contents = file.read.strip
if contents['<td width="75%" valign="top">']
result.player1 = User.new($2.to_i, $1) if contents =~ HTML_Player_Filter
result.player2 = User.new($2.to_i, $1) if contents =~ HTML_Opponent_Filter
from_players = contents.scan(Regexp.union(HTML_Player_Filter, HTML_Opponent_Filter)).collect{|matched|matched[0] ? true : false} #匹配player成功matched前两位有值,opponent成功后两位有值,["尸体", "100015", nil, nil], il, nil], [nil, nil, "游戏的徒弟", "288436"]
#去除HTML标签
contents.gsub!(/<.*?>/,'')
#处理HTML转义字符
require 'cgi'
contents = CGI.unescape_html(contents)
else
result.player1 = User.new($2 ? $2.to_i : $1.to_sym, $1) if contents =~ Player_Filter
result.player2 = User.new($2 ? $2.to_i : $1.to_sym, $1) if contents =~ Opponent_Filter
from_players = contents.scan(Delimiter).collect do |matched|
id = (matched[1] || matched[0]).to_sym
name = matched[0]
if result.player1 and result.player1.id == id
true
elsif result.player2 and result.player2.id == id
false
elsif result.player1.nil?
result.player1 = User.new(id , name)
true
elsif result.player2.nil?
result.player2 = User.new(id, name)
false
else
#无法匹配玩家,一般是观战消息..
false
end
end
end
result.player1 ||= User.new($1.to_sym, "我")
result.player2 ||= User.new($1.to_sym, "对手")
lines = contents.split(Delimiter)
lines.shift #split后,在第一个操作之前会多出一个空白元素
if from_players.empty?
Game_Event.push Game_Event::Error.new("播放战报", "战报无法识别")
return []
end
lines = lines.each_slice(lines.size/from_players.size).collect{|a|a.last.strip}
from_players = from_players.to_enum
result.actions = lines.collect do |action_str|
action = Action.parse action_str
action.from_player = from_players.next
Game_Event::Action.new(action, action_str)
end
$game.room = result.room = Room.new(0, "Replay", result.player1, result.player2)
result
end
def self.html_decode(text)
text.gsub(Regexp.new(HTML_Replacement.keys.collect{|key|Regexp.escape key}.join('|')), HTML_Replacement)
end
def get
@actions.shift
end
def eof?
@actions.empty?
end
end
class User
attr_accessor :level, :exp
def self.parse(info)
if info =~ /(.+)\((\d+)\)/
new $2.to_i, $1
else
nil
end
end
def initialize(id, name = "", level = nil, exp = nil)
@id = id
@name = name
@level = level
@exp = exp
end
def set(id, name = :keep, level = :keep, exp = :keep)
@id = id unless id == :keep
@name = name unless name == :keep
@level = level unless level == :keep
@exp = exp unless exp == :keep
end
def avatar(size = :small)
cache = "graphics/avatars/#{@id}_#{size}.png"
result = Surface.load(cache) rescue Surface.load("graphics/avatars/loading_#{size}.png")
scene = $scene
if block_given?
yield result
Thread.new do
open("http://www.duelcn.com/uc_server/avatar.php?uid=#{id-100000}&size=#{size}", 'rb') {|io|open(cache, 'wb') {|c|c.write io.read}} rescue cache = "graphics/avatars/error_#{size}.png"
(yield Surface.load(cache) if scene == $scene) rescue nil
end
else
result
end
end
def status
room = room()
result = case
when room.nil?
:lobby
when room.player2
:dueling
else
:waiting
end
result
end
def room
$game.rooms.find{|room|room.include? self}
end
def space
Dialog.web "http://www.duelcn.com/home.php?mod=space&uid=#{@id-100000}"
end
def color
@friend ? [255,0,0] : [0,0,0]
end
end
class Window_Login
def clicked
return if @last_clicked and Time.now - @last_clicked < 3 #防止重复点击
case @index
when :login
Widget_Msgbox.new("iDuel", "正在登录")
$scene.draw #强制重绘一次,下面会阻塞
$game = Iduel.new
$config[$config['game']]['username'] = @username_inputbox.value
$config[$config['game']]['password'] = @remember_password.checked? ? @password_inputbox.value : nil
Config.save
$game.login(@username_inputbox.value, @password_inputbox.value)
@last_clicked = Time.now
when :register
Dialog.web Iduel::Register_Url
@last_clicked = Time.now
when :replay
file = Dialog.get_open_file("播放录像", "所有支持的录像 (*.txt;*.htm)" => "*.txt;*.htm", "iDuel的html的录像 (*.htm)" => "*.htm", "文本录像 (*.txt)" => "*.txt")
if !file.empty?
$game = Iduel.new
$game.user = User.new(0)
Widget_Msgbox.new("回放录像", "录像读取中...")
$scene.draw
$log.info('iduel window_login'){'loading reply file'}
$scene = Scene_Replay.new Replay.load file
end
@last_clicked = Time.now
end
end
end
\ No newline at end of file
#输入法by夏娜 #输入法by夏娜
require 'dl'
require 'dl/import'
module RM_IME module RM_IME
if Windows
require 'dl'
require 'dl/import'
extend DL::Importer extend DL::Importer
Dir.chdir('ruby/bin'){dlload 'RMIME.dll'} Dir.chdir('ruby/bin') { dlload 'RMIME.dll' }
extern 'void _init(long, int, int)' extern 'void _init(long, int, int)'
extern 'void _update(int, int)' extern 'void _update(int, int)'
extern 'void _dispose()' extern 'void _dispose()'
...@@ -32,6 +35,7 @@ module RM_IME ...@@ -32,6 +35,7 @@ module RM_IME
def press?(rkey) def press?(rkey)
return GetAsyncKeyState(rkey) != 0 return GetAsyncKeyState(rkey) != 0
end end
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# ● 重复按下判断 # ● 重复按下判断
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -54,6 +58,7 @@ module RM_IME ...@@ -54,6 +58,7 @@ module RM_IME
return false return false
end end
end end
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# ● 击键判断 # ● 击键判断
#---------------------------------------------------------------------- #----------------------------------------------------------------------
...@@ -72,66 +77,89 @@ module RM_IME ...@@ -72,66 +77,89 @@ module RM_IME
end end
end end
HWND = RM_INPUT.FindWindow('SDL_app', WM.caption[0]) HWND = RM_INPUT.FindWindow('SDL_app', WM.caption[0])
end
module_function module_function
def init def init
return unless Windows
return if @active return if @active
$log.info('输入法'){'开启'} $log.info('输入法') { '开启' }
_init(HWND, 0, 0) _init(HWND, 0, 0)
@x = 0 @x = 0
@y = 0 @y = 0
@active = true @active = true
end end
def set(x,y)
def set(x, y)
return unless Windows
@x = x @x = x
@y = y @y = y
end end
def text def text
return "" unless Windows
buf = 0.chr * 1024 buf = 0.chr * 1024
_get_text(buf) _get_text(buf)
buf.force_encoding("UTF-8") buf.force_encoding("UTF-8")
buf.delete!("\0") buf.delete!("\0")
end end
def update def update
_update(@x,@y) return unless Windows
buf = [0,0].pack("LL") _update(@x, @y)
buf = [0, 0].pack("LL")
_back(buf) _back(buf)
buf = buf.unpack("LL") buf = buf.unpack("LL")
@backspace = buf[0] == 1 @backspace = buf[0] == 1
@delete = buf[1] == 1 @delete = buf[1] == 1
end end
def dispose def dispose
return unless Windows
return if !@active return if !@active
$log.info('输入法'){'关闭'} $log.info('输入法') { '关闭' }
_dispose _dispose
@active = false @active = false
end end
def active? def active?
@active @active
end end
def backspace? def backspace?
@backspace @backspace
end end
def delete? def delete?
@delete @delete
end end
def left? def left?
return unless Windows
RM_INPUT.repeat?(RM_INPUT::LEFT) RM_INPUT.repeat?(RM_INPUT::LEFT)
end end
def right? def right?
return unless Windows
RM_INPUT.repeat?(RM_INPUT::RIGHT) RM_INPUT.repeat?(RM_INPUT::RIGHT)
end end
def tab? def tab?
return unless Windows
RM_INPUT.trigger?(RM_INPUT::TAB) RM_INPUT.trigger?(RM_INPUT::TAB)
end end
def enter? def enter?
return unless Windows
RM_INPUT.trigger?(RM_INPUT::ENTER) RM_INPUT.trigger?(RM_INPUT::ENTER)
end end
def esc? def esc?
return unless Windows
RM_INPUT.trigger?(RM_INPUT::ESC) RM_INPUT.trigger?(RM_INPUT::ESC)
end end
end end
class Widget_InputBox < Window class Widget_InputBox < Window
attr_accessor :type attr_accessor :type
attr_reader :value attr_reader :value
...@@ -139,8 +167,9 @@ class Widget_InputBox < Window ...@@ -139,8 +167,9 @@ class Widget_InputBox < Window
@@active = nil @@active = nil
@@cursor = nil @@cursor = nil
@@focus = true @@focus = true
def initialize(x,y,width,height,z=300, &proc)
super(x,y,width,height,z) def initialize(x, y, width, height, z=300, &proc)
super(x, y, width, height, z)
@font = TTF.open("fonts/wqy-microhei.ttc", 20) @font = TTF.open("fonts/wqy-microhei.ttc", 20)
@proc = proc @proc = proc
@value = "" @value = ""
...@@ -149,6 +178,7 @@ class Widget_InputBox < Window ...@@ -149,6 +178,7 @@ class Widget_InputBox < Window
@count = 0 @count = 0
@char_pos = [2] @char_pos = [2]
end end
def value=(value) def value=(value)
return if @value == value return if @value == value
@value = value @value = value
...@@ -161,6 +191,7 @@ class Widget_InputBox < Window ...@@ -161,6 +191,7 @@ class Widget_InputBox < Window
end end
refresh refresh
end end
def index=(index) def index=(index)
if index > @value.size if index > @value.size
index = @value.size index = @value.size
...@@ -174,17 +205,19 @@ class Widget_InputBox < Window ...@@ -174,17 +205,19 @@ class Widget_InputBox < Window
@@cursor.x = @x + @char_pos[@index] @@cursor.x = @x + @char_pos[@index]
RM_IME.set(@@cursor.x, @@cursor.y) RM_IME.set(@@cursor.x, @@cursor.y)
end end
def refresh def refresh
clear clear
@font.draw_blended_utf8(@contents, @type == :password ? '*' * @value.size : @value, 2, 0, 0x00, 0x00, 0x00) unless @value.empty? @font.draw_blended_utf8(@contents, @type == :password ? '*' * @value.size : @value, 2, 0, 0x00, 0x00, 0x00) unless @value.empty?
end end
def clicked def clicked
RM_IME.init RM_IME.init
@@active = self @@active = self
@@focus = true @@focus = true
unless @@cursor and !@@cursor.destroyed? unless @@cursor and !@@cursor.destroyed?
@@cursor = Window.new(0,0,2,@height-4,301) @@cursor = Window.new(0, 0, 2, @height-4, 301)
@@cursor.contents.fill_rect(0,0,@@cursor.width,@@cursor.height,0xFF000000) @@cursor.contents.fill_rect(0, 0, @@cursor.width, @@cursor.height, 0xFF000000)
end end
@@cursor.y = @y + 2 @@cursor.y = @y + 2
mouse_x = Mouse.state[0] - @x mouse_x = Mouse.state[0] - @x
...@@ -202,10 +235,12 @@ class Widget_InputBox < Window ...@@ -202,10 +235,12 @@ class Widget_InputBox < Window
end end
end end
def clear(x=0, y=0, width=@width, height=@height) def clear(x=0, y=0, width=@width, height=@height)
@contents.fill_rect(x,y,width,height,0x110000FF) @contents.fill_rect(x, y, width, height, 0x110000FF)
@contents.fill_rect(x+2,y+2,width-4,height-4,0xFFFFFFFF) @contents.fill_rect(x+2, y+2, width-4, height-4, 0xFFFFFFFF)
end end
def update def update
return unless self == @@active and @@focus return unless self == @@active and @@focus
if @count >= 40 if @count >= 40
...@@ -214,7 +249,6 @@ class Widget_InputBox < Window ...@@ -214,7 +249,6 @@ class Widget_InputBox < Window
else else
@count += 1 @count += 1
end end
RM_IME.update RM_IME.update
new_value = self.value.dup new_value = self.value.dup
new_index = self.index new_index = self.index
...@@ -250,12 +284,14 @@ class Widget_InputBox < Window ...@@ -250,12 +284,14 @@ class Widget_InputBox < Window
end end
end end
end end
def destroy def destroy
if @@active == self if @@active == self
Widget_InputBox.focus = false Widget_InputBox.focus = false
end end
super super
end end
def self.focus=(focus) def self.focus=(focus)
@@focus = focus @@focus = focus
if !@@focus if !@@focus
......
...@@ -11,7 +11,7 @@ class Widget_ScrollBar < Window ...@@ -11,7 +11,7 @@ class Widget_ScrollBar < Window
@scroll ||= 0 @scroll ||= 0
@scroll_max ||= 0 @scroll_max ||= 0
@scrolling = nil @scrolling = nil
Surface.transform_draw(@back,@contents,0,1,@contents.h.to_f/@back.h,0,0,0,0,0) Surface.transform_draw(@back,@contents,0,1,@contents.h.to_f/@back.h,0,0,0,0,0) rescue nil
refresh refresh
end end
def index=(index) def index=(index)
......
require_relative 'window_host' require_relative 'window_host'
class Window_LobbyButtons < Window_List class Window_LobbyButtons < Window_List
def initialize(x, y) def initialize(x, y)
@items = [I18n.t('lobby.faq'), I18n.t('lobby.filter'), I18n.t('lobby.editdeck'), I18n.t('lobby.newroom'), "自动匹配"] @items = [I18n.t('lobby.faq'), I18n.t('lobby.filter'), I18n.t('lobby.editdeck'), I18n.t('lobby.newroom'), I18n.t('lobby.match')]
@button = Surface.load("graphics/lobby/button.png") @button = Surface.load("graphics/lobby/button.png")
super(x, y, @items.size*@button.w/3+@items.size*4, 30) super(x, y, @items.size*@button.w/3+@items.size*4, 30)
@font = TTF.open("fonts/wqy-microhei.ttc", 15) @font = TTF.open("fonts/wqy-microhei.ttc", 15)
......
...@@ -87,7 +87,7 @@ class Ygocore < Game ...@@ -87,7 +87,7 @@ class Ygocore < Game
http = EM::HttpRequest.new("http://my-card.in/servers.json").get http = EM::HttpRequest.new("http://my-card.in/servers.json").get
http.callback { http.callback {
begin begin
self.servers.replace JSON.parse(http.response).collect {|data| Server.new(data['id'], data['name'], data['ip'], data['port'], data['auth'])} self.servers.replace JSON.parse(http.response).collect { |data| Server.new(data['id'], data['name'], data['ip'], data['port'], data['auth']) }
self.filter[:servers] = self.servers.clone self.filter[:servers] = self.servers.clone
rescue rescue
Game_Event.push Game_Event::Error.new('ygocore', '读取服务器列表失败.1', true) Game_Event.push Game_Event::Error.new('ygocore', '读取服务器列表失败.1', true)
...@@ -96,7 +96,7 @@ class Ygocore < Game ...@@ -96,7 +96,7 @@ class Ygocore < Game
#EventMachine::connect "mycard-server.my-card.in", 9997, Client #EventMachine::connect "mycard-server.my-card.in", 9997, Client
ws = WebSocket::EventMachine::Client.connect(:host => "mycard-server.my-card.in", :port => 9998); ws = WebSocket::EventMachine::Client.connect(:host => "mycard-server.my-card.in", :port => 9998);
ws.onmessage do |msg, type| ws.onmessage do |msg, type|
$log.info('收到websocket消息'){msg.force_encoding("UTF-8")} $log.info('收到websocket消息') { msg.force_encoding("UTF-8") }
Game_Event.push Game_Event::RoomsUpdate.new JSON.parse(msg).collect { |room| Game_Event.parse_room(room) } Game_Event.push Game_Event::RoomsUpdate.new JSON.parse(msg).collect { |room| Game_Event.parse_room(room) }
end end
ws.onclose do ws.onclose do
...@@ -105,7 +105,7 @@ class Ygocore < Game ...@@ -105,7 +105,7 @@ class Ygocore < Game
end end
} }
http.errback{ http.errback {
Game_Event.push Game_Event::Error.new('ygocore', '读取服务器列表失败', true) Game_Event.push Game_Event::Error.new('ygocore', '读取服务器列表失败', true)
} }
} }
...@@ -120,8 +120,12 @@ class Ygocore < Game ...@@ -120,8 +120,12 @@ class Ygocore < Game
connected = false connected = false
if @@im.jid.domain == "my-card.in" if @@im.jid.domain == "my-card.in"
@@im.connect("ygopro-server.my-card.in", 5223) rescue Game_Event.push Game_Event::Error.new('登录', '连接服务器失败') begin
@@im.connect("ygopro-server.my-card.in", 5223)
connected = true connected = true
rescue
Game_Event.push Game_Event::Error.new('登录', '连接服务器失败')
end
else else
srv = [] srv = []
Resolv::DNS.open { |dns| Resolv::DNS.open { |dns|
...@@ -131,10 +135,9 @@ class Ygocore < Game ...@@ -131,10 +135,9 @@ class Ygocore < Game
if srv.empty? if srv.empty?
Game_Event.push Game_Event::Error.new('登录', '解析服务器地址失败') Game_Event.push Game_Event::Error.new('登录', '解析服务器地址失败')
Thread.exit
end end
# Sort SRV records: lowest priority first, highest weight first # Sort SRV records: lowest priority first, highest weight first
srv.sort! { |a,b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) } srv.sort! { |a, b| (a.priority != b.priority) ? (a.priority <=> b.priority) : (b.weight <=> a.weight) }
srv.each { |record| srv.each { |record|
begin begin
...@@ -150,6 +153,7 @@ class Ygocore < Game ...@@ -150,6 +153,7 @@ class Ygocore < Game
if connected if connected
begin begin
@@im.fd.define_singleton_method(:external_encoding) { |*args| @@im.fd.io.external_encoding(*args) }
@@im.auth(@password) @@im.auth(@password)
rescue Jabber::ClientAuthenticationFailure rescue Jabber::ClientAuthenticationFailure
Game_Event.push Game_Event::Error.new('登录', '用户名或密码错误') Game_Event.push Game_Event::Error.new('登录', '用户名或密码错误')
...@@ -168,9 +172,6 @@ class Ygocore < Game ...@@ -168,9 +172,6 @@ class Ygocore < Game
end end
end end
Game_Event.push Game_Event::AllUsers.new @@im_room.roster.keys.collect { |nick| User.new(nick.to_sym, nick) } rescue p $! Game_Event.push Game_Event::AllUsers.new @@im_room.roster.keys.collect { |nick| User.new(nick.to_sym, nick) } rescue p $!
else
$log.error('聊天连接出错.1') { exception }
Game_Event.push Game_Event::Error.new('登录', '连接服务器失败.1')
end end
rescue StandardError => exception rescue StandardError => exception
$log.error('聊天连接出错') { exception } $log.error('聊天连接出错') { exception }
...@@ -190,6 +191,7 @@ class Ygocore < Game ...@@ -190,6 +191,7 @@ class Ygocore < Game
#send(:chat, channel: chatmessage.channel.id, message: chatmessage.message, time: chatmessage.time) #send(:chat, channel: chatmessage.channel.id, message: chatmessage.message, time: chatmessage.time)
end end
end end
#def chat(chatmessage) #def chat(chatmessage)
# case chatmessage.channel # case chatmessage.channel
# when :lobby # when :lobby
...@@ -239,8 +241,8 @@ class Ygocore < Game ...@@ -239,8 +241,8 @@ class Ygocore < Game
@recv = nil @recv = nil
end end
def ygocore_path def self.ygocore_path
"ygocore/ygopro_vs.exe" Windows ? 'ygocore/ygopro_vs.exe' : 'ygocore/gframe'
end end
def self.register def self.register
...@@ -267,10 +269,9 @@ class Ygocore < Game ...@@ -267,10 +269,9 @@ class Ygocore < Game
if !image_downloading and !Update.images.empty? if !image_downloading and !Update.images.empty?
return Widget_Msgbox.new("加入房间", "卡图正在下载中,可能显示不出部分卡图", :ok => "确定") { run_ygocore(option, true) } return Widget_Msgbox.new("加入房间", "卡图正在下载中,可能显示不出部分卡图", :ok => "确定") { run_ygocore(option, true) }
end end
path = 'ygocore/ygopro_vs.exe'
Widget_Msgbox.new("ygocore", "正在启动ygocore") rescue nil Widget_Msgbox.new("ygocore", "正在启动ygocore") rescue nil
#写入配置文件并运行ygocore #写入配置文件并运行ygocore
Dir.chdir(File.dirname(path)) do Dir.chdir(File.dirname(ygocore_path)) do
case option case option
when Room when Room
room = option room = option
...@@ -305,14 +306,18 @@ class Ygocore < Game ...@@ -305,14 +306,18 @@ class Ygocore < Game
system_conf[field] = contents system_conf[field] = contents
end end
rescue rescue
system_conf['antialias'] = 2
system_conf['textfont'] = 'c:/windows/fonts/simsun.ttc 14'
system_conf['numfont'] = 'c:/windows/fonts/arialbd.ttf'
end end
if $game.user if $game.user
system_conf['nickname'] = $game.user.name system_conf['nickname'] = $game.user.name
system_conf['nickname'] += '$' + $game.password if $game.password and !$game.password.empty? and room.server.auth system_conf['nickname'] += '$' + $game.password if $game.password and !$game.password.empty? and room.server.auth
end end
font, size = system_conf['textfont'].split(' ')
if !File.file?(font) or size.to_i.to_s != size
system_conf['textfont'] = '../fonts/wqy_microhei.ttc 14'
end
if !File.file?(system_conf['numfont'])
system_conf['textfont'] = Windows ? '../fonts/wqy_microhei.ttc 14' : '/usr/share/fonts/gnu-free/FreeSansBold.ttf'
end
system_conf['lastip'] = room.server.ip system_conf['lastip'] = room.server.ip
system_conf['lastport'] = room.server.port.to_s system_conf['lastport'] = room.server.port.to_s
system_conf['roompass'] = room_name if room_name and !room_name.empty? system_conf['roompass'] = room_name if room_name and !room_name.empty?
...@@ -340,7 +345,7 @@ class Ygocore < Game ...@@ -340,7 +345,7 @@ class Ygocore < Game
open('system.conf', 'w') { |file| file.write system_conf.collect { |key, value| "#{key} = #{value}" }.join("\n") } open('system.conf', 'w') { |file| file.write system_conf.collect { |key, value| "#{key} = #{value}" }.join("\n") }
args = '-d' args = '-d'
end end
IO.popen("ygopro_vs.exe #{args}") IO.popen("./#{File.basename(ygocore_path)} #{args}")
WM.iconify rescue nil WM.iconify rescue nil
end end
Widget_Msgbox.destroy rescue nil Widget_Msgbox.destroy rescue nil
...@@ -368,7 +373,7 @@ class Ygocore < Game ...@@ -368,7 +373,7 @@ class Ygocore < Game
Config.save Config.save
end end
rescue Exception => exception rescue Exception => exception
$log.error('公告读取失败') { [exception.inspect, *exception.backtrace].collect { |str| str.force_encoding("UTF-8") }.join("\n") } $log.error('公告读取失败') { [exception.inspect, *exception.backtrace].collect { |str| str.encode("UTF-8") }.join("\n") }
end end
end end
end end
......
...@@ -12,7 +12,9 @@ en: ...@@ -12,7 +12,9 @@ en:
replay: "Replay" replay: "Replay"
lobby: lobby:
faq: "FAQ" faq: "FAQ"
filter: "Filter"
editdeck: "Edit Deck" editdeck: "Edit Deck"
newroom: "NewRoom" newroom: "NewRoom"
match: "QuickMatch"
lobby: "Lobby" lobby: "Lobby"
en: zh:
lang: "中文" lang: "中文"
chat: chat:
room: "lobby.zh" room: "lobby.zh"
...@@ -16,6 +16,7 @@ en: ...@@ -16,6 +16,7 @@ en:
newroom: "建立房间" newroom: "建立房间"
lobby: "大厅" lobby: "大厅"
filter: "房间筛选" filter: "房间筛选"
match: "自动匹配"
waiting_only: "仅等待中" waiting_only: "仅等待中"
normal_only: "仅标准房" normal_only: "仅标准房"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment