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

0.8.4

parent 03bca965
...@@ -20,7 +20,7 @@ end ...@@ -20,7 +20,7 @@ end
spec = Gem::Specification.new do |s| spec = Gem::Specification.new do |s|
s.name = 'mycard' s.name = 'mycard'
s.version = '0.8.2' s.version = '0.8.4'
s.extra_rdoc_files = ['README.txt', 'LICENSE.txt'] s.extra_rdoc_files = ['README.txt', 'LICENSE.txt']
s.summary = 'a card game' s.summary = 'a card game'
s.description = s.summary s.description = s.summary
......
...@@ -9,4 +9,7 @@ module Cacheable ...@@ -9,4 +9,7 @@ module Cacheable
@@all[self][id] = super(id, *args) @@all[self][id] = super(id, *args)
end end
end end
def find(id)
@@all[self][id]
end
end end
\ No newline at end of file
...@@ -66,8 +66,8 @@ class Scene_Lobby < Scene ...@@ -66,8 +66,8 @@ class Scene_Lobby < Scene
when Game_Event::AllUsers when Game_Event::AllUsers
@userlist.items = $game.users @userlist.items = $game.users
when Game_Event::AllRooms, Game_Event::AllServers when Game_Event::AllRooms, Game_Event::AllServers
@roomlist.items = $game.rooms.find_all { |room| @roomlist.items = p $game.rooms.find_all { |room|
$game.filter[:servers].collect { |server| server.id }.include?(room.server_id) and $game.filter[:servers].include?(room.server) and
$game.filter[:waiting_only] ? (room.status == :wait) : true and $game.filter[:waiting_only] ? (room.status == :wait) : true and
$game.filter[:normal_only] ? (!room.tag? && (room.ot == 0) && (room.lp = 8000)) : true $game.filter[:normal_only] ? (!room.tag? && (room.ot == 0) && (room.lp = 8000)) : true
} }
......
...@@ -2,7 +2,7 @@ require 'open-uri' ...@@ -2,7 +2,7 @@ require 'open-uri'
require "fileutils" require "fileutils"
require_relative 'card' require_relative 'card'
module Update module Update
Version = '0.8.2' Version = '0.8.4'
URL = "http://my-card.in/mycard/update.json?version=#{Version}" URL = "http://my-card.in/mycard/update.json?version=#{Version}"
class <<self class <<self
attr_reader :thumbnails, :images, :status attr_reader :thumbnails, :images, :status
......
...@@ -11,6 +11,7 @@ class Window_Filter < Window ...@@ -11,6 +11,7 @@ class Window_Filter < Window
@servers = $game.servers.each_with_index.collect do |server, index| @servers = $game.servers.each_with_index.collect do |server, index|
result = Widget_Checkbox.new(self, 4+@x,@y+WLH+WLH*index,@width-8,24,true,server.name){|checked|checked ? $game.filter[:servers].push(server) : $game.filter[:servers].delete(server) ; Game_Event.push(Game_Event::AllRooms.new($game.rooms))} result = Widget_Checkbox.new(self, 4+@x,@y+WLH+WLH*index,@width-8,24,true,server.name){|checked|checked ? $game.filter[:servers].push(server) : $game.filter[:servers].delete(server) ; Game_Event.push(Game_Event::AllRooms.new($game.rooms))}
result.background = @background.copy_rect(4,WLH+WLH*index,@width-8,24) result.background = @background.copy_rect(4,WLH+WLH*index,@width-8,24)
result.checked = $game.filter[:servers].include? server
result.refresh result.refresh
result result
end end
......
...@@ -7,22 +7,22 @@ class Game_Event ...@@ -7,22 +7,22 @@ class Game_Event
else else
Error.new('登录', '用户名或密码错误') Error.new('登录', '用户名或密码错误')
end end
when :rooms #when :rooms
AllRooms.new data.collect{|room|parse_room(room)} #AllRooms.new data.collect{|room|parse_room(room)}
when :rooms_update #when :rooms_update
RoomsUpdate.new data.collect{|room|parse_room(room)} #RoomsUpdate.new data.collect{|room|parse_room(room)}
when :servers #when :servers
servers = data.collect{|server|parse_server(server)} # servers = data.collect{|server|parse_server(server)}
$game.filter[:servers].concat (servers - $game.servers) # $game.filter[:servers].concat (servers - $game.servers)
AllServers.new servers # AllServers.new servers
#when :newuser #when :newuser
#NewUser.new parse_user data #NewUser.new parse_user data
#when :missinguser #when :missinguser
#MissingUser.new parse_user data #MissingUser.new parse_user data
when :newroom #when :newroom
NewRoom.new parse_room data # NewRoom.new parse_room data
when :missingroom #when :missingroom
MissingRoom.new parse_room data # MissingRoom.new parse_room data
when :chat when :chat
case data[:channel] case data[:channel]
when :lobby when :lobby
...@@ -33,25 +33,25 @@ class Game_Event ...@@ -33,25 +33,25 @@ class Game_Event
end end
end end
def self.parse_room(room) def self.parse_room(room)
result = Room.new(room[:id], room[:name]) result = Room.new(room['id'], room['name'])
result.player1 = room[:player1] && parse_user(room[:player1]) result.private = room['private']
result.player2 = room[:player2] && parse_user(room[:player2]) result.pvp = room['pvp']
result.private = room[:private] result.match = room['mode'] == 1
result.pvp = room[:pvp] result.tag = room['mode'] == 2
result.match = room[:match] result.ot = room['rule'] || 0
result.tag = room[:tag] result.status = room['status'].to_sym
result.ot = room[:ot] result.lp = room['start_lp'] || 8000
result.status = room[:status]
result.lp = room[:lp] result.player1 = room['users'][0] && parse_user(room['users'][0])
result._deleted = room[:_deleted] result.player2 = room['users'][1] && parse_user(room['users'][1])
result.server_id = room[:server_id]
result.server_ip = room[:server_ip] result.server = Server.find room['server_id']
result.server_port = room[:server_port]
result.server_auth = room[:server_auth] result._deleted = room['_deleted']
result result
end end
def self.parse_user(user) def self.parse_user(user)
User.new(user[:id], user[:name], user[:certified]) User.new(user['id'] || user[:id], user['name'] || user[:name], user['certified'] || user[:certified])
end end
def self.parse_server(server) def self.parse_server(server)
Server.new(server[:id], server[:name], server[:ip], server[:port], server[:auth]) Server.new(server[:id], server[:name], server[:ip], server[:port], server[:auth])
......
#encoding: UTF-8 #encoding: UTF-8
load 'lib/ygocore/window_login.rb' load 'lib/ygocore/window_login.rb'
require 'eventmachine' require 'eventmachine'
require 'em-http'
require 'websocket'
require 'open-uri' require 'open-uri'
require 'yaml' require 'yaml'
class Ygocore < Game class Ygocore < Game
...@@ -77,7 +79,30 @@ class Ygocore < Game ...@@ -77,7 +79,30 @@ class Ygocore < Game
def connect def connect
@recv = Thread.new do @recv = Thread.new do
EventMachine::run { EventMachine::run {
http = EM::HttpRequest.new("http://my-card.in/servers.json").get
http.callback {
begin
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
rescue
Game_Event.push Game_Event::Error.new('ygocore', '读取服务器列表失败', true)
end
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.onmessage do |msg, type|
$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) }
end
ws.onclose do
$log.info('websocket连接断开')
Game_Event.push Game_Event::Error.new('ygocore', '网络连接中断.1', true)
end
}
http.errback{
Game_Event.push Game_Event::Error.new('ygocore', '读取服务器列表失败', true)
}
} }
end end
end end
...@@ -137,10 +162,9 @@ class Ygocore < Game ...@@ -137,10 +162,9 @@ class Ygocore < Game
room.password = room_config[:password] room.password = room_config[:password]
room.ot = room_config[:ot] room.ot = room_config[:ot]
room.lp = room_config[:lp] room.lp = room_config[:lp]
server = @filter[:servers].sample || Server.new(nil, "", $game.server, $game.port, true)
room.server_ip = server.ip room.host_server
room.server_port = server.port
room.server_auth = server.auth
if $game.rooms.any? { |game_room| game_room.name == room_name } if $game.rooms.any? { |game_room| game_room.name == room_name }
Widget_Msgbox.new("建立房间", "房间名已存在", :ok => "确定") Widget_Msgbox.new("建立房间", "房间名已存在", :ok => "确定")
else else
...@@ -157,7 +181,7 @@ class Ygocore < Game ...@@ -157,7 +181,7 @@ class Ygocore < Game
end end
def refresh def refresh
send(:refresh) #send(:refresh)
end end
def send(header, data=nil) def send(header, data=nil)
...@@ -241,10 +265,10 @@ class Ygocore < Game ...@@ -241,10 +265,10 @@ class Ygocore < Game
system_conf['numfont'] = 'c:/windows/fonts/arialbd.ttf' system_conf['numfont'] = 'c:/windows/fonts/arialbd.ttf'
end end
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
p room $log.info room
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 system_conf['roompass'] = room_name
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 = '-j' args = '-j'
...@@ -326,3 +350,265 @@ class Ygocore < Game ...@@ -326,3 +350,265 @@ class Ygocore < Game
end end
get_announcements get_announcements
end end
# websocket, due to the author hasn't release separate gem yet
#https://github.com/imanel/websocket-ruby/issues/12
module WebSocket
module EventMachine
class Base < ::EventMachine::Connection
###########
### API ###
###########
def onopen(&blk)
; @onopen = blk;
end
# Called when connection is opened
def onclose(&blk)
; @onclose = blk;
end
# Called when connection is closed
def onerror(&blk)
; @onerror = blk;
end
# Called when error occurs
def onmessage(&blk)
; @onmessage = blk;
end
# Called when message is received from server
def onping(&blk)
; @onping = blk;
end
# Called when ping message is received from server
def onpong(&blk)
; @onpong = blk;
end
# Called when pond message is received from server
# Send data to client
# @param data [String] Data to send
# @param args [Hash] Arguments for send
# @option args [String] :type Type of frame to send - available types are "text", "binary", "ping", "pong" and "close"
# @return [Boolean] true if data was send, otherwise call on_error if needed
def send(data, args = {})
type = args[:type] || :text
unless type == :plain
frame = outgoing_frame.new(:version => @handshake.version, :data => data, :type => type)
if !frame.supported?
trigger_onerror("Frame type '#{type}' is not supported in protocol version #{@handshake.version}")
return false
elsif !frame.require_sending?
return false
end
data = frame.to_s
end
# debug "Sending raw: ", data
send_data(data)
true
end
# Close connection
# @return [Boolean] true if connection is closed immediately, false if waiting for server to close connection
def close
if @state == :open
@state = :closing
return false if send('', :type => :close)
else
send('', :type => :close) if @state == :closing
@state = :closed
end
close_connection_after_writing
true
end
# Send ping message to client
# @return [Boolean] false if protocol version is not supporting ping requests
def ping(data = '')
send(data, :type => :ping)
end
# Send pong message to client
# @return [Boolean] false if protocol version is not supporting pong requests
def pong(data = '')
send(data, :type => :pong)
end
############################
### EventMachine methods ###
############################
def receive_data(data)
# debug "Received raw: ", data
case @state
when :connecting then
handle_connecting(data)
when :open then
handle_open(data)
when :closing then
handle_closing(data)
end
end
def unbind
unless @state == :closed
@state = :closed
close
trigger_onclose('')
end
end
#######################
### Private methods ###
#######################
private
['onopen'].each do |m|
define_method "trigger_#{m}" do
callback = instance_variable_get("@#{m}")
callback.call if callback
end
end
['onerror', 'onping', 'onpong', 'onclose'].each do |m|
define_method "trigger_#{m}" do |data|
callback = instance_variable_get("@#{m}")
callback.call(data) if callback
end
end
def trigger_onmessage(data, type)
@onmessage.call(data, type) if @onmessage
end
def handle_connecting(data)
@handshake << data
return unless @handshake.finished?
if @handshake.valid?
send(@handshake.to_s, :type => :plain) if @handshake.should_respond?
@frame = incoming_frame.new(:version => @handshake.version)
@state = :open
trigger_onopen
handle_open(@handshake.leftovers) if @handshake.leftovers
else
trigger_onerror(@handshake.error)
close
end
end
def handle_open(data)
@frame << data
while frame = @frame.next
case frame.type
when :close
@state = :closing
close
trigger_onclose(frame.to_s)
when :ping
pong(frame.to_s)
trigger_onping(frame.to_s)
when :pong
trigger_onpong(frame.to_s)
when :text
trigger_onmessage(frame.to_s, :text)
when :binary
trigger_onmessage(frame.to_s, :binary)
end
end
unbind if @frame.error?
end
def handle_closing(data)
@state = :closed
close
trigger_onclose
end
def debug(description, data)
puts(description + data.bytes.to_a.collect { |b| '\x' + b.to_s(16).rjust(2, '0') }.join) unless @state == :connecting
end
end
end
end
# Example WebSocket Client (using EventMachine)
# @example
# ws = WebSocket::EventMachine::Client.connect(:host => "0.0.0.0", :port => 8080)
# ws.onmessage { |msg| ws.send "Pong: #{msg}" }
# ws.send "data"
module WebSocket
module EventMachine
class Client < Base
# Connect to websocket server
# @param args [Hash] The request arguments
# @option args [String] :host The host IP/DNS name
# @option args [Integer] :port The port to connect too(default = 80)
# @option args [Integer] :version Version of protocol to use(default = 13)
def self.connect(args = {})
host = nil
port = nil
if args[:uri]
uri = URI.parse(args[:uri])
host = uri.host
port = uri.port
end
host = args[:host] if args[:host]
port = args[:port] if args[:port]
port ||= 80
::EventMachine.connect host, port, self, args
end
# Initialize connection
# @param args [Hash] Arguments for connection
# @option args [String] :host The host IP/DNS name
# @option args [Integer] :port The port to connect too(default = 80)
# @option args [Integer] :version Version of protocol to use(default = 13)
def initialize(args)
@args = args
end
############################
### EventMachine methods ###
############################
# Called after initialize of connection, but before connecting to server
def post_init
@state = :connecting
@handshake = WebSocket::Handshake::Client.new(@args)
end
# Called by EventMachine after connecting.
# Sends handshake to server
def connection_completed
send(@handshake.to_s, :type => :plain)
end
private
def incoming_frame
WebSocket::Frame::Incoming::Client
end
def outgoing_frame
WebSocket::Frame::Outgoing::Client
end
end
end
end
...@@ -5,7 +5,7 @@ class Room ...@@ -5,7 +5,7 @@ class Room
attr_accessor :ot attr_accessor :ot
attr_accessor :lp attr_accessor :lp
attr_accessor :status attr_accessor :status
attr_accessor :server_id, :server_ip, :server_port, :server_auth attr_accessor :server
alias pvp? pvp alias pvp? pvp
alias match? match alias match? match
alias tag? tag alias tag? tag
...@@ -38,4 +38,19 @@ class Room ...@@ -38,4 +38,19 @@ class Room
end end
result result
end end
def host_server
servers = $game.servers
servers.select!{|server|server.auth} if @pvp
s = servers & $game.filter[:servers]
servers = s if !s.empty?
server = servers.min_by{|server|$game.rooms.select{|room|room.server == server}.size}
p server
server ||= Server.new(nil, "", $game.server, $game.port, true)
self.server = server
server
end
end end
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