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

nothing

parent c1f6f124
/nbproject/
/.idea/
/ruby/
/pkg/
/config.yml
/log.log
/profile.log
/replay/
/mycard/
/mycard.exe
/7z.exe
/ygocore/
/graphics/avatars/*_*.png
/error-程序出错请到论坛反馈.txt
/nbproject/
/.idea/
/ruby/
/pkg/
/config.yml
/log.log
/profile.log
/replay/
/mycard/
/mycard.exe
/7z.exe
/ygocore/
/graphics/avatars/*_*.png
/error-程序出错请到论坛反馈.txt
Thumbs.db
\ No newline at end of file
#encoding: UTF-8
require 'rubygems'
require 'rake'
require 'rake/clean'
require 'rubygems/package_task'
require 'rdoc/task'
#require 'rake/testtask'
Windows = RUBY_PLATFORM["mingw"] || RUBY_PLATFORM["mswin"]
#在windows上UTF-8脚本编码环境中 Dir.glob无法列出中文目录下的文件 所以自己写个递归
def list(path)
result = []
Dir.foreach(path) do |file|
next if file == "." or file == ".."
result << "#{path}/#{file}"
result.concat list(result.last) if File.directory? result.last
end
result
end
spec = Gem::Specification.new do |s|
s.name = 'mycard'
s.version = '0.7.4'
s.extra_rdoc_files = ['README.txt', 'LICENSE.txt']
s.summary = 'a card game'
s.description = s.summary
s.author = 'zh99998'
s.email = 'zh99998@gmail.com'
s.homepage = 'http://card.touhou,cc'
# s.executables = ['your_executable_here']
s.files = %w(LICENSE.txt README.txt replay)
%w{lib audio data fonts graphics ygocore}.each{|dir|s.files.concat list(dir)}
if Windows
s.files += %w(mycard.exe) + list("ruby")
else
s.files += %w(install.sh)
end
s.require_path = "lib"
#s.bindir = "bin"
end
Gem::PackageTask.new(spec) do |p|
p.gem_spec = spec
if Windows
p.need_zip = true
p.zip_command = '../7z.exe a'
def p.zip_file
"#{package_name}-win32.7z"
end
else
p.need_tar = true
end
end
Rake::RDocTask.new do |rdoc|
files =['README.txt', 'LICENSE.txt', 'lib/**/*.rb']
rdoc.rdoc_files.add(files)
rdoc.main = "README.txt" # page to start on
rdoc.title = "Mycard Docs"
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
rdoc.options << '--line-numbers'
end
CLOBBER.include %w(error-程序出错请到论坛反馈.txt log.log profile.log config.yml doc ygocore/pics) + list('replay') + list('ygocore/replay') + list('.').keep_if{|file|File.basename(file) == "Thumbs.db"} + list("graphics/avatars").keep_if{|file|File.basename(file) =~ /.*_(?:small|middle|large)\.png/} + list("ygocore/deck").keep_if{|file|File.basename(file) != 'sample.ydk'}
#encoding: UTF-8
require 'rubygems'
require 'rake'
require 'rake/clean'
require 'rubygems/package_task'
require 'rdoc/task'
#require 'rake/testtask'
Windows = RUBY_PLATFORM["mingw"] || RUBY_PLATFORM["mswin"]
#在windows上UTF-8脚本编码环境中 Dir.glob无法列出中文目录下的文件 所以自己写个递归
def list(path)
result = []
Dir.foreach(path) do |file|
next if file == "." or file == ".."
result << "#{path}/#{file}"
result.concat list(result.last) if File.directory? result.last
end
result
end
spec = Gem::Specification.new do |s|
s.name = 'mycard'
s.version = '0.7.4'
s.extra_rdoc_files = ['README.txt', 'LICENSE.txt']
s.summary = 'a card game'
s.description = s.summary
s.author = 'zh99998'
s.email = 'zh99998@gmail.com'
s.homepage = 'http://card.touhou,cc'
# s.executables = ['your_executable_here']
s.files = %w(LICENSE.txt README.txt replay)
%w{lib audio data fonts graphics ygocore}.each{|dir|s.files.concat list(dir)}
if Windows
s.files += %w(mycard.exe) + list("ruby")
else
s.files += %w(install.sh)
end
s.require_path = "lib"
#s.bindir = "bin"
end
Gem::PackageTask.new(spec) do |p|
p.gem_spec = spec
if Windows
p.need_zip = true
p.zip_command = '../7z.exe a'
def p.zip_file
"#{package_name}-win32.7z"
end
else
p.need_tar = true
end
end
Rake::RDocTask.new do |rdoc|
files =['README.txt', 'LICENSE.txt', 'lib/**/*.rb']
rdoc.rdoc_files.add(files)
rdoc.main = "README.txt" # page to start on
rdoc.title = "Mycard Docs"
rdoc.rdoc_dir = 'doc/rdoc' # rdoc output folder
rdoc.options << '--line-numbers'
end
CLOBBER.include %w(error-程序出错请到论坛反馈.txt log.log profile.log config.yml doc ygocore/pics) + list('replay') + list('ygocore/replay') + list('.').keep_if{|file|File.basename(file) == "Thumbs.db"} + list("graphics/avatars").keep_if{|file|File.basename(file) =~ /.*_(?:small|middle|large)\.png/} + list("ygocore/deck").keep_if{|file|File.basename(file) != 'sample.ydk'}
---
name: "沙沙"
field:
cardimage:
- 1
- 2
- 3
- 4
cardtext:
- 5
- 6
- 7
- 8
chat:
- 9
- 10
- 11
- 12
---
name: "沙沙"
field:
cardimage:
- 1
- 2
- 3
- 4
cardtext:
- 5
- 6
- 7
- 8
chat:
- 9
- 10
- 11
- 12
#encoding: UTF-8
class Action
attr_accessor :from_player, :msg
attr_accessor :id
def initialize(from_player=true, msg=nil)
@id = @@id
@from_player = from_player
@msg = msg
@@id += 1 if @from_player
end
def player_field
@from_player ? $game.player_field : $game.opponent_field
end
def opponent_field
@from_player ? $game.opponent_field : $game.player_field
end
def run
#子类定义
end
class Reset < Action
def run
player_field.reset
super
end
end
class Deck < Action; end
class Side < Deck; end
class Go < Reset
def run
super
player_field.hand = player_field.deck.pop(5)
end
end
class FirstToGo < Go; end
class SecondToGo < Go; end
class Chat < Action; end
class Shuffle < Action
def run
player_field.deck.shuffle!
super
end
end
class Coin < Action
attr_reader :result
def initialize(from_player, result=rand(1)==0, msg=nil)
super(from_player, msg)
@result = result
end
end
class Dice < Action
attr_reader :result
def initialize(from_player, result=rand(6)+1, msg=nil)
super(from_player, msg)
@result = result
end
end
class ChangePhase < Action
attr_reader :phase
def initialize(from_player, phase)
super(from_player)
@phase = phase
end
def run
$game.phase = phase
super
end
end
class Move < Action
attr_reader :from_pos, :to_pos, :card, :position
def initialize(from_player, from_pos, to_pos=nil, card=nil, msg=nil, position=nil)
super(from_player, msg)
@from_pos = from_pos
@to_pos = to_pos
@card = card
@position = position
end
def parse_field(pos)
case pos
when 0..10, :field
player_field.field
when 11..70, :hand, :handtop, :handrandom
player_field.hand
when 71..130,:deck, :decktop, :deckbottom
player_field.deck
when :graveyard
player_field.graveyard
when :extra
player_field.extra
when :removed
player_field.removed
end
end
def run
$log.info('移动操作执行'){self.inspect}
from_field = parse_field(@from_pos)
from_pos = case @from_pos
when 0..10
@from_pos
when 11..70
@from_pos - 11
when 71..130
@from_pos - 71
when :handtop
player_field.hand.size - 1
when :decktop
player_field.deck.size - 1
when nil
nil
else
(@card.is_a?(Game_Card) ? from_field.index(@card) : from_field.index{|card|card.card == @card}) || from_field.index{|card|!card.known?}
end
to_field = parse_field(@to_pos)
card = if from_pos
case @card
when Game_Card
@card
when Card
if from_field[from_pos]
from_field[from_pos].card = @card
else
$log.warn('移动操作1'){'似乎凭空产生了卡片' + self.inspect}
from_field[from_pos] = Game_Card.new(@card)
end
from_field[from_pos]
else
from_field[from_pos] || Game_Card.new
end
else #没有来源
$log.warn('移动操作2'){'似乎凭空产生了卡片' + self.inspect}
Game_Card.new(@card)
end
if @position
if @position == :"face-up"
if card.position != :attack and (6..10).include?(@to_pos || @from_pos) #里侧表示的怪兽
card.position = :defense
else
card.position = :attack
end
else
card.position = @position
end
end
if @to_pos
if from_pos
if from_field == player_field.field
from_field[from_pos] = nil
else
from_field.delete_at from_pos
end
end
case @to_pos
when 0..10
to_field[@to_pos] = card
when :hand, :deck, :decktop, :extra, :graveyard, :removed
to_field.push card
when :deckbottom
to_field.unshift card
else
$log.error('移动操作3'){'错误的to_pos' + self.inspect}
end
end
if from_field == player_field.hand and !@card || !@card.known?
case @to_pos
when 0..5
player_field.hand.each{|card|card.card = Card::Unknown if card.known? and !card.monster?}
when 6..10
player_field.hand.each{|card|card.card = Card::Unknown if card.known? and card.monster?}
else
player_field.hand.each{|card|card.card = Card::Unknown if card.known?}
end
end
super
end
end
class Set < Move
def initialize(from_player, from_pos, to_pos, card)
super(from_player, from_pos, to_pos, card, nil, :set)
end
end
class Activate < Move
def initialize(from_player, from_pos, to_pos, card)
super(from_player, from_pos, to_pos, card, nil, :attack)
end
end
class Summon < Move
def initialize(from_player, from_pos, to_pos, card, msg=nil)
super(from_player, from_pos, to_pos, card, msg, :attack)
end
end
class SpecialSummon < Move
def initialize(from_player, from_pos, to_pos, card, msg=nil, position=:attack)
super(from_player, from_pos, to_pos, card, msg, position)
end
end
class SendToGraveyard < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :graveyard, card, nil, :attack)
end
end
class Remove < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :removed, card, nil, :attack)
end
end
class ReturnToHand < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :hand, card, nil, :set)
end
end
class ReturnToDeck < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :deck, card, nil, :set)
end
end
class ReturnToDeckBottom < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :deckbottom, card, nil, :set)
end
end
class ReturnToExtra < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :extra, card, nil, :set)
end
end
class Control < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, nil, card)
end
def run
to_pos = opponent_field.field[6..10].index(nil)+6
unless to_pos
$log.warn('转移控制权'){'没有空余场位'}
return
end
card = if @card.is_a? Game_Card
@card
elsif player_field.field[from_pos]
card = player_field.field[from_pos]
card.card = @card
card
else
$log.warn('转移控制权'){'似乎凭空产生了卡片'+self.inspect}
Game_Card.new(@card)
end
player_field.field[from_pos] = nil
opponent_field.field[to_pos] = card
end
end
class SendToOpponentGraveyard < SendToGraveyard
def run
card = if @card.is_a? Game_Card
@card
elsif player_field.field[from_pos]
card = player_field.field[from_pos]
card.card = @card
card
else
Game_Card.new(@card)
end
player_field.field[from_pos] = nil
opponent_field.graveyard.unshift card
end
end
class Tribute < SendToGraveyard; end
class Discard < SendToGraveyard; end
class ChangePosition < Move
def initialize(from_player, from_pos, card, position)
super(from_player, from_pos, from_pos, card, nil, position)
end
end
class Flip < ChangePosition
def initialize(from_player, from_pos, card, position=:defense)
super(from_player, from_pos, card, position)
end
end
class FlipSummon < Flip
def initialize(from_player, from_pos, card)
super(from_player, from_pos, card, :attack)
end
end
class Draw < Move
def initialize(from_player=true, msg=nil)
@from_player = from_player
super(from_player, :decktop, :hand, nil, msg, :set)
end
end
class Counter < Action
end
class MultiDraw < Action
def initialize(from_player, count, msg=nil)
super(from_player, msg)
@count = count
end
def run
super
player_field.hand.concat player_field.deck.pop(@count)
end
end
class MultiMove < Action
def initialize(from_player, from_pos, to_pos, cards=nil)
super(from_player)
@from_pos = from_pos
@to_pos = to_pos
@cards = cards
end
def run
from_field = case @from_pos
when :hand
player_field.hand
when :graveyard
player_field.graveyard
when :spellsandtraps
player_field.field[0..5]
when :monsters
player_field.field[6..10]
end
@cards = if @cards
@cards.collect do |card|
index = from_field.index{|fieldcard|fieldcard and fieldcard.card == card} || from_field.index{|fieldcard|fieldcard and !fieldcard.known?}
if index
fieldcard = from_field[index]
from_field[index] = nil
fieldcard.card = card
fieldcard
else
$log.warn '似乎凭空产生了卡片'
Game_Card.new(@card)
end
end
else
from_field.compact
end
to_field, position = case @to_pos
when :hand
[player_field.hand, :set]
when :graveyard
[player_field.graveyard, :attack]
when :deck
[player_field.deck, :set]
when :removed
[player_field.removed, :attack]
end
#执行部分
case @from_pos
when :hand
player_field.hand.clear
when :graveyard
player_field.graveyard.clear
when :spellsandtraps
player_field.field[0..5] = Array.new(6, nil)
when :monsters
player_field.field[6..10] = Array.new(5, nil)
end
if to_field == player_field.hand or to_field == player_field.deck
@cards.each{|card|card.position = position; to_field.push card}
else
@cards.each{|card|card.position = position; to_field.unshift card}
end
super
end
end
=begin #似乎不需要细分
class MonstersSendToGraveyard < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :graveyard, cards)
end
end
class MonstersRemove < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :remove, cards)
end
end
class MonstersReturnToDeck < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :deck, cards)
end
end
class MonstersReturnToHand < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :hand, cards)
end
end
class SpellsAndTrapsSendToGraveyard < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :graveyard, cards)
end
end
class SpellsAndTrapsRemove < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :remove, cards)
end
end
class SpellsAndTrapsReturnToDeck < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :deck, cards)
end
end
class SpellsAndTrapsReturnToHand < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :hand, cards)
end
end
class HandSendToGraveyard < MultiMove
def initialize(from_player, cards)
super(from_player, :hand, :graveyard, cards)
end
end
class HandRemove < MultiMove
def initialize(from_player, cards)
super(from_player, :hand, :remove, cards)
end
end
class HandReturnToDeck < MultiMove
def initialize(from_player, cards)
super(from_player, :hand, :deck, cards)
end
end
=end
class RefreshField < Action
attr_reader :field
def initialize(from_player, field, msg=nil)
super(from_player, msg)
@field = field
end
def run
super
return if @field.is_a? Game_Field #本地信息,无需处理。
player_field.lp = @field[:lp]
if player_field.hand.size > @field[:hand]
player_field.hand.pop(player_field.hand.size-@field[:hand])
elsif player_field.hand.size < @field[:hand]
(@field[:hand]-player_field.hand.size).times{$log.warn('刷新场地-手卡'){'似乎凭空产生了卡片'};player_field.hand.push Game_Card.new(Card::Unknown)}
end
if player_field.deck.size > @field[:deck]
player_field.deck.pop(player_field.deck.size-@field[:deck])
elsif player_field.deck.size < @field[:deck]
(@field[:deck]-player_field.deck.size).times{$log.warn('刷新场地-卡组'){'似乎凭空产生了卡片'};player_field.deck.push Game_Card.new(Card::Unknown)}
end
if player_field.graveyard.size > @field[:graveyard]
player_field.graveyard.pop(player_field.graveyard.size-@field[:graveyard])
elsif player_field.graveyard.size < @field[:graveyard]
(@field[:graveyard]-player_field.graveyard.size).times{$log.warn('刷新场地-墓地'){'似乎凭空产生了卡片'};player_field.graveyard.push Game_Card.new(Card::Unknown)}
end
(0..10).each do |pos|
if @field[pos]
if player_field.field[pos]
player_field.field[pos].card = @field[pos][:card]
else
$log.warn("刷新场地-#{pos}"){'似乎凭空产生了卡片'}
player_field.field[pos] = Game_Card.new(@field[pos][:card])
end
player_field.field[pos].position = @field[pos][:position]
else
player_field.field[pos] = nil
end
end
end
end
class TurnEnd < RefreshField
attr_reader :turn
def initialize(from_player, field, turn, msg=nil)
super(from_player, field, msg)
@turn = turn
end
def run
$game.phase = :DP
$game.turn = @turn.next
$game.turn_player = !from_player
super
end
end
class Show < Move
attr_reader :from_pos, :card
def initialize(from_player, from_pos, card)
super(from_player, from_pos, nil, card)
@from_pos = from_pos
@card = card
end
end
class MultiShow < Action
def initialize(from_player, from_pos=nil, cards)
super(from_player, nil)
@from_pos = from_pos
@cards = cards
end
def run
return if @cards[0].is_a? Game_Card #本地消息,不处理
case @from_pos
when :hand
if player_field.hand.size > @cards.size
player_field.hand.pop(player_field.hand.size-@cards.size)
end
@cards.each_with_index do |card, index|
if player_field.hand[index]
player_field.hand[index].card = card
else
player_field.hand[index] = Game_Card.new card
end
end
when 71..130
cards = @cards.to_enum
player_field.deck[@from_pos-71, @cards.size].each do |game_card|
game_card.card = cards.next
end
end
end
end
class EffectActivate < Move
def initialize(from_player, from_pos, card)
if (0..10).include?(from_pos)
position = :"face-up"
else
position = nil
end
super(from_player, from_pos, to_pos, card, nil, position)
end
end
class ActivateAsk < Action
def initialize(from_player)
super(from_player)
end
end
class ActivateAnswer < Action
def initialize(from_player, activate)
super(from_player)
@activate = activate
end
end
class Target < Action
def initialize(from_player, from_pos, card, target_player ,target_pos, target_card)
super(from_player)
@from_pos = from_pos
@card = card
@target_pos = target_player
@target_pos = target_pos
@target_card = target_card
end
def run
card = if @card.is_a? Game_Card
@card
else
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
player_field.field[@from_pos]
else
$log.warn('攻击宣言'){'似乎凭空产生了卡片' + self.inspect}
player_field[@from_pos] = Game_Card.new(@card)
end
end
$log.info('攻击宣言'){self.inspect}
end
end
class ViewDeck < Action; end
class LP < Action
attr_accessor :operator, :value
def initialize(from_player, operator, value)
super(from_player)
@operator = operator
@value = value
end
def run
case operator
when :lose
player_field.lp -= @value
when :increase
player_field.lp += @value
when :become
player_field.lp = @value
end
end
end
class Attack < Action
def initialize(from_player, from_pos, to_pos=nil, card)
super(from_player)
@from_pos = from_pos
@to_pos = to_pos
@card = card
end
def run
card = if @card.is_a? Game_Card
@card
elsif @from_pos
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
else
$log.warn('攻击宣言'){'似乎凭空产生了卡片' + self.inspect}
player_field.field[@from_pos] = Game_Card.new(@card)
player_field.field[@from_pos].position = :attack
end
player_field.field[@from_pos]
else
$log.info('直接攻击'){'功能未实现'}
@card
end
end
end
class Counter < Action
def initialize(from_player, from_pos, card, operator, value)
super(from_player)
@from_pos = from_pos
@card = card
@operator = operator
@value = value
end
def run
card = if @card.is_a? Game_Card
@card
else
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
else
$log.warn('指示物操作'){'似乎凭空产生了卡片' + self.inspect}
player_field.field[@from_pos] = Game_Card.new(@card)
player_field.field[@from_pos].position = :attack
end
player_field.field[@from_pos]
end
case @operator
when :become
card.counters = @value
else
$log.warn('指示物操作'){'become以外的未实现' + self.inspect}
end
end
end
class Note < Action
def initialize(from_player, from_pos, card, note)
super(from_player)
@from_pos = from_pos
@card = card
@note = note
end
def run
card = if @card.is_a? Game_Card
@card
else
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
else
$log.warn('指示物操作'){'似乎凭空产生了卡片' + self.inspect}
player_field.field[@from_pos] = Game_Card.new(@card)
player_field.field[@from_pos].position = :attack
end
player_field.field[@from_pos]
end
card.note = @note
end
end
class Token < SpecialSummon
def initialize(from_player, to_pos, card, position=:defense)
super(from_player, nil, to_pos, card)
end
end
class MultiToken < SpecialSummon
def initialize(from_player, num, card, position=:attack)
super(from_player, nil, nil, card)
@num = num
end
def run
@num.times do
@to_pos = player_field.field[6..10].index(nil)+6
super
end
end
end
class Add < Action
def initialize(from_player, card)
super(from_player)
@card = card
end
def run
if @card.extra?
player_field.extra << Game_Card.new(@card)
else
player_field.hand << Game_Card.new(@card)
end
end
end
class Destroy < Action
def initialize(from_player, from_pos, card)
super(from_player)
@from_pos = from_pos
@card = card
end
def run
if @from_pos <= 10
player_field.field[@from_pos] = nil
else
player_field.hand.delete_at(@from_pos - 11)
end
end
end
class CardInfo < Action
def initialize(card, card_type, atk, _def, attribute, type, level, lore)
return unless card.diy?
card.card_type = card_type
#card.monster_type = monster_type
card.atk = atk
card.def = _def
card.attribute = attribute
card.type = type
card.level = level
card.lore = lore
end
end
class Unknown < Action
def initialize(str)
@str = str
$log.warn('unkonwn action') { str }
end
def run
$log.warn('unkonwn action run'){ @str }
end
end
def self.reset
@@id=1
end
reset
#encoding: UTF-8
class Action
attr_accessor :from_player, :msg
attr_accessor :id
def initialize(from_player=true, msg=nil)
@id = @@id
@from_player = from_player
@msg = msg
@@id += 1 if @from_player
end
def player_field
@from_player ? $game.player_field : $game.opponent_field
end
def opponent_field
@from_player ? $game.opponent_field : $game.player_field
end
def run
#子类定义
end
class Reset < Action
def run
player_field.reset
super
end
end
class Deck < Action; end
class Side < Deck; end
class Go < Reset
def run
super
player_field.hand = player_field.deck.pop(5)
end
end
class FirstToGo < Go; end
class SecondToGo < Go; end
class Chat < Action; end
class Shuffle < Action
def run
player_field.deck.shuffle!
super
end
end
class Coin < Action
attr_reader :result
def initialize(from_player, result=rand(1)==0, msg=nil)
super(from_player, msg)
@result = result
end
end
class Dice < Action
attr_reader :result
def initialize(from_player, result=rand(6)+1, msg=nil)
super(from_player, msg)
@result = result
end
end
class ChangePhase < Action
attr_reader :phase
def initialize(from_player, phase)
super(from_player)
@phase = phase
end
def run
$game.phase = phase
super
end
end
class Move < Action
attr_reader :from_pos, :to_pos, :card, :position
def initialize(from_player, from_pos, to_pos=nil, card=nil, msg=nil, position=nil)
super(from_player, msg)
@from_pos = from_pos
@to_pos = to_pos
@card = card
@position = position
end
def parse_field(pos)
case pos
when 0..10, :field
player_field.field
when 11..70, :hand, :handtop, :handrandom
player_field.hand
when 71..130,:deck, :decktop, :deckbottom
player_field.deck
when :graveyard
player_field.graveyard
when :extra
player_field.extra
when :removed
player_field.removed
end
end
def run
$log.info('移动操作执行'){self.inspect}
from_field = parse_field(@from_pos)
from_pos = case @from_pos
when 0..10
@from_pos
when 11..70
@from_pos - 11
when 71..130
@from_pos - 71
when :handtop
player_field.hand.size - 1
when :decktop
player_field.deck.size - 1
when nil
nil
else
(@card.is_a?(Game_Card) ? from_field.index(@card) : from_field.index{|card|card.card == @card}) || from_field.index{|card|!card.known?}
end
to_field = parse_field(@to_pos)
card = if from_pos
case @card
when Game_Card
@card
when Card
if from_field[from_pos]
from_field[from_pos].card = @card
else
$log.warn('移动操作1'){'似乎凭空产生了卡片' + self.inspect}
from_field[from_pos] = Game_Card.new(@card)
end
from_field[from_pos]
else
from_field[from_pos] || Game_Card.new
end
else #没有来源
$log.warn('移动操作2'){'似乎凭空产生了卡片' + self.inspect}
Game_Card.new(@card)
end
if @position
if @position == :"face-up"
if card.position != :attack and (6..10).include?(@to_pos || @from_pos) #里侧表示的怪兽
card.position = :defense
else
card.position = :attack
end
else
card.position = @position
end
end
if @to_pos
if from_pos
if from_field == player_field.field
from_field[from_pos] = nil
else
from_field.delete_at from_pos
end
end
case @to_pos
when 0..10
to_field[@to_pos] = card
when :hand, :deck, :decktop, :extra, :graveyard, :removed
to_field.push card
when :deckbottom
to_field.unshift card
else
$log.error('移动操作3'){'错误的to_pos' + self.inspect}
end
end
if from_field == player_field.hand and !@card || !@card.known?
case @to_pos
when 0..5
player_field.hand.each{|card|card.card = Card::Unknown if card.known? and !card.monster?}
when 6..10
player_field.hand.each{|card|card.card = Card::Unknown if card.known? and card.monster?}
else
player_field.hand.each{|card|card.card = Card::Unknown if card.known?}
end
end
super
end
end
class Set < Move
def initialize(from_player, from_pos, to_pos, card)
super(from_player, from_pos, to_pos, card, nil, :set)
end
end
class Activate < Move
def initialize(from_player, from_pos, to_pos, card)
super(from_player, from_pos, to_pos, card, nil, :attack)
end
end
class Summon < Move
def initialize(from_player, from_pos, to_pos, card, msg=nil)
super(from_player, from_pos, to_pos, card, msg, :attack)
end
end
class SpecialSummon < Move
def initialize(from_player, from_pos, to_pos, card, msg=nil, position=:attack)
super(from_player, from_pos, to_pos, card, msg, position)
end
end
class SendToGraveyard < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :graveyard, card, nil, :attack)
end
end
class Remove < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :removed, card, nil, :attack)
end
end
class ReturnToHand < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :hand, card, nil, :set)
end
end
class ReturnToDeck < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :deck, card, nil, :set)
end
end
class ReturnToDeckBottom < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :deckbottom, card, nil, :set)
end
end
class ReturnToExtra < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, :extra, card, nil, :set)
end
end
class Control < Move
def initialize(from_player, from_pos, card)
super(from_player, from_pos, nil, card)
end
def run
to_pos = opponent_field.field[6..10].index(nil)+6
unless to_pos
$log.warn('转移控制权'){'没有空余场位'}
return
end
card = if @card.is_a? Game_Card
@card
elsif player_field.field[from_pos]
card = player_field.field[from_pos]
card.card = @card
card
else
$log.warn('转移控制权'){'似乎凭空产生了卡片'+self.inspect}
Game_Card.new(@card)
end
player_field.field[from_pos] = nil
opponent_field.field[to_pos] = card
end
end
class SendToOpponentGraveyard < SendToGraveyard
def run
card = if @card.is_a? Game_Card
@card
elsif player_field.field[from_pos]
card = player_field.field[from_pos]
card.card = @card
card
else
Game_Card.new(@card)
end
player_field.field[from_pos] = nil
opponent_field.graveyard.unshift card
end
end
class Tribute < SendToGraveyard; end
class Discard < SendToGraveyard; end
class ChangePosition < Move
def initialize(from_player, from_pos, card, position)
super(from_player, from_pos, from_pos, card, nil, position)
end
end
class Flip < ChangePosition
def initialize(from_player, from_pos, card, position=:defense)
super(from_player, from_pos, card, position)
end
end
class FlipSummon < Flip
def initialize(from_player, from_pos, card)
super(from_player, from_pos, card, :attack)
end
end
class Draw < Move
def initialize(from_player=true, msg=nil)
@from_player = from_player
super(from_player, :decktop, :hand, nil, msg, :set)
end
end
class Counter < Action
end
class MultiDraw < Action
def initialize(from_player, count, msg=nil)
super(from_player, msg)
@count = count
end
def run
super
player_field.hand.concat player_field.deck.pop(@count)
end
end
class MultiMove < Action
def initialize(from_player, from_pos, to_pos, cards=nil)
super(from_player)
@from_pos = from_pos
@to_pos = to_pos
@cards = cards
end
def run
from_field = case @from_pos
when :hand
player_field.hand
when :graveyard
player_field.graveyard
when :spellsandtraps
player_field.field[0..5]
when :monsters
player_field.field[6..10]
end
@cards = if @cards
@cards.collect do |card|
index = from_field.index{|fieldcard|fieldcard and fieldcard.card == card} || from_field.index{|fieldcard|fieldcard and !fieldcard.known?}
if index
fieldcard = from_field[index]
from_field[index] = nil
fieldcard.card = card
fieldcard
else
$log.warn '似乎凭空产生了卡片'
Game_Card.new(@card)
end
end
else
from_field.compact
end
to_field, position = case @to_pos
when :hand
[player_field.hand, :set]
when :graveyard
[player_field.graveyard, :attack]
when :deck
[player_field.deck, :set]
when :removed
[player_field.removed, :attack]
end
#执行部分
case @from_pos
when :hand
player_field.hand.clear
when :graveyard
player_field.graveyard.clear
when :spellsandtraps
player_field.field[0..5] = Array.new(6, nil)
when :monsters
player_field.field[6..10] = Array.new(5, nil)
end
if to_field == player_field.hand or to_field == player_field.deck
@cards.each{|card|card.position = position; to_field.push card}
else
@cards.each{|card|card.position = position; to_field.unshift card}
end
super
end
end
=begin #似乎不需要细分
class MonstersSendToGraveyard < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :graveyard, cards)
end
end
class MonstersRemove < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :remove, cards)
end
end
class MonstersReturnToDeck < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :deck, cards)
end
end
class MonstersReturnToHand < MultiMove
def initialize(from_player, cards)
super(from_player, :monsters, :hand, cards)
end
end
class SpellsAndTrapsSendToGraveyard < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :graveyard, cards)
end
end
class SpellsAndTrapsRemove < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :remove, cards)
end
end
class SpellsAndTrapsReturnToDeck < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :deck, cards)
end
end
class SpellsAndTrapsReturnToHand < MultiMove
def initialize(from_player, cards)
super(from_player, :spellsandtraps, :hand, cards)
end
end
class HandSendToGraveyard < MultiMove
def initialize(from_player, cards)
super(from_player, :hand, :graveyard, cards)
end
end
class HandRemove < MultiMove
def initialize(from_player, cards)
super(from_player, :hand, :remove, cards)
end
end
class HandReturnToDeck < MultiMove
def initialize(from_player, cards)
super(from_player, :hand, :deck, cards)
end
end
=end
class RefreshField < Action
attr_reader :field
def initialize(from_player, field, msg=nil)
super(from_player, msg)
@field = field
end
def run
super
return if @field.is_a? Game_Field #本地信息,无需处理。
player_field.lp = @field[:lp]
if player_field.hand.size > @field[:hand]
player_field.hand.pop(player_field.hand.size-@field[:hand])
elsif player_field.hand.size < @field[:hand]
(@field[:hand]-player_field.hand.size).times{$log.warn('刷新场地-手卡'){'似乎凭空产生了卡片'};player_field.hand.push Game_Card.new(Card::Unknown)}
end
if player_field.deck.size > @field[:deck]
player_field.deck.pop(player_field.deck.size-@field[:deck])
elsif player_field.deck.size < @field[:deck]
(@field[:deck]-player_field.deck.size).times{$log.warn('刷新场地-卡组'){'似乎凭空产生了卡片'};player_field.deck.push Game_Card.new(Card::Unknown)}
end
if player_field.graveyard.size > @field[:graveyard]
player_field.graveyard.pop(player_field.graveyard.size-@field[:graveyard])
elsif player_field.graveyard.size < @field[:graveyard]
(@field[:graveyard]-player_field.graveyard.size).times{$log.warn('刷新场地-墓地'){'似乎凭空产生了卡片'};player_field.graveyard.push Game_Card.new(Card::Unknown)}
end
(0..10).each do |pos|
if @field[pos]
if player_field.field[pos]
player_field.field[pos].card = @field[pos][:card]
else
$log.warn("刷新场地-#{pos}"){'似乎凭空产生了卡片'}
player_field.field[pos] = Game_Card.new(@field[pos][:card])
end
player_field.field[pos].position = @field[pos][:position]
else
player_field.field[pos] = nil
end
end
end
end
class TurnEnd < RefreshField
attr_reader :turn
def initialize(from_player, field, turn, msg=nil)
super(from_player, field, msg)
@turn = turn
end
def run
$game.phase = :DP
$game.turn = @turn.next
$game.turn_player = !from_player
super
end
end
class Show < Move
attr_reader :from_pos, :card
def initialize(from_player, from_pos, card)
super(from_player, from_pos, nil, card)
@from_pos = from_pos
@card = card
end
end
class MultiShow < Action
def initialize(from_player, from_pos=nil, cards)
super(from_player, nil)
@from_pos = from_pos
@cards = cards
end
def run
return if @cards[0].is_a? Game_Card #本地消息,不处理
case @from_pos
when :hand
if player_field.hand.size > @cards.size
player_field.hand.pop(player_field.hand.size-@cards.size)
end
@cards.each_with_index do |card, index|
if player_field.hand[index]
player_field.hand[index].card = card
else
player_field.hand[index] = Game_Card.new card
end
end
when 71..130
cards = @cards.to_enum
player_field.deck[@from_pos-71, @cards.size].each do |game_card|
game_card.card = cards.next
end
end
end
end
class EffectActivate < Move
def initialize(from_player, from_pos, card)
if (0..10).include?(from_pos)
position = :"face-up"
else
position = nil
end
super(from_player, from_pos, to_pos, card, nil, position)
end
end
class ActivateAsk < Action
def initialize(from_player)
super(from_player)
end
end
class ActivateAnswer < Action
def initialize(from_player, activate)
super(from_player)
@activate = activate
end
end
class Target < Action
def initialize(from_player, from_pos, card, target_player ,target_pos, target_card)
super(from_player)
@from_pos = from_pos
@card = card
@target_pos = target_player
@target_pos = target_pos
@target_card = target_card
end
def run
card = if @card.is_a? Game_Card
@card
else
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
player_field.field[@from_pos]
else
$log.warn('攻击宣言'){'似乎凭空产生了卡片' + self.inspect}
player_field[@from_pos] = Game_Card.new(@card)
end
end
$log.info('攻击宣言'){self.inspect}
end
end
class ViewDeck < Action; end
class LP < Action
attr_accessor :operator, :value
def initialize(from_player, operator, value)
super(from_player)
@operator = operator
@value = value
end
def run
case operator
when :lose
player_field.lp -= @value
when :increase
player_field.lp += @value
when :become
player_field.lp = @value
end
end
end
class Attack < Action
def initialize(from_player, from_pos, to_pos=nil, card)
super(from_player)
@from_pos = from_pos
@to_pos = to_pos
@card = card
end
def run
card = if @card.is_a? Game_Card
@card
elsif @from_pos
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
else
$log.warn('攻击宣言'){'似乎凭空产生了卡片' + self.inspect}
player_field.field[@from_pos] = Game_Card.new(@card)
player_field.field[@from_pos].position = :attack
end
player_field.field[@from_pos]
else
$log.info('直接攻击'){'功能未实现'}
@card
end
end
end
class Counter < Action
def initialize(from_player, from_pos, card, operator, value)
super(from_player)
@from_pos = from_pos
@card = card
@operator = operator
@value = value
end
def run
card = if @card.is_a? Game_Card
@card
else
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
else
$log.warn('指示物操作'){'似乎凭空产生了卡片' + self.inspect}
player_field.field[@from_pos] = Game_Card.new(@card)
player_field.field[@from_pos].position = :attack
end
player_field.field[@from_pos]
end
case @operator
when :become
card.counters = @value
else
$log.warn('指示物操作'){'become以外的未实现' + self.inspect}
end
end
end
class Note < Action
def initialize(from_player, from_pos, card, note)
super(from_player)
@from_pos = from_pos
@card = card
@note = note
end
def run
card = if @card.is_a? Game_Card
@card
else
if player_field.field[@from_pos]
player_field.field[@from_pos].card = @card
else
$log.warn('指示物操作'){'似乎凭空产生了卡片' + self.inspect}
player_field.field[@from_pos] = Game_Card.new(@card)
player_field.field[@from_pos].position = :attack
end
player_field.field[@from_pos]
end
card.note = @note
end
end
class Token < SpecialSummon
def initialize(from_player, to_pos, card, position=:defense)
super(from_player, nil, to_pos, card)
end
end
class MultiToken < SpecialSummon
def initialize(from_player, num, card, position=:attack)
super(from_player, nil, nil, card)
@num = num
end
def run
@num.times do
@to_pos = player_field.field[6..10].index(nil)+6
super
end
end
end
class Add < Action
def initialize(from_player, card)
super(from_player)
@card = card
end
def run
if @card.extra?
player_field.extra << Game_Card.new(@card)
else
player_field.hand << Game_Card.new(@card)
end
end
end
class Destroy < Action
def initialize(from_player, from_pos, card)
super(from_player)
@from_pos = from_pos
@card = card
end
def run
if @from_pos <= 10
player_field.field[@from_pos] = nil
else
player_field.hand.delete_at(@from_pos - 11)
end
end
end
class CardInfo < Action
def initialize(card, card_type, atk, _def, attribute, type, level, lore)
return unless card.diy?
card.card_type = card_type
#card.monster_type = monster_type
card.atk = atk
card.def = _def
card.attribute = attribute
card.type = type
card.level = level
card.lore = lore
end
end
class Unknown < Action
def initialize(str)
@str = str
$log.warn('unkonwn action') { str }
end
def run
$log.warn('unkonwn action run'){ @str }
end
end
def self.reset
@@id=1
end
reset
end
\ No newline at end of file
#encoding: UTF-8
#==Card Model
class Card
require 'sqlite3'
@db = SQLite3::Database.new( "data/data.sqlite" )
@all = {}
@diy = {}
@count = @db.get_first_value("select COUNT(*) from `yu-gi-oh`") rescue 0
@db.results_as_hash = true
PicPath = if RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"]
require 'win32/registry'
ospicpath = Win32::Registry::HKEY_CURRENT_USER.open('Software\OCGSOFT\Cards'){|reg|reg['Path']} rescue ''
ospicpath.force_encoding "GBK"
ospicpath.encode "UTF-8"
else
'' #其他操作系统卡图存放位置标准尚未制定。
end
CardBack = Surface.load("graphics/field/card.jpg").display_format rescue nil
CardBack_Small = Surface.load("graphics/field/card_small.gif").display_format rescue nil
class << self
def find(id, order_by=nil)
case id
when Integer
@all[id] || old_new(@db.get_first_row("select * from `yu-gi-oh` where id = #{id}"))
when Symbol
row = @db.get_first_row("select * from `yu-gi-oh` where name = '#{id}'")
if row
@all[row['id'].to_i] || old_new(row)
else
@diy[id] ||= Card.new('id' => 0, 'number' => :"00000000", 'name' => id, 'attribute' => :, 'level' => 1, 'card_type' => :通常怪兽, 'stats' => "", 'archettypes' => "", 'mediums' => "", 'lore' => "")
end
when Hash
old_new(id)
when nil
Card::Unknown
else
sql = "select * from `yu-gi-oh` where " << id
sql << " order by #{order_by}" if order_by
$log.debug('查询卡片执行SQL'){sql}
@db.execute(sql).collect {|row|@all[row['id'].to_i] || old_new(row)}
end
end
def all
if @all.size != @count
sql = "select * from `yu-gi-oh` where id not in (#{@all.keys.join(', ')})"
@db.execute(sql).each{|row|old_new(row)}
end
@all
end
def cache
@all
end
alias old_new new
def new(id)
find(id)
end
def load_from_ycff3(db = RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"] ? (require 'win32/registry';Win32::Registry::HKEY_CURRENT_USER.open('Software\OCGSOFT\YFCC'){|reg|reg['Path']+"YGODATA/YGODAT.dat"} rescue '') : '')
require 'win32ole'
conn = WIN32OLE.new('ADODB.Connection')
conn.open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + db + ";Jet OLEDB:Database Password=paradisefox@sohu.com" )
records = WIN32OLE.new('ADODB.Recordset')
records.open("select EFFECT from YGOEFFECT", conn)
stats = records.GetRows.first
stats.unshift nil
records.close
records = WIN32OLE.new('ADODB.Recordset')
records.open("YGODATA", conn)
records.MoveNext #跳过首行那个空白卡
sql = ""
while !records.EOF
sql << "INSERT INTO `yu-gi-oh` VALUES(
#{records.Fields.Item("CardID").value-1},
'#{records.Fields.Item("CardPass").value}',
'#{records.Fields.Item("SCCardName").value}',
'#{records.Fields.Item("SCCardType").value == "XYZ怪兽" ? "超量怪兽" : records.Fields.Item("SCCardType").value}',
#{records.Fields.Item("SCDCardType").value == '    ' ? "NULL" : "'#{records.Fields.Item("SCDCardType").value}'"},
#{records.Fields.Item("CardATK").value || "NULL"},
#{records.Fields.Item("CardDef").value || "NULL"},
#{records.Fields.Item("SCCardAttribute").value == '    ' ? "NULL" : "'#{records.Fields.Item("SCCardAttribute").value}'"},
#{records.Fields.Item("SCCardRace").value == '    ' ? "NULL" : "'#{records.Fields.Item("SCCardRace").value}'"},
#{records.Fields.Item("CardStarNum").value || "NULL"},
'#{records.Fields.Item("SCCardDepict").value}',
#{case records.Fields.Item("ENCardBan").value; when "Normal"; 3; when "SubConfine"; 2; when "Confine"; 1; else; 0; end},
'#{records.Fields.Item("CardEfficeType").value}',
'#{records.Fields.Item("CardPhal").value.split(",").collect{|stat|stats[stat.to_i]}.join("\t")}',
'#{records.Fields.Item("CardCamp").value.gsub("、", "\t")}',
#{records.Fields.Item("CardISTKEN").value}
);"
records.MoveNext
end
@db.execute('begin transaction')
@db.execute('DROP INDEX if exists "main"."name";')
@db.execute('DROP TABLE if exists "main"."yu-gi-oh";')
@db.execute('CREATE TABLE "yu-gi-oh" (
"id" INTEGER NOT NULL,
"number" TEXT NOT NULL,
"name" TEXT NOT NULL,
"card_type" TEXT NOT NULL,
"monster_type" TEXT,
"atk" INTEGER,
"def" INTEGER,
"attribute" TEXT,
"type" TEXT,
"level" INTEGER,
"lore" TEXT NOT NULL,
"status" INTEGER NOT NULL,
"stats" TEXT NOT NULL,
"archettypes" TEXT NOT NULL,
"mediums" TEXT NOT NULL,
"tokens" INTEGER NOT NULL,
PRIMARY KEY ("id")
);')
@db.execute_batch(sql)
@db.execute('CREATE UNIQUE INDEX "main"."name" ON "yu-gi-oh" ("name");')
@db.execute('commit transaction')
@count = @db.get_first_value("select COUNT(*) from `yu-gi-oh`") #重建计数
@all.clear #清空缓存
end
end
attr_accessor :id
attr_accessor :number
attr_accessor :name
attr_accessor :card_type
attr_accessor :monster_type
attr_accessor :atk
attr_accessor :def
attr_accessor :attribute
attr_accessor :type
attr_accessor :level
attr_accessor :lore
attr_accessor :status
attr_accessor :stats
attr_accessor :archettypes
attr_accessor :mediums
attr_accessor :tokens
def initialize(hash)
@id = hash['id'].to_i
@number = hash['number'].to_sym
@name = hash['name'].to_sym
@card_type = hash['card_type'].to_sym
@monster_type = hash["monster_type"] && hash["monster_type"].to_sym
@atk = hash['atk'] && hash['atk'].to_i
@def = hash['def'] && hash['def'].to_i
@attribute = hash['attribute'] && hash['attribute'].to_sym
@type = hash['type'] && hash['type'].to_sym
@level = hash['level'] && hash['level'].to_i
@lore = hash['lore']
@status = hash['status'].to_i
@stats = hash['stats'].split("\t").collect{|stat|stat.to_i}
@archettypes = hash['archettypes'].split("\t").collect{|archettype|stat.to_sym}
@mediums = hash['mediums'].split("\t").collect{|medium|medium.to_sym}
@tokens = hash['tokens'].to_i
@token = hash['token']
Card.cache[@id] = self
end
def create_image
@image ||= Surface.load("graphics/field/card.jpg").display_format
end
def image
@image ||= Surface.load("#{PicPath}/#{@id}.jpg").display_format rescue create_image
end
def image_small
@image_small ||= image.transform_surface(0xFF000000,0,54.0/image.w, 81.0/image.h,Surface::TRANSFORM_SAFE).copy_rect(1, 1, 54, 81).display_format
end
def image_horizontal
if @image_horizontal.nil?
image_horizontal = image_small.transform_surface(0xFF000000,90,1,1,Surface::TRANSFORM_SAFE)
@image_horizontal = image_horizontal.copy_rect(1, 1, 81, 54).display_format #SDL的bug,会多出1像素的黑边
image_horizontal.destroy
end
@image_horizontal
end
def unknown?
@id == 1
end
def monster?
[:融合怪兽, :同调怪兽, :超量怪兽, :通常怪兽, :效果怪兽, :调整怪兽, :仪式怪兽].include? card_type
end
def trap?
[:通常陷阱, :反击陷阱, :永续陷阱].include? card_type
end
def spell?
[:通常魔法, :速攻魔法, :装备魔法, :场地魔法, :仪式魔法, :永续魔法].include? card_type
end
def extra?
[:融合怪兽, :同调怪兽, :超量怪兽].include? card_type
end
def token?
@token
end
def diy?
number == :"00000000"
end
def known?
self != Unknown
end
def inspect
"[#{card_type}][#{name}]"
end
Unknown = Card.new('id' => 0, 'number' => :"00000000", 'attribute' => :, 'level' => 1, 'name' => "", 'lore' => '', 'card_type' => :通常怪兽, 'stats' => "", 'archettypes' => "", 'mediums' => "")
Unknown.instance_eval{@image = CardBack; @image_small = CardBack_Small}
end
#encoding: UTF-8
#==Card Model
class Card
require 'sqlite3'
@db = SQLite3::Database.new( "data/data.sqlite" )
@all = {}
@diy = {}
@count = @db.get_first_value("select COUNT(*) from `yu-gi-oh`") rescue 0
@db.results_as_hash = true
PicPath = if RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"]
require 'win32/registry'
ospicpath = Win32::Registry::HKEY_CURRENT_USER.open('Software\OCGSOFT\Cards'){|reg|reg['Path']} rescue ''
ospicpath.force_encoding "GBK"
ospicpath.encode "UTF-8"
else
'' #其他操作系统卡图存放位置标准尚未制定。
end
CardBack = Surface.load("graphics/field/card.jpg").display_format rescue nil
CardBack_Small = Surface.load("graphics/field/card_small.gif").display_format rescue nil
class << self
def find(id, order_by=nil)
case id
when Integer
@all[id] || old_new(@db.get_first_row("select * from `yu-gi-oh` where id = #{id}"))
when Symbol
row = @db.get_first_row("select * from `yu-gi-oh` where name = '#{id}'")
if row
@all[row['id'].to_i] || old_new(row)
else
@diy[id] ||= Card.new('id' => 0, 'number' => :"00000000", 'name' => id, 'attribute' => :, 'level' => 1, 'card_type' => :通常怪兽, 'stats' => "", 'archettypes' => "", 'mediums' => "", 'lore' => "")
end
when Hash
old_new(id)
when nil
Card::Unknown
else
sql = "select * from `yu-gi-oh` where " << id
sql << " order by #{order_by}" if order_by
$log.debug('查询卡片执行SQL'){sql}
@db.execute(sql).collect {|row|@all[row['id'].to_i] || old_new(row)}
end
end
def all
if @all.size != @count
sql = "select * from `yu-gi-oh` where id not in (#{@all.keys.join(', ')})"
@db.execute(sql).each{|row|old_new(row)}
end
@all
end
def cache
@all
end
alias old_new new
def new(id)
find(id)
end
def load_from_ycff3(db = RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"] ? (require 'win32/registry';Win32::Registry::HKEY_CURRENT_USER.open('Software\OCGSOFT\YFCC'){|reg|reg['Path']+"YGODATA/YGODAT.dat"} rescue '') : '')
require 'win32ole'
conn = WIN32OLE.new('ADODB.Connection')
conn.open("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + db + ";Jet OLEDB:Database Password=paradisefox@sohu.com" )
records = WIN32OLE.new('ADODB.Recordset')
records.open("select EFFECT from YGOEFFECT", conn)
stats = records.GetRows.first
stats.unshift nil
records.close
records = WIN32OLE.new('ADODB.Recordset')
records.open("YGODATA", conn)
records.MoveNext #跳过首行那个空白卡
sql = ""
while !records.EOF
sql << "INSERT INTO `yu-gi-oh` VALUES(
#{records.Fields.Item("CardID").value-1},
'#{records.Fields.Item("CardPass").value}',
'#{records.Fields.Item("SCCardName").value}',
'#{records.Fields.Item("SCCardType").value == "XYZ怪兽" ? "超量怪兽" : records.Fields.Item("SCCardType").value}',
#{records.Fields.Item("SCDCardType").value == '    ' ? "NULL" : "'#{records.Fields.Item("SCDCardType").value}'"},
#{records.Fields.Item("CardATK").value || "NULL"},
#{records.Fields.Item("CardDef").value || "NULL"},
#{records.Fields.Item("SCCardAttribute").value == '    ' ? "NULL" : "'#{records.Fields.Item("SCCardAttribute").value}'"},
#{records.Fields.Item("SCCardRace").value == '    ' ? "NULL" : "'#{records.Fields.Item("SCCardRace").value}'"},
#{records.Fields.Item("CardStarNum").value || "NULL"},
'#{records.Fields.Item("SCCardDepict").value}',
#{case records.Fields.Item("ENCardBan").value; when "Normal"; 3; when "SubConfine"; 2; when "Confine"; 1; else; 0; end},
'#{records.Fields.Item("CardEfficeType").value}',
'#{records.Fields.Item("CardPhal").value.split(",").collect{|stat|stats[stat.to_i]}.join("\t")}',
'#{records.Fields.Item("CardCamp").value.gsub("、", "\t")}',
#{records.Fields.Item("CardISTKEN").value}
);"
records.MoveNext
end
@db.execute('begin transaction')
@db.execute('DROP INDEX if exists "main"."name";')
@db.execute('DROP TABLE if exists "main"."yu-gi-oh";')
@db.execute('CREATE TABLE "yu-gi-oh" (
"id" INTEGER NOT NULL,
"number" TEXT NOT NULL,
"name" TEXT NOT NULL,
"card_type" TEXT NOT NULL,
"monster_type" TEXT,
"atk" INTEGER,
"def" INTEGER,
"attribute" TEXT,
"type" TEXT,
"level" INTEGER,
"lore" TEXT NOT NULL,
"status" INTEGER NOT NULL,
"stats" TEXT NOT NULL,
"archettypes" TEXT NOT NULL,
"mediums" TEXT NOT NULL,
"tokens" INTEGER NOT NULL,
PRIMARY KEY ("id")
);')
@db.execute_batch(sql)
@db.execute('CREATE UNIQUE INDEX "main"."name" ON "yu-gi-oh" ("name");')
@db.execute('commit transaction')
@count = @db.get_first_value("select COUNT(*) from `yu-gi-oh`") #重建计数
@all.clear #清空缓存
end
end
attr_accessor :id
attr_accessor :number
attr_accessor :name
attr_accessor :card_type
attr_accessor :monster_type
attr_accessor :atk
attr_accessor :def
attr_accessor :attribute
attr_accessor :type
attr_accessor :level
attr_accessor :lore
attr_accessor :status
attr_accessor :stats
attr_accessor :archettypes
attr_accessor :mediums
attr_accessor :tokens
def initialize(hash)
@id = hash['id'].to_i
@number = hash['number'].to_sym
@name = hash['name'].to_sym
@card_type = hash['card_type'].to_sym
@monster_type = hash["monster_type"] && hash["monster_type"].to_sym
@atk = hash['atk'] && hash['atk'].to_i
@def = hash['def'] && hash['def'].to_i
@attribute = hash['attribute'] && hash['attribute'].to_sym
@type = hash['type'] && hash['type'].to_sym
@level = hash['level'] && hash['level'].to_i
@lore = hash['lore']
@status = hash['status'].to_i
@stats = hash['stats'].split("\t").collect{|stat|stat.to_i}
@archettypes = hash['archettypes'].split("\t").collect{|archettype|stat.to_sym}
@mediums = hash['mediums'].split("\t").collect{|medium|medium.to_sym}
@tokens = hash['tokens'].to_i
@token = hash['token']
Card.cache[@id] = self
end
def create_image
@image ||= Surface.load("graphics/field/card.jpg").display_format
end
def image
@image ||= Surface.load("#{PicPath}/#{@id}.jpg").display_format rescue create_image
end
def image_small
@image_small ||= image.transform_surface(0xFF000000,0,54.0/image.w, 81.0/image.h,Surface::TRANSFORM_SAFE).copy_rect(1, 1, 54, 81).display_format
end
def image_horizontal
if @image_horizontal.nil?
image_horizontal = image_small.transform_surface(0xFF000000,90,1,1,Surface::TRANSFORM_SAFE)
@image_horizontal = image_horizontal.copy_rect(1, 1, 81, 54).display_format #SDL的bug,会多出1像素的黑边
image_horizontal.destroy
end
@image_horizontal
end
def unknown?
@id == 1
end
def monster?
[:融合怪兽, :同调怪兽, :超量怪兽, :通常怪兽, :效果怪兽, :调整怪兽, :仪式怪兽].include? card_type
end
def trap?
[:通常陷阱, :反击陷阱, :永续陷阱].include? card_type
end
def spell?
[:通常魔法, :速攻魔法, :装备魔法, :场地魔法, :仪式魔法, :永续魔法].include? card_type
end
def extra?
[:融合怪兽, :同调怪兽, :超量怪兽].include? card_type
end
def token?
@token
end
def diy?
number == :"00000000"
end
def known?
self != Unknown
end
def inspect
"[#{card_type}][#{name}]"
end
Unknown = Card.new('id' => 0, 'number' => :"00000000", 'attribute' => :, 'level' => 1, 'name' => "", 'lore' => '', 'card_type' => :通常怪兽, 'stats' => "", 'archettypes' => "", 'mediums' => "")
Unknown.instance_eval{@image = CardBack; @image_small = CardBack_Small}
end
#Card.load_from_ycff3
\ No newline at end of file
module Dialog
#选择文件对话框
require 'win32api'
GetOpenFileName = Win32API.new("comdlg32.dll", "GetOpenFileNameW", "p", "i")
GetSaveFileName = Win32API.new("comdlg32.dll", "GetSaveFileNameW", "p", "i")
OFN_EXPLORER = 0x00080000
OFN_PATHMUSTEXIST = 0x00000800
OFN_FILEMUSTEXIST = 0x00001000
OFN_ALLOWMULTISELECT = 0x00000200
OFN_FLAGS = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST |
OFN_ALLOWMULTISELECT
#打开网页
require 'win32ole'
Shell = WIN32OLE.new('Shell.Application')
module_function
def get_open_file(title="选择文件", filter = {"所有文件 (*.*)" => "*.*"}, save=nil)
szFile = (0.chr * 20481).encode("UTF-16LE")
szFileTitle = 0.chr * 2049
szTitle = (title+"\0").encode("UTF-16LE")
szFilter = (filter.flatten.join("\0")+"\0\0").encode("UTF-16LE")
szInitialDir = "\0"
ofn =
[
76, # lStructSize L
0, # hwndOwner L
0, # hInstance L
szFilter, # lpstrFilter L
0, # lpstrCustomFilter L
0, # nMaxCustFilter L
1, # nFilterIndex L
szFile, # lpstrFile L
szFile.size - 1, # nMaxFile L
szFileTitle, # lpstrFileTitle L
szFileTitle.size - 1, # nMaxFileTitle L
szInitialDir, # lpstrInitialDir L
szTitle, # lpstrTitle L
OFN_FLAGS, # Flags L
0, # nFileOffset S
0, # nFileExtension S
0, # lpstrDefExt L
0, # lCustData L
0, # lpfnHook L
0 # lpTemplateName L
].pack("LLLPLLLPLPLPPLS2L4")
Dir.chdir {
if save
GetSaveFileName.call(ofn)
else
GetOpenFileName.call(ofn)
end
}
szFile.delete!("\0".encode("UTF-16LE"))
result = szFile.encode("UTF-8")
if !result.empty? and save.is_a? Array
ext = save[ofn.unpack("LLLPLLLPLPLPPLS2L4")[6] - 1]
if result[-ext.size, ext.size].downcase != ext.downcase
result << ext
end
end
result
end
def web(url)
Shell.ShellExecute url
end
def uac(command, *args)
Shell.ShellExecute File.expand_path(command), args.join(' '), Dir.pwd, "runas"
end
module Dialog
#选择文件对话框
require 'win32api'
GetOpenFileName = Win32API.new("comdlg32.dll", "GetOpenFileNameW", "p", "i")
GetSaveFileName = Win32API.new("comdlg32.dll", "GetSaveFileNameW", "p", "i")
OFN_EXPLORER = 0x00080000
OFN_PATHMUSTEXIST = 0x00000800
OFN_FILEMUSTEXIST = 0x00001000
OFN_ALLOWMULTISELECT = 0x00000200
OFN_FLAGS = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST |
OFN_ALLOWMULTISELECT
#打开网页
require 'win32ole'
Shell = WIN32OLE.new('Shell.Application')
module_function
def get_open_file(title="选择文件", filter = {"所有文件 (*.*)" => "*.*"}, save=nil)
szFile = (0.chr * 20481).encode("UTF-16LE")
szFileTitle = 0.chr * 2049
szTitle = (title+"\0").encode("UTF-16LE")
szFilter = (filter.flatten.join("\0")+"\0\0").encode("UTF-16LE")
szInitialDir = "\0"
ofn =
[
76, # lStructSize L
0, # hwndOwner L
0, # hInstance L
szFilter, # lpstrFilter L
0, # lpstrCustomFilter L
0, # nMaxCustFilter L
1, # nFilterIndex L
szFile, # lpstrFile L
szFile.size - 1, # nMaxFile L
szFileTitle, # lpstrFileTitle L
szFileTitle.size - 1, # nMaxFileTitle L
szInitialDir, # lpstrInitialDir L
szTitle, # lpstrTitle L
OFN_FLAGS, # Flags L
0, # nFileOffset S
0, # nFileExtension S
0, # lpstrDefExt L
0, # lCustData L
0, # lpfnHook L
0 # lpTemplateName L
].pack("LLLPLLLPLPLPPLS2L4")
Dir.chdir {
if save
GetSaveFileName.call(ofn)
else
GetOpenFileName.call(ofn)
end
}
szFile.delete!("\0".encode("UTF-16LE"))
result = szFile.encode("UTF-8")
if !result.empty? and save.is_a? Array
ext = save[ofn.unpack("LLLPLLLPLPLPPLS2L4")[6] - 1]
if result[-ext.size, ext.size].downcase != ext.downcase
result << ext
end
end
result
end
def web(url)
Shell.ShellExecute url
end
def uac(command, *args)
Shell.ShellExecute File.expand_path(command), args.join(' '), Dir.pwd, "runas"
end
end
\ No newline at end of file
#游戏适配器的抽象类
require_relative 'game_event'
require_relative 'action'
require_relative 'user'
require_relative 'room'
class Game
attr_reader :users, :rooms
attr_accessor :user, :room, :player_field, :opponent_field, :turn, :turn_player, :phase
def initialize
@users = []
@rooms = []
end
def login(username, password=nil)
end
def refresh
end
def host(room_name, room_config)
end
def join(room)
end
def watch(room)
end
def leave
end
def action(action)
end
def chat(chatmessage)
end
def exit
$scene = Scene_Login.new if $scene
end
def watching?
@room and @room.include? @user
end
def self.deck_edit
require_relative 'window_deck'
@deck_window = Window_Deck.new
end
def refresh_interval
5
end
def show_chat_self
false
end
end
#游戏适配器的抽象类
require_relative 'game_event'
require_relative 'action'
require_relative 'user'
require_relative 'room'
class Game
attr_reader :users, :rooms
attr_accessor :user, :room, :player_field, :opponent_field, :turn, :turn_player, :phase
def initialize
@users = []
@rooms = []
end
def login(username, password=nil)
end
def refresh
end
def host(room_name, room_config)
end
def join(room)
end
def watch(room)
end
def leave
end
def action(action)
end
def chat(chatmessage)
end
def exit
$scene = Scene_Login.new if $scene
end
def watching?
@room and @room.include? @user
end
def self.deck_edit
require_relative 'window_deck'
@deck_window = Window_Deck.new
end
def refresh_interval
5
end
def show_chat_self
false
end
end
#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
#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
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
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
#!/usr/bin/env ruby
begin
Windows = RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"]
Thread.abort_on_exception = true
require_relative 'resolution'
require_relative 'announcement'
require_relative 'config'
require_relative 'association'
#读取配置文件
$config = Config.load
Config.save
#读取命令行参数
log = "log.log"
log_level = "INFO"
profile = nil
ARGV.each do |arg|
arg = arg.dup.force_encoding("UTF-8")
arg.force_encoding("GBK") unless arg.valid_encoding?
case arg
when /--log=(.*)/
log.replace $1
when /--log-level=(.*)/
log_level.replace $1
when /--profile=(.*)/
profile = $1
when /^mycard:.*|\.ydk$|\.yrp$|\.deck$/
require_relative 'quickstart'
$scene = false
when /register_association/
Association.register
$scene = false
end
end
unless $scene == false
#加载文件
require 'logger'
require 'sdl'
include SDL
require_relative 'dialog'
require_relative 'graphics'
require_relative 'window'
require_relative 'widget_msgbox'
#日志
if log == "STDOUT" #调试用
log = STDOUT
end
$log = Logger.new(log)
$log.level = Logger.const_get log_level
#性能分析
if profile
if profile == "STDOUT"
profile = STDOUT
else
profile = open(profile, 'w')
end
require 'profiler'
RubyVM::InstructionSequence.compile_option = {
:trace_instruction => true,
:specialized_instruction => false
}
Profiler__::start_profile
end
SDL::Event::APPMOUSEFOCUS = 1
SDL::Event::APPINPUTFOCUS = 2
SDL::Event::APPACTIVE = 4
SDL.putenv ("SDL_VIDEO_CENTERED=1");
SDL.init(INIT_VIDEO)
WM::set_caption("MyCard", "MyCard")
WM::icon = Surface.load("graphics/system/icon.gif")
$screen = Screen.open($config['screen']['width'], $config['screen']['height'], 0, HWSURFACE | ($config['screen']['fullscreen'] ? FULLSCREEN : 0))
TTF.init
#声音
begin
SDL.init(INIT_AUDIO)
Mixer.open(Mixer::DEFAULT_FREQUENCY, Mixer::DEFAULT_FORMAT, Mixer::DEFAULT_CHANNELS, 1536)
Mixer.set_volume_music(60)
rescue
nil
end
#标题场景
require_relative 'scene_title'
$scene = Scene_Title.new
#自动更新, 加载放到SDL前面会崩, 原因不明
require_relative 'update'
Update.start
WM::set_caption("MyCard v#{Update::Version}", "MyCard")
#文件关联
Association.start
#初始化完毕
$log.info("main") { "初始化成功" }
end
rescue Exception => exception
open('error-程序出错请到论坛反馈.txt', 'w') { |f| f.write [exception.inspect, *exception.backtrace].join("\n") }
$scene = false
end
#主循环
begin
$scene.main while $scene
rescue Exception => exception
exception.backtrace.each { |backtrace| break if backtrace =~ /^(.*)\.rb:\d+:in `.*'"$/ } #由于脚本是从main.rb开始执行的,总会有个能匹配成功的文件
$log.fatal($1) { [exception.inspect, *exception.backtrace].collect { |str| str.force_encoding("UTF-8") }.join("\n") }
$game.exit if $game
require_relative 'scene_error'
$scene = Scene_Error.new
retry
ensure
if profile
Profiler__::print_profile(profile)
profile.close
end
$log.close rescue nil
#!/usr/bin/env ruby
begin
Windows = RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"]
Thread.abort_on_exception = true
require_relative 'resolution'
require_relative 'announcement'
require_relative 'config'
require_relative 'association'
#读取配置文件
$config = Config.load
Config.save
#读取命令行参数
log = "log.log"
log_level = "INFO"
profile = nil
ARGV.each do |arg|
arg = arg.dup.force_encoding("UTF-8")
arg.force_encoding("GBK") unless arg.valid_encoding?
case arg
when /--log=(.*)/
log.replace $1
when /--log-level=(.*)/
log_level.replace $1
when /--profile=(.*)/
profile = $1
when /^mycard:.*|\.ydk$|\.yrp$|\.deck$/
require_relative 'quickstart'
$scene = false
when /register_association/
Association.register
$scene = false
end
end
unless $scene == false
#加载文件
require 'logger'
require 'sdl'
include SDL
require_relative 'dialog'
require_relative 'graphics'
require_relative 'window'
require_relative 'widget_msgbox'
#日志
if log == "STDOUT" #调试用
log = STDOUT
end
$log = Logger.new(log)
$log.level = Logger.const_get log_level
#性能分析
if profile
if profile == "STDOUT"
profile = STDOUT
else
profile = open(profile, 'w')
end
require 'profiler'
RubyVM::InstructionSequence.compile_option = {
:trace_instruction => true,
:specialized_instruction => false
}
Profiler__::start_profile
end
SDL::Event::APPMOUSEFOCUS = 1
SDL::Event::APPINPUTFOCUS = 2
SDL::Event::APPACTIVE = 4
SDL.putenv ("SDL_VIDEO_CENTERED=1");
SDL.init(INIT_VIDEO)
WM::set_caption("MyCard", "MyCard")
WM::icon = Surface.load("graphics/system/icon.gif")
$screen = Screen.open($config['screen']['width'], $config['screen']['height'], 0, HWSURFACE | ($config['screen']['fullscreen'] ? FULLSCREEN : 0))
TTF.init
#声音
begin
SDL.init(INIT_AUDIO)
Mixer.open(Mixer::DEFAULT_FREQUENCY, Mixer::DEFAULT_FORMAT, Mixer::DEFAULT_CHANNELS, 1536)
Mixer.set_volume_music(60)
rescue
nil
end
#标题场景
require_relative 'scene_title'
$scene = Scene_Title.new
#自动更新, 加载放到SDL前面会崩, 原因不明
require_relative 'update'
Update.start
WM::set_caption("MyCard v#{Update::Version}", "MyCard")
#文件关联
Association.start
#初始化完毕
$log.info("main") { "初始化成功" }
end
rescue Exception => exception
open('error-程序出错请到论坛反馈.txt', 'w') { |f| f.write [exception.inspect, *exception.backtrace].join("\n") }
$scene = false
end
#主循环
begin
$scene.main while $scene
rescue Exception => exception
exception.backtrace.each { |backtrace| break if backtrace =~ /^(.*)\.rb:\d+:in `.*'"$/ } #由于脚本是从main.rb开始执行的,总会有个能匹配成功的文件
$log.fatal($1) { [exception.inspect, *exception.backtrace].collect { |str| str.force_encoding("UTF-8") }.join("\n") }
$game.exit if $game
require_relative 'scene_error'
$scene = Scene_Error.new
retry
ensure
if profile
Profiler__::print_profile(profile)
profile.close
end
$log.close rescue nil
end
\ No newline at end of file
#==============================================================================
# 鈻�Scene_Title
#------------------------------------------------------------------------------
# 銆�itle
#==============================================================================
class Picture < Image
@load_path = "graphics/picture"
end
#==============================================================================
# 鈻�Scene_Title
#------------------------------------------------------------------------------
# 銆�itle
#==============================================================================
class Picture < Image
@load_path = "graphics/picture"
end
#encoding: UTF-8
#==============================================================================
# ■ Scene_Base
#------------------------------------------------------------------------------
#  游戏中全部画面的超级类。
#==============================================================================
require_relative 'fpstimer'
require_relative 'game'
require_relative 'window_bgm'
require 'ogginfo'
require_relative 'widget_inputbox'
class Scene
attr_reader :windows
attr_reader :background
@@fpstimer = FPSTimer.new
@@last_bgm = @@bgm = nil
#--------------------------------------------------------------------------
# ● 主处理
#--------------------------------------------------------------------------
def initialize
@background = nil
@windows = []
@active_window = nil
@font = TTF.open('fonts/wqy-microhei.ttc', 16)
end
def main
start
while $scene == self
update
@@fpstimer.wait_frame{draw}
end
terminate
end
def draw
if @background
$screen.put(@background,0,0)
else
$screen.fill_rect(0, 0, $screen.w, $screen.h, 0x000000)
end
@windows.each do |window|
window.draw($screen)
end
if Update.status
@font.draw_blended_utf8($screen, Update.status, 0, 0, 0xFF, 0xFF, 0xFF)
else
@font.draw_blended_utf8($screen, "%.1f" % @@fpstimer.real_fps, 0, 0, 0xFF, 0xFF, 0xFF)
end
$screen.update_rect(0,0,0,0)
end
#--------------------------------------------------------------------------
# ● 开始处理
#--------------------------------------------------------------------------
def start
if $config['bgm'] and @@last_bgm != bgm and SDL.inited_system(INIT_AUDIO) != 0 and File.file? "audio/bgm/#{bgm}"
@@bgm.destroy if @@bgm
@@bgm = Mixer::Music.load "audio/bgm/#{bgm}"
Mixer.fade_in_music(@@bgm, -1, 800)
title = OggInfo.new("audio/bgm/#{bgm}").tag["title"]
@bgm_window = Window_BGM.new title if title and !title.empty?
@@last_bgm = bgm
end
end
def bgm
"title.ogg"
end
def last_bgm
@@last_bgm
end
def last_bgm=(bgm)
@@last_bgm = bgm
end
def refresh_rect(x, y, width, height, background=@background, ox=0,oy=0)
Surface.blit(background,x+ox,y+oy,width,height,$screen,x,y)
yield
$screen.update_rect(x, y, width, height)
end
#--------------------------------------------------------------------------
# ● 执行渐变
#--------------------------------------------------------------------------
def perform_transition
Graphics.transition(10)
end
#--------------------------------------------------------------------------
# ● 开始後处理
#--------------------------------------------------------------------------
def post_start
end
#--------------------------------------------------------------------------
# ● 更新画面
#--------------------------------------------------------------------------
def update
@bgm_window.update if @bgm_window and !@bgm_window.destroyed?
while event = Event.poll
handle(event)
end
#要不要放到一个Scene_Game里来处理这个?
while event = Game_Event.poll
handle_game(event)
end
end
def handle(event)
case event
when Event::MouseMotion
update_active_window(event.x, event.y)
when Event::MouseButtonDown
case event.button
when Mouse::BUTTON_LEFT
update_active_window(event.x, event.y)
@active_window.clicked if @active_window
if !(@active_window.is_a? Widget_InputBox)
Widget_InputBox.focus = false
end
when 4
@active_window.scroll_up if @active_window
when 5
@active_window.scroll_down if @active_window
end
when Event::MouseButtonUp
case event.button
when Mouse::BUTTON_LEFT
update_active_window(event.x, event.y)
@active_window.mouseleftbuttonup if @active_window
end
when Event::KeyDown
case event.sym
when Key::RETURN
if event.mod & Key::MOD_ALT != 0
$config['screen']['fullscreen'] = !$config['screen']['fullscreen']
$screen.destroy
style = HWSURFACE
style |= FULLSCREEN if $config['screen']["fullscreen"]
$screen = Screen.open($config['screen']["width"], $config['screen']["height"], 0, style)
Config.save
end
when Key::F12
$scene = Scene_Title.new
else
#$log.info('unhandled event'){event.inspect}
end
when Event::Quit
$scene = nil
when Event::Active
if (event.state & Event::APPINPUTFOCUS) != 0
Widget_InputBox.focus = event.gain
end
else
#$log.info('unhandled event'){event.inspect}
end
end
def handle_game(event)
case event
when Game_Event::Error
if event.fatal
Widget_Msgbox.new(event.title, event.message, :ok => "确定"){$game.exit if $game;$scene = Scene_Login.new}
else
Widget_Msgbox.new(event.title, event.message, :ok => "确定")
end
else
$log.debug('未处理的游戏事件'){event.inspect}
end
end
#--------------------------------------------------------------------------
# ● 结束前处理
#--------------------------------------------------------------------------
def pre_terminate
end
#--------------------------------------------------------------------------
# ● 结束处理
#--------------------------------------------------------------------------
def terminate
self.windows.each{|window|window.destroy}
end
def update_active_window(x, y)
self.windows.reverse.each do |window|
if window.include?(x, y) && window.visible
if window != @active_window
@active_window.lostfocus(window) if @active_window and !@active_window.destroyed?
@active_window = window
end
@active_window.mousemoved(x, y)
return @active_window
end
end
if @active_window and !@active_window.destroyed?
@active_window.lostfocus
@active_window = nil
end
end
end
#encoding: UTF-8
#==============================================================================
# ■ Scene_Base
#------------------------------------------------------------------------------
#  游戏中全部画面的超级类。
#==============================================================================
require_relative 'fpstimer'
require_relative 'game'
require_relative 'window_bgm'
require 'ogginfo'
require_relative 'widget_inputbox'
class Scene
attr_reader :windows
attr_reader :background
@@fpstimer = FPSTimer.new
@@last_bgm = @@bgm = nil
#--------------------------------------------------------------------------
# ● 主处理
#--------------------------------------------------------------------------
def initialize
@background = nil
@windows = []
@active_window = nil
@font = TTF.open('fonts/wqy-microhei.ttc', 16)
end
def main
start
while $scene == self
update
@@fpstimer.wait_frame{draw}
end
terminate
end
def draw
if @background
$screen.put(@background,0,0)
else
$screen.fill_rect(0, 0, $screen.w, $screen.h, 0x000000)
end
@windows.each do |window|
window.draw($screen)
end
if Update.status
@font.draw_blended_utf8($screen, Update.status, 0, 0, 0xFF, 0xFF, 0xFF)
else
@font.draw_blended_utf8($screen, "%.1f" % @@fpstimer.real_fps, 0, 0, 0xFF, 0xFF, 0xFF)
end
$screen.update_rect(0,0,0,0)
end
#--------------------------------------------------------------------------
# ● 开始处理
#--------------------------------------------------------------------------
def start
if $config['bgm'] and @@last_bgm != bgm and SDL.inited_system(INIT_AUDIO) != 0 and File.file? "audio/bgm/#{bgm}"
@@bgm.destroy if @@bgm
@@bgm = Mixer::Music.load "audio/bgm/#{bgm}"
Mixer.fade_in_music(@@bgm, -1, 800)
title = OggInfo.new("audio/bgm/#{bgm}").tag["title"]
@bgm_window = Window_BGM.new title if title and !title.empty?
@@last_bgm = bgm
end
end
def bgm
"title.ogg"
end
def last_bgm
@@last_bgm
end
def last_bgm=(bgm)
@@last_bgm = bgm
end
def refresh_rect(x, y, width, height, background=@background, ox=0,oy=0)
Surface.blit(background,x+ox,y+oy,width,height,$screen,x,y)
yield
$screen.update_rect(x, y, width, height)
end
#--------------------------------------------------------------------------
# ● 执行渐变
#--------------------------------------------------------------------------
def perform_transition
Graphics.transition(10)
end
#--------------------------------------------------------------------------
# ● 开始後处理
#--------------------------------------------------------------------------
def post_start
end
#--------------------------------------------------------------------------
# ● 更新画面
#--------------------------------------------------------------------------
def update
@bgm_window.update if @bgm_window and !@bgm_window.destroyed?
while event = Event.poll
handle(event)
end
#要不要放到一个Scene_Game里来处理这个?
while event = Game_Event.poll
handle_game(event)
end
end
def handle(event)
case event
when Event::MouseMotion
update_active_window(event.x, event.y)
when Event::MouseButtonDown
case event.button
when Mouse::BUTTON_LEFT
update_active_window(event.x, event.y)
@active_window.clicked if @active_window
if !(@active_window.is_a? Widget_InputBox)
Widget_InputBox.focus = false
end
when 4
@active_window.scroll_up if @active_window
when 5
@active_window.scroll_down if @active_window
end
when Event::MouseButtonUp
case event.button
when Mouse::BUTTON_LEFT
update_active_window(event.x, event.y)
@active_window.mouseleftbuttonup if @active_window
end
when Event::KeyDown
case event.sym
when Key::RETURN
if event.mod & Key::MOD_ALT != 0
$config['screen']['fullscreen'] = !$config['screen']['fullscreen']
$screen.destroy
style = HWSURFACE
style |= FULLSCREEN if $config['screen']["fullscreen"]
$screen = Screen.open($config['screen']["width"], $config['screen']["height"], 0, style)
Config.save
end
when Key::F12
$scene = Scene_Title.new
else
#$log.info('unhandled event'){event.inspect}
end
when Event::Quit
$scene = nil
when Event::Active
if (event.state & Event::APPINPUTFOCUS) != 0
Widget_InputBox.focus = event.gain
end
else
#$log.info('unhandled event'){event.inspect}
end
end
def handle_game(event)
case event
when Game_Event::Error
if event.fatal
Widget_Msgbox.new(event.title, event.message, :ok => "确定"){$game.exit if $game;$scene = Scene_Login.new}
else
Widget_Msgbox.new(event.title, event.message, :ok => "确定")
end
else
$log.debug('未处理的游戏事件'){event.inspect}
end
end
#--------------------------------------------------------------------------
# ● 结束前处理
#--------------------------------------------------------------------------
def pre_terminate
end
#--------------------------------------------------------------------------
# ● 结束处理
#--------------------------------------------------------------------------
def terminate
self.windows.each{|window|window.destroy}
end
def update_active_window(x, y)
self.windows.reverse.each do |window|
if window.include?(x, y) && window.visible
if window != @active_window
@active_window.lostfocus(window) if @active_window and !@active_window.destroyed?
@active_window = window
end
@active_window.mousemoved(x, y)
return @active_window
end
end
if @active_window and !@active_window.destroyed?
@active_window.lostfocus
@active_window = nil
end
end
end
#encoding: UTF-8
#==============================================================================
# Scene_Duel
#------------------------------------------------------------------------------
# 决斗盘的场景
#==============================================================================
class Scene_Duel < Scene
require_relative 'window_lp'
require_relative 'window_phases'
require_relative 'window_field'
require_relative 'window_fieldback'
require_relative 'card'
require_relative 'deck'
require_relative 'action'
require_relative 'replay'
require_relative 'game_card'
require_relative 'game_field'
require_relative 'window_chat'
attr_reader :cardinfo_window
attr_reader :player_field_window
attr_reader :opponent_field_window
attr_reader :fieldback_window
def initialize(room, deck=nil)
super()
@room = room
@deck = deck
end
def start
WM::set_caption("MyCard v#{Update::Version} - #{$config['game']} - #{$game.user.name}(#{$game.user.id}) - #{@room.name}(#{@room.id})", "MyCard")
@background = Surface.load("graphics/field/main.png").display_format
Surface.blit(@background, 0, 0, 0, 0, $screen, 0, 0)
init_game
init_replay
@phases_window = Window_Phases.new(122, 356)
@fieldback_window = Window_FieldBack.new(131,173)
@cardinfo_window = Window_CardInfo.new(715, 0)
@player_field_window = Window_Field.new(2, 397, $game.player_field, true)
@opponent_field_window = Window_Field.new(2, 56, $game.opponent_field, false)
@player_lp_window = Window_LP.new(0,0, @room.player1, true)
@opponent_lp_window = Window_LP.new(360,0, @room.player2, false)
@join_se = Mixer::Wave.load("audio/se/join.ogg") if SDL.inited_system(INIT_AUDIO) != 0
create_action_window
create_chat_window
super
end
def bgm
"duel.ogg"
end
def create_action_window
@player_field_window.action_window = Window_Action.new
end
def create_chat_window
@background.fill_rect(@cardinfo_window.x, @cardinfo_window.height, 1024-@cardinfo_window.x, 768-@cardinfo_window.height,0xFFFFFFFF)
@chat_window = Window_Chat.new(@cardinfo_window.x, @cardinfo_window.height, 1024-@cardinfo_window.x, 768-@cardinfo_window.height){|text|chat(text)}
@chat_window.channel = @room
end
def chat(text)
action Action::Chat.new(true, text)
end
def init_replay
@replay = Replay.new
end
def save_replay
#@replay.save if @replay #功能尚不可用
end
def init_game
$game.player_field = Game_Field.new @deck
$game.opponent_field = Game_Field.new
$game.turn_player = true #
$game.turn = 0
end
def change_phase(phase)
action Action::ChangePhase.new(true, phase)
if phase == :EP and
action Action::TurnEnd.new(true, $game.player_field, $game.turn_player ? $game.turn : $game.turn.next)
end
end
def reset
action Action::Reset.new(true)
end
def first_to_go
action Action::FirstToGo.new(true)
end
def handle(event)
case event
when Event::MouseButtonDown
case event.button
when Mouse::BUTTON_RIGHT
if @player_field_window.action_window
@player_field_window.action_window.next
end
else
super
end
when Event::KeyDown
case event.sym
when Key::F1
action Action::Shuffle.new
@player_field_window.refresh
when Key::F2
first_to_go
@player_field_window.refresh
when Key::F3
action Action::Dice.new(true)
when Key::F5
reset
@player_field_window.refresh
when Key::F10
$game.leave
else
super
end
else
super
end
end
def action(action)
$game.action action# if @from_player
Game_Event.push Game_Event::Action.new(action)
end
def handle_game(event)
case event
when Game_Event::Chat
@chat_window.add event.chatmessage
when Game_Event::Action
if event.action.instance_of?(Action::Reset) and event.action.from_player
save_replay
init_replay
end
@replay.add event.str
str = event.str
if str =~ /^\[\d+\] (.*)$/m
str = $1
end
if str =~ /^(?:●|◎)→(.*)$/m
str = $1
end
user = if $game.room.player2 == $game.user
event.action.from_player ? $game.room.player2 : $game.room.player1
else
event.action.from_player ? $game.room.player1 : $game.room.player2
end
@chat_window.add ChatMessage.new(user, str, $game.room)
event.action.run
refresh
when Game_Event::Leave
$scene = Scene_Lobby.new
when Game_Event::Join
$game.room = event.room
@player_lp_window.player = $game.room.player1
@opponent_lp_window.player = $game.room.player2
player = $game.room.player1 == $game.user ? $game.room.player2 : $game.room.player1
if player
notify_send("对手加入房间", "#{player.name}(#{player.id})")
Mixer.play_channel(-1,@join_se,0) if SDL.inited_system(INIT_AUDIO) != 0
else
notify_send("对手离开房间", "对手离开房间")
end
else
super
end
end
def update
@cardinfo_window.update
@chat_window.update
super
end
def refresh
@fieldback_window.card = $game.player_field.field[0] && $game.player_field.field[0].card_type == :"场地魔法" && $game.player_field.field[0].position == :attack ? $game.player_field.field[0] : $game.opponent_field.field[0] && $game.opponent_field.field[0].card_type == :"场地魔法" && $game.opponent_field.field[0].position == :attack ? $game.opponent_field.field[0] : nil
@player_field_window.refresh
@opponent_field_window.refresh
@phases_window.player = $game.turn_player
@phases_window.phase = $game.phase
@player_lp_window.lp = $game.player_field.lp
@opponent_lp_window.lp = $game.opponent_field.lp
end
def terminate
unless $scene.is_a? Scene_Lobby or $scene.is_a? Scene_Duel
$game.exit
end
save_replay
super
end
def notify_send(title, msg)
command = "notify-send -i graphics/system/icon.ico #{title} #{msg}"
command = "start ruby/bin/#{command}".encode "GBK" if RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"]
system(command)
$log.info command
end
#encoding: UTF-8
#==============================================================================
# Scene_Duel
#------------------------------------------------------------------------------
# 决斗盘的场景
#==============================================================================
class Scene_Duel < Scene
require_relative 'window_lp'
require_relative 'window_phases'
require_relative 'window_field'
require_relative 'window_fieldback'
require_relative 'card'
require_relative 'deck'
require_relative 'action'
require_relative 'replay'
require_relative 'game_card'
require_relative 'game_field'
require_relative 'window_chat'
attr_reader :cardinfo_window
attr_reader :player_field_window
attr_reader :opponent_field_window
attr_reader :fieldback_window
def initialize(room, deck=nil)
super()
@room = room
@deck = deck
end
def start
WM::set_caption("MyCard v#{Update::Version} - #{$config['game']} - #{$game.user.name}(#{$game.user.id}) - #{@room.name}(#{@room.id})", "MyCard")
@background = Surface.load("graphics/field/main.png").display_format
Surface.blit(@background, 0, 0, 0, 0, $screen, 0, 0)
init_game
init_replay
@phases_window = Window_Phases.new(122, 356)
@fieldback_window = Window_FieldBack.new(131,173)
@cardinfo_window = Window_CardInfo.new(715, 0)
@player_field_window = Window_Field.new(2, 397, $game.player_field, true)
@opponent_field_window = Window_Field.new(2, 56, $game.opponent_field, false)
@player_lp_window = Window_LP.new(0,0, @room.player1, true)
@opponent_lp_window = Window_LP.new(360,0, @room.player2, false)
@join_se = Mixer::Wave.load("audio/se/join.ogg") if SDL.inited_system(INIT_AUDIO) != 0
create_action_window
create_chat_window
super
end
def bgm
"duel.ogg"
end
def create_action_window
@player_field_window.action_window = Window_Action.new
end
def create_chat_window
@background.fill_rect(@cardinfo_window.x, @cardinfo_window.height, 1024-@cardinfo_window.x, 768-@cardinfo_window.height,0xFFFFFFFF)
@chat_window = Window_Chat.new(@cardinfo_window.x, @cardinfo_window.height, 1024-@cardinfo_window.x, 768-@cardinfo_window.height){|text|chat(text)}
@chat_window.channel = @room
end
def chat(text)
action Action::Chat.new(true, text)
end
def init_replay
@replay = Replay.new
end
def save_replay
#@replay.save if @replay #功能尚不可用
end
def init_game
$game.player_field = Game_Field.new @deck
$game.opponent_field = Game_Field.new
$game.turn_player = true #
$game.turn = 0
end
def change_phase(phase)
action Action::ChangePhase.new(true, phase)
if phase == :EP and
action Action::TurnEnd.new(true, $game.player_field, $game.turn_player ? $game.turn : $game.turn.next)
end
end
def reset
action Action::Reset.new(true)
end
def first_to_go
action Action::FirstToGo.new(true)
end
def handle(event)
case event
when Event::MouseButtonDown
case event.button
when Mouse::BUTTON_RIGHT
if @player_field_window.action_window
@player_field_window.action_window.next
end
else
super
end
when Event::KeyDown
case event.sym
when Key::F1
action Action::Shuffle.new
@player_field_window.refresh
when Key::F2
first_to_go
@player_field_window.refresh
when Key::F3
action Action::Dice.new(true)
when Key::F5
reset
@player_field_window.refresh
when Key::F10
$game.leave
else
super
end
else
super
end
end
def action(action)
$game.action action# if @from_player
Game_Event.push Game_Event::Action.new(action)
end
def handle_game(event)
case event
when Game_Event::Chat
@chat_window.add event.chatmessage
when Game_Event::Action
if event.action.instance_of?(Action::Reset) and event.action.from_player
save_replay
init_replay
end
@replay.add event.str
str = event.str
if str =~ /^\[\d+\] (.*)$/m
str = $1
end
if str =~ /^(?:●|◎)→(.*)$/m
str = $1
end
user = if $game.room.player2 == $game.user
event.action.from_player ? $game.room.player2 : $game.room.player1
else
event.action.from_player ? $game.room.player1 : $game.room.player2
end
@chat_window.add ChatMessage.new(user, str, $game.room)
event.action.run
refresh
when Game_Event::Leave
$scene = Scene_Lobby.new
when Game_Event::Join
$game.room = event.room
@player_lp_window.player = $game.room.player1
@opponent_lp_window.player = $game.room.player2
player = $game.room.player1 == $game.user ? $game.room.player2 : $game.room.player1
if player
notify_send("对手加入房间", "#{player.name}(#{player.id})")
Mixer.play_channel(-1,@join_se,0) if SDL.inited_system(INIT_AUDIO) != 0
else
notify_send("对手离开房间", "对手离开房间")
end
else
super
end
end
def update
@cardinfo_window.update
@chat_window.update
super
end
def refresh
@fieldback_window.card = $game.player_field.field[0] && $game.player_field.field[0].card_type == :"场地魔法" && $game.player_field.field[0].position == :attack ? $game.player_field.field[0] : $game.opponent_field.field[0] && $game.opponent_field.field[0].card_type == :"场地魔法" && $game.opponent_field.field[0].position == :attack ? $game.opponent_field.field[0] : nil
@player_field_window.refresh
@opponent_field_window.refresh
@phases_window.player = $game.turn_player
@phases_window.phase = $game.phase
@player_lp_window.lp = $game.player_field.lp
@opponent_lp_window.lp = $game.opponent_field.lp
end
def terminate
unless $scene.is_a? Scene_Lobby or $scene.is_a? Scene_Duel
$game.exit
end
save_replay
super
end
def notify_send(title, msg)
command = "notify-send -i graphics/system/icon.ico #{title} #{msg}"
command = "start ruby/bin/#{command}".encode "GBK" if RUBY_PLATFORM["win"] || RUBY_PLATFORM["ming"]
system(command)
$log.info command
end
end
\ No newline at end of file
#encoding: UTF-8
#==============================================================================
# Scene_Lobby
#------------------------------------------------------------------------------
# 大厅
#==============================================================================
class Scene_Lobby < Scene
require_relative 'window_userlist'
require_relative 'window_userinfo'
require_relative 'window_roomlist'
require_relative 'window_chat'
require_relative 'window_host'
require_relative 'window_lobbybuttons'
require_relative 'chatmessage'
require_relative 'scene_duel'
attr_reader :chat_window
def start
WM::set_caption("MyCard v#{Update::Version} - #{$config['game']} - #{$game.user.name}(#{$game.user.id})", "MyCard")
$game.refresh
@background = Graphics.load('lobby', 'background', false)
Surface.blit(@background,0,0,0,0,$screen,0,0)
@userlist = Window_UserList.new(24,204,$game.users)
@roomlist = Window_RoomList.new(320,50,$game.rooms)
@userinfo = Window_UserInfo.new(24,24, $game.user)
@host_window = Window_LobbyButtons.new(748,18)
@active_window = @roomlist
@chat_window = Window_Chat.new(313,$config['screen']['height'] - 225,698,212)
@count = 0
super
end
def bgm
"lobby.ogg"
end
def handle(event)
case event
when Event::KeyDown
case event.sym
when Key::UP
@active_window.cursor_up
when Key::DOWN
@active_window.cursor_down
when Key::F2
#@joinroom_msgbox = Widget_Msgbox.new("创建房间", "正在等待对手")
#$game.host Room.new(0, $game.user.name)
when Key::F3
#@joinroom_msgbox = Widget_Msgbox.new("加入房间", "正在加入房间")
#$game.join 'localhost'
when Key::F5
$game.refresh
when Key::F12
$game.exit
$scene = Scene_Login.new
end
else
super
end
end
def handle_game(event)
case event
when Game_Event::AllUsers
@userlist.items = $game.users
when Game_Event::AllRooms
@roomlist.items = $game.rooms
when Game_Event::Join
join(event.room)
when Game_Event::Watch
require_relative 'scene_watch'
$scene = Scene_Watch.new(event.room)
when Game_Event::Chat
@chat_window.add event.chatmessage
else
super
end
end
def join(room)
$scene = Scene_Duel.new(room)
end
def update
@chat_window.update
@host_window.update
@roomlist.update
if @count >= $game.refresh_interval*60
$game.refresh
@count = 0
end
@count += 1
super
end
def terminate
unless $scene.is_a? Scene_Lobby or $scene.is_a? Scene_Duel
$game.exit
end
end
#encoding: UTF-8
#==============================================================================
# Scene_Lobby
#------------------------------------------------------------------------------
# 大厅
#==============================================================================
class Scene_Lobby < Scene
require_relative 'window_userlist'
require_relative 'window_userinfo'
require_relative 'window_roomlist'
require_relative 'window_chat'
require_relative 'window_host'
require_relative 'window_lobbybuttons'
require_relative 'chatmessage'
require_relative 'scene_duel'
attr_reader :chat_window
def start
WM::set_caption("MyCard v#{Update::Version} - #{$config['game']} - #{$game.user.name}(#{$game.user.id})", "MyCard")
$game.refresh
@background = Graphics.load('lobby', 'background', false)
Surface.blit(@background,0,0,0,0,$screen,0,0)
@userlist = Window_UserList.new(24,204,$game.users)
@roomlist = Window_RoomList.new(320,50,$game.rooms)
@userinfo = Window_UserInfo.new(24,24, $game.user)
@host_window = Window_LobbyButtons.new(748,18)
@active_window = @roomlist
@chat_window = Window_Chat.new(313,$config['screen']['height'] - 225,698,212)
@count = 0
super
end
def bgm
"lobby.ogg"
end
def handle(event)
case event
when Event::KeyDown
case event.sym
when Key::UP
@active_window.cursor_up
when Key::DOWN
@active_window.cursor_down
when Key::F2
#@joinroom_msgbox = Widget_Msgbox.new("创建房间", "正在等待对手")
#$game.host Room.new(0, $game.user.name)
when Key::F3
#@joinroom_msgbox = Widget_Msgbox.new("加入房间", "正在加入房间")
#$game.join 'localhost'
when Key::F5
$game.refresh
when Key::F12
$game.exit
$scene = Scene_Login.new
end
else
super
end
end
def handle_game(event)
case event
when Game_Event::AllUsers
@userlist.items = $game.users
when Game_Event::AllRooms
@roomlist.items = $game.rooms
when Game_Event::Join
join(event.room)
when Game_Event::Watch
require_relative 'scene_watch'
$scene = Scene_Watch.new(event.room)
when Game_Event::Chat
@chat_window.add event.chatmessage
else
super
end
end
def join(room)
$scene = Scene_Duel.new(room)
end
def update
@chat_window.update
@host_window.update
@roomlist.update
if @count >= $game.refresh_interval*60
$game.refresh
@count = 0
end
@count += 1
super
end
def terminate
unless $scene.is_a? Scene_Lobby or $scene.is_a? Scene_Duel
$game.exit
end
end
end
\ No newline at end of file
#encoding: UTF-8
#==============================================================================
# ■ Scene_Login
#------------------------------------------------------------------------------
#  login
#==============================================================================
require_relative 'window_gameselect'
require_relative 'window_announcements'
require_relative 'window_login'
require_relative 'scene_replay'
require_relative 'scene_lobby'
class Scene_Login < Scene
def start
WM::set_caption("MyCard v#{Update::Version}", "MyCard")
@background = Graphics.load('login', 'background', false)
#======================================================
# We'll pay fpr that soon or later.
#======================================================
if $config['screen']['height'] == 768
@gameselect_window = Window_GameSelect.new(117,269)
elsif $config['screen']['height'] == 640
@gameselect_window = Window_GameSelect.new(117,134)
else
raise "无法分辨的分辨率"
end
#======================================================
# ENDS HERE
#======================================================
super
end
def update
@gameselect_window.update
super
end
def handle_game(event)
case event
when Game_Event::Login
require_relative 'scene_lobby'
$scene = Scene_Lobby.new
else
super
end
end
#def terminate
# @gameselect_window.destroy
#end
#encoding: UTF-8
#==============================================================================
# ■ Scene_Login
#------------------------------------------------------------------------------
#  login
#==============================================================================
require_relative 'window_gameselect'
require_relative 'window_announcements'
require_relative 'window_login'
require_relative 'scene_replay'
require_relative 'scene_lobby'
class Scene_Login < Scene
def start
WM::set_caption("MyCard v#{Update::Version}", "MyCard")
@background = Graphics.load('login', 'background', false)
#======================================================
# We'll pay fpr that soon or later.
#======================================================
if $config['screen']['height'] == 768
@gameselect_window = Window_GameSelect.new(117,269)
elsif $config['screen']['height'] == 640
@gameselect_window = Window_GameSelect.new(117,134)
else
raise "无法分辨的分辨率"
end
#======================================================
# ENDS HERE
#======================================================
super
end
def update
@gameselect_window.update
super
end
def handle_game(event)
case event
when Game_Event::Login
require_relative 'scene_lobby'
$scene = Scene_Lobby.new
else
super
end
end
#def terminate
# @gameselect_window.destroy
#end
end
\ No newline at end of file
#encoding: UTF-8
#==============================================================================
# Scene_Title
#------------------------------------------------------------------------------
# title
#==============================================================================
require_relative 'scene'
require_relative 'widget_inputbox'
require_relative 'window_title'
BGM = 'title.ogg'
class Scene_Title < Scene
def start
WM::set_caption("MyCard v#{Update::Version}", "MyCard")
title = Dir.glob("graphics/titles/title_*.*")
title = title[rand(title.size)]
@background = Surface.load(title).display_format
Surface.blit(@background,0,0,0,0,$screen,0,0)
@command_window = Window_Title.new(title["left"] ? 200 : title["right"] ? 600 : 400, $config['screen']['height']/2-100)
@decision_se = Mixer::Wave.load("audio/se/decision.ogg") if SDL.inited_system(INIT_AUDIO) != 0
super
end
def clear(x,y,width,height)
Surface.blit(@background,x,y,width,height,$screen,x,y)
end
def determine
return unless @command_window.index
Mixer.play_channel(-1,@decision_se,0) if SDL.inited_system(INIT_AUDIO) != 0
case @command_window.index
when 0
require_relative 'scene_login'
$scene = Scene_Login.new
when 1
#require_relative 'scene_single'
require_relative 'widget_msgbox'
Widget_Msgbox.new("mycard", "功能未实现", :ok => "确定")
#Scene_Single.new
when 2
require_relative 'widget_msgbox'
require_relative 'scene_login'
require_relative 'deck'
load 'lib/ygocore/game.rb' #TODO:不规范啊不规范
Ygocore.deck_edit
when 3
require_relative 'scene_config'
$scene = Scene_Config.new
when 4
$scene = nil
end
end
def terminate
@command_window.destroy
@background.destroy
super
end
end
#encoding: UTF-8
#==============================================================================
# Scene_Title
#------------------------------------------------------------------------------
# title
#==============================================================================
require_relative 'scene'
require_relative 'widget_inputbox'
require_relative 'window_title'
BGM = 'title.ogg'
class Scene_Title < Scene
def start
WM::set_caption("MyCard v#{Update::Version}", "MyCard")
title = Dir.glob("graphics/titles/title_*.*")
title = title[rand(title.size)]
@background = Surface.load(title).display_format
Surface.blit(@background,0,0,0,0,$screen,0,0)
@command_window = Window_Title.new(title["left"] ? 200 : title["right"] ? 600 : 400, $config['screen']['height']/2-100)
@decision_se = Mixer::Wave.load("audio/se/decision.ogg") if SDL.inited_system(INIT_AUDIO) != 0
super
end
def clear(x,y,width,height)
Surface.blit(@background,x,y,width,height,$screen,x,y)
end
def determine
return unless @command_window.index
Mixer.play_channel(-1,@decision_se,0) if SDL.inited_system(INIT_AUDIO) != 0
case @command_window.index
when 0
require_relative 'scene_login'
$scene = Scene_Login.new
when 1
#require_relative 'scene_single'
require_relative 'widget_msgbox'
Widget_Msgbox.new("mycard", "功能未实现", :ok => "确定")
#Scene_Single.new
when 2
require_relative 'widget_msgbox'
require_relative 'scene_login'
require_relative 'deck'
load 'lib/ygocore/game.rb' #TODO:不规范啊不规范
Ygocore.deck_edit
when 3
require_relative 'scene_config'
$scene = Scene_Config.new
when 4
$scene = nil
end
end
def terminate
@command_window.destroy
@background.destroy
super
end
end
#encoding: UTF-8
#==============================================================================
# ■ Scene_Watch
#------------------------------------------------------------------------------
#  观战
#==============================================================================
require_relative 'scene_duel'
class Scene_Watch < Scene_Duel
def create_action_window
end
def chat(text)
$game.chat text, $game.room
Game_Event.push Game_Event::Action.new(Action::Chat.new(true, text), "#{$game.user}:#{text}")
end
def action(action)
end
def start
super
#$game.chat "#{$game.user.name}(#{$game.user.id})进入了观战", @room
end
def terminate
#$game.chat "#{$game.user.name}(#{$game.user.id})离开了观战", @room
end
def handle_game(event)
case event
when Game_Event::Leave
Widget_Msgbox.new("离开房间", "观战结束", :ok => "确定") { $scene = Scene_Lobby.new }
else
super
end
end
end
#encoding: UTF-8
#==============================================================================
# ■ Scene_Watch
#------------------------------------------------------------------------------
#  观战
#==============================================================================
require_relative 'scene_duel'
class Scene_Watch < Scene_Duel
def create_action_window
end
def chat(text)
$game.chat text, $game.room
Game_Event.push Game_Event::Action.new(Action::Chat.new(true, text), "#{$game.user}:#{text}")
end
def action(action)
end
def start
super
#$game.chat "#{$game.user.name}(#{$game.user.id})进入了观战", @room
end
def terminate
#$game.chat "#{$game.user.name}(#{$game.user.id})离开了观战", @room
end
def handle_game(event)
case event
when Game_Event::Leave
Widget_Msgbox.new("离开房间", "观战结束", :ok => "确定") { $scene = Scene_Lobby.new }
else
super
end
end
end
require 'open-uri'
require "fileutils"
require_relative 'card'
module Update
Version = '0.7.4'
URL = "http://my-card.in/mycard/update.json?version=#{Version}"
class <<self
attr_reader :thumbnails, :images, :status
def start
Dir.glob("mycard-update-*-*.zip") do |file|
file =~ /mycard-update-(.+?)-(.+?)\.zip/
if $1 <= Version and $2 > Version
$log.info('安装更新'){file}
WM::set_caption("MyCard - 正在更新 #{Version} -> #{$2}", "MyCard")
require 'zip/zip'
Zip::ZipFile::open(file) do |zip|
zip.each do |f|
if !File.directory?(f.name)
FileUtils.mkdir_p(File.dirname(f.name))
end
f.extract{true}
end
end rescue $log.error('安装更新出错'){file+$!.inspect+$!.backtrace.inspect}
Version.replace $2
File.delete file
@updated = true
end
end
if @updated
IO.popen('./mycard')
$scene = nil
end
@images = []
@thumbnails = []
@status = '正在检查更新'
@updated = false
Thread.new do
open(URL) do |file|
require 'json'
reply = file.read
$log.info('下载更新-服务器回传'){reply}
reply = JSON.parse(reply)
$log.info('下载更新-解析后'){reply.inspect}
reply.each do |fil|
name = File.basename fil
@status.replace "正在下载更新#{name}"
open(fil, 'rb') do |fi|
$log.info('下载完毕'){name}
@updated = true
open(name, 'wb') do |f|
f.write fi.read
end
end rescue $log.error('下载更新'){'下载更新失败'}
end
end rescue $log.error('检查更新'){'检查更新失败'}
if @updated
require_relative 'widget_msgbox'
Widget_Msgbox.new('mycard', '下载更新完毕,点击确定重新运行mycard并安装更新', :ok => "确定"){IO.popen('./mycard'); $scene = nil}
end
if File.file? "ygocore/cards.cdb"
require 'sqlite3'
db = SQLite3::Database.new( "ygocore/cards.cdb" )
db.execute( "select id from datas" ) do |row|
@thumbnails << row[0]
end
@images.replace @thumbnails
if !File.directory?('ygocore/pics/thumbnail')
FileUtils.mkdir_p('ygocore/pics/thumbnail')
end
existed_thumbnails = []
Dir.foreach("ygocore/pics/thumbnail") do |file|
if file =~ /(\d+)\.jpg/
existed_thumbnails << $1.to_i
end
end
@thumbnails -= existed_thumbnails
existed_images = []
Dir.foreach("ygocore/pics") do |file|
if file =~ /(\d+)\.jpg/
existed_images << $1.to_i
end
end
@images -= existed_images
existed_images = []
if (!@images.empty? or !@thumbnails.empty?) and File.file?("#{Card::PicPath}/1.jpg")
db_mycard = SQLite3::Database.new( "data/data.sqlite" )
db_mycard.execute( "select id, number from `yu-gi-oh` where number in (#{(@images+@thumbnails).uniq.collect{|number|"'%08d'" % number}.join(',')})" ) do |row|
id = row[0]
number = row[1].to_i
src = "#{Card::PicPath}/#{id}.jpg"
dest = "ygocore/pics/#{number}.jpg"
dest_thumb = "ygocore/pics/thumbnail/#{number}.jpg"
if File.file?(src)
@status.replace "检测到存在iDuel卡图 正在导入 #{id}.jpg"
existed_images << number
if !File.exist?(dest)
FileUtils.copy_file(src, dest)
FileUtils.copy_file(src, dest_thumb)
end
end
end
end
@images -= existed_images
@thumbnails -= existed_images
@thumbnails = (@thumbnails & @images) + (@thumbnails - @images)
unless @thumbnails.empty? and @images.empty?
$log.info('待下载的完整卡图'){@images.inspect}
$log.info('待下载的缩略卡图'){@thumbnails.inspect}
threads = 5.times.collect do
thread = Thread.new do
while number = @thumbnails.pop
@status.replace "正在下载缩略卡图 (剩余#{@thumbnails.size}张)"
open("http://my-card.in/images/cards/ygocore/thumbnail/#{number}.jpg", 'rb') do |remote|
next if File.file? "ygocore/pics/thumbnail/#{number}.jpg"
#$log.debug('下载缩略卡图'){"http://my-card.in/images/cards/ygocore/thumbnail/#{number}.jpg 到 ygocore/pics/thumbnail/#{number}.jpg" }
open("ygocore/pics/thumbnail/#{number}.jpg", 'wb') do |local|
local.write remote.read
end
end rescue $log.error('下载缩略出错'){"http://my-card.in/images/cards/ygocore/thumbnail/#{number}.jpg 到 ygocore/pics/thumbnail/#{number}.jpg" }
end
while number = @images.pop
@status.replace "正在下载完整卡图 (剩余#{@images.size}张)"
#$log.debug('下载完整卡图'){"http://my-card.in/images/cards/ygocore/#{number}.jpg 到 ygocore/pics/#{number}.jpg" }
open("http://my-card.in/images/cards/ygocore/#{number}.jpg", 'rb') do |remote|
next if File.file? "ygocore/pics/#{number}.jpg"
open("ygocore/pics/#{number}.jpg", 'wb') do |local|
local.write remote.read
end
end rescue $log.error('下载完整卡图出错'){"http://my-card.in/images/cards/ygocore/#{number}.jpg 到 ygocore/pics/#{number}.jpg" }
end
end
thread.priority = -1
thread
end
threads.each{|thread|thread.join}
end
end rescue $log.error('卡图更新'){'找不到ygocore卡片数据库'}
@status = nil
end.priority = -1
end
end
end
require 'open-uri'
require "fileutils"
require_relative 'card'
module Update
Version = '0.7.4'
URL = "http://my-card.in/mycard/update.json?version=#{Version}"
class <<self
attr_reader :thumbnails, :images, :status
def start
Dir.glob("mycard-update-*-*.zip") do |file|
file =~ /mycard-update-(.+?)-(.+?)\.zip/
if $1 <= Version and $2 > Version
$log.info('安装更新'){file}
WM::set_caption("MyCard - 正在更新 #{Version} -> #{$2}", "MyCard")
require 'zip/zip'
Zip::ZipFile::open(file) do |zip|
zip.each do |f|
if !File.directory?(f.name)
FileUtils.mkdir_p(File.dirname(f.name))
end
f.extract{true}
end
end rescue $log.error('安装更新出错'){file+$!.inspect+$!.backtrace.inspect}
Version.replace $2
File.delete file
@updated = true
end
end
if @updated
IO.popen('./mycard')
$scene = nil
end
@images = []
@thumbnails = []
@status = '正在检查更新'
@updated = false
Thread.new do
open(URL) do |file|
require 'json'
reply = file.read
$log.info('下载更新-服务器回传'){reply}
reply = JSON.parse(reply)
$log.info('下载更新-解析后'){reply.inspect}
reply.each do |fil|
name = File.basename fil
@status.replace "正在下载更新#{name}"
open(fil, 'rb') do |fi|
$log.info('下载完毕'){name}
@updated = true
open(name, 'wb') do |f|
f.write fi.read
end
end rescue $log.error('下载更新'){'下载更新失败'}
end
end rescue $log.error('检查更新'){'检查更新失败'}
if @updated
require_relative 'widget_msgbox'
Widget_Msgbox.new('mycard', '下载更新完毕,点击确定重新运行mycard并安装更新', :ok => "确定"){IO.popen('./mycard'); $scene = nil}
end
if File.file? "ygocore/cards.cdb"
require 'sqlite3'
db = SQLite3::Database.new( "ygocore/cards.cdb" )
db.execute( "select id from datas" ) do |row|
@thumbnails << row[0]
end
@images.replace @thumbnails
if !File.directory?('ygocore/pics/thumbnail')
FileUtils.mkdir_p('ygocore/pics/thumbnail')
end
existed_thumbnails = []
Dir.foreach("ygocore/pics/thumbnail") do |file|
if file =~ /(\d+)\.jpg/
existed_thumbnails << $1.to_i
end
end
@thumbnails -= existed_thumbnails
existed_images = []
Dir.foreach("ygocore/pics") do |file|
if file =~ /(\d+)\.jpg/
existed_images << $1.to_i
end
end
@images -= existed_images
existed_images = []
if (!@images.empty? or !@thumbnails.empty?) and File.file?("#{Card::PicPath}/1.jpg")
db_mycard = SQLite3::Database.new( "data/data.sqlite" )
db_mycard.execute( "select id, number from `yu-gi-oh` where number in (#{(@images+@thumbnails).uniq.collect{|number|"'%08d'" % number}.join(',')})" ) do |row|
id = row[0]
number = row[1].to_i
src = "#{Card::PicPath}/#{id}.jpg"
dest = "ygocore/pics/#{number}.jpg"
dest_thumb = "ygocore/pics/thumbnail/#{number}.jpg"
if File.file?(src)
@status.replace "检测到存在iDuel卡图 正在导入 #{id}.jpg"
existed_images << number
if !File.exist?(dest)
FileUtils.copy_file(src, dest)
FileUtils.copy_file(src, dest_thumb)
end
end
end
end
@images -= existed_images
@thumbnails -= existed_images
@thumbnails = (@thumbnails & @images) + (@thumbnails - @images)
unless @thumbnails.empty? and @images.empty?
$log.info('待下载的完整卡图'){@images.inspect}
$log.info('待下载的缩略卡图'){@thumbnails.inspect}
threads = 5.times.collect do
thread = Thread.new do
while number = @thumbnails.pop
@status.replace "正在下载缩略卡图 (剩余#{@thumbnails.size}张)"
open("http://my-card.in/images/cards/ygocore/thumbnail/#{number}.jpg", 'rb') do |remote|
next if File.file? "ygocore/pics/thumbnail/#{number}.jpg"
#$log.debug('下载缩略卡图'){"http://my-card.in/images/cards/ygocore/thumbnail/#{number}.jpg 到 ygocore/pics/thumbnail/#{number}.jpg" }
open("ygocore/pics/thumbnail/#{number}.jpg", 'wb') do |local|
local.write remote.read
end
end rescue $log.error('下载缩略出错'){"http://my-card.in/images/cards/ygocore/thumbnail/#{number}.jpg 到 ygocore/pics/thumbnail/#{number}.jpg" }
end
while number = @images.pop
@status.replace "正在下载完整卡图 (剩余#{@images.size}张)"
#$log.debug('下载完整卡图'){"http://my-card.in/images/cards/ygocore/#{number}.jpg 到 ygocore/pics/#{number}.jpg" }
open("http://my-card.in/images/cards/ygocore/#{number}.jpg", 'rb') do |remote|
next if File.file? "ygocore/pics/#{number}.jpg"
open("ygocore/pics/#{number}.jpg", 'wb') do |local|
local.write remote.read
end
end rescue $log.error('下载完整卡图出错'){"http://my-card.in/images/cards/ygocore/#{number}.jpg 到 ygocore/pics/#{number}.jpg" }
end
end
thread.priority = -1
thread
end
threads.each{|thread|thread.join}
end
end rescue $log.error('卡图更新'){'找不到ygocore卡片数据库'}
@status = nil
end.priority = -1
end
end
end
class Window
WLH = 24
attr_accessor :x, :y, :width, :height, :z, :contents, :visible, :viewport, :background
alias visible? visible
def initialize(x, y, width, height, z=200)
@x = x
@y = y
@z = z
@width = width
@height = height
@visible = true
#@angle = 0
@viewport = [0, 0, @width, @height]
@destroyed = false
amask = 0xff000000
rmask = 0x00ff0000
gmask = 0x0000ff00
bmask = 0x000000ff
#@background ||= Surface.new(SWSURFACE, @width, @height, 32, rmask, gmask, bmask, amask)
@contents ||= Surface.new(SWSURFACE, @width, @height, 32, rmask, gmask, bmask, amask)
#按Z坐标插入
unless $scene.windows.each_with_index do |window, index|
if window.z > @z
$scene.windows.insert(index, self)
break true
end
end == true
$scene.windows << self
end
end
def draw_stroked_text(text,x,y,size=1,font=@font,color=@color,color_stroke=@color_stroke)
[[x-size,y-size], [x-size,y], [x-size,y+size],
[x,y-size], [x,y+size],
[x+size,y-size], [x+size,y], [x+size,y+size],
].each{|pos|font.draw_blended_utf8(@contents, text, pos[0], pos[1], *color)}
font.draw_blended_utf8(@contents, text, x, y, *color_stroke)
end
def include?(x,y)
x >= @x && x < @x + @width && y >= @y && y < @y + @height
end
def destroy
@destroyed = true
@contents.destroy if @contents
$scene.windows.delete self if $scene
end
def destroyed?
@destroyed
end
def draw(screen)
return unless self.contents && self.visible? && !self.destroyed?
Surface.blit(self.contents, *self.viewport, screen, self.x, self.y)
end
def clear(x=0, y=0, width=@width, height=@height)
if @background
Surface.blit(@background,x,y,width,height,@contents,x,y)
elsif $scene and $scene.background
Surface.blit($scene.background,@x+x,@y+y,width,height,@contents,x,y)
else
@contents.fill_rect(x,y,width,height,0xFF000000)
end
end
def update
#子类定义
end
def refresh
#子类定义
end
def mousemoved(x,y)
#子类定义
end
def clicked
#子类定义
end
def mouseleftbuttonup
#子类定义
end
def lostfocus(active_window=nil)
#子类定义
end
def cursor_up(wrap=false)
#子类定义
end
def cursor_down(wrap=false)
#子类定义
end
def scroll_up
cursor_up
end
def scroll_down
cursor_down
end
class Window
WLH = 24
attr_accessor :x, :y, :width, :height, :z, :contents, :visible, :viewport, :background
alias visible? visible
def initialize(x, y, width, height, z=200)
@x = x
@y = y
@z = z
@width = width
@height = height
@visible = true
#@angle = 0
@viewport = [0, 0, @width, @height]
@destroyed = false
amask = 0xff000000
rmask = 0x00ff0000
gmask = 0x0000ff00
bmask = 0x000000ff
#@background ||= Surface.new(SWSURFACE, @width, @height, 32, rmask, gmask, bmask, amask)
@contents ||= Surface.new(SWSURFACE, @width, @height, 32, rmask, gmask, bmask, amask)
#按Z坐标插入
unless $scene.windows.each_with_index do |window, index|
if window.z > @z
$scene.windows.insert(index, self)
break true
end
end == true
$scene.windows << self
end
end
def draw_stroked_text(text,x,y,size=1,font=@font,color=@color,color_stroke=@color_stroke)
[[x-size,y-size], [x-size,y], [x-size,y+size],
[x,y-size], [x,y+size],
[x+size,y-size], [x+size,y], [x+size,y+size],
].each{|pos|font.draw_blended_utf8(@contents, text, pos[0], pos[1], *color)}
font.draw_blended_utf8(@contents, text, x, y, *color_stroke)
end
def include?(x,y)
x >= @x && x < @x + @width && y >= @y && y < @y + @height
end
def destroy
@destroyed = true
@contents.destroy if @contents
$scene.windows.delete self if $scene
end
def destroyed?
@destroyed
end
def draw(screen)
return unless self.contents && self.visible? && !self.destroyed?
Surface.blit(self.contents, *self.viewport, screen, self.x, self.y)
end
def clear(x=0, y=0, width=@width, height=@height)
if @background
Surface.blit(@background,x,y,width,height,@contents,x,y)
elsif $scene and $scene.background
Surface.blit($scene.background,@x+x,@y+y,width,height,@contents,x,y)
else
@contents.fill_rect(x,y,width,height,0xFF000000)
end
end
def update
#子类定义
end
def refresh
#子类定义
end
def mousemoved(x,y)
#子类定义
end
def clicked
#子类定义
end
def mouseleftbuttonup
#子类定义
end
def lostfocus(active_window=nil)
#子类定义
end
def cursor_up(wrap=false)
#子类定义
end
def cursor_down(wrap=false)
#子类定义
end
def scroll_up
cursor_up
end
def scroll_down
cursor_down
end
end
\ No newline at end of file
#==============================================================================
# ■ Scene_Title
#------------------------------------------------------------------------------
#  title
#==============================================================================
require_relative 'widget_scrollbar'
require_relative 'widget_inputbox'
require_relative 'chatmessage'
require_relative 'window_scrollable'
class Window_Chat < Window_Scrollable
WLH=16
def initialize(x, y, width, height)
super(x,y,width,height)
if @width > 600 #判断大厅还是房间,这个判据比较囧,待优化
@chat_background = Surface.load("graphics/system/chat.png").display_format
else
@chat_background = Surface.load("graphics/system/chat_room.png").display_format
end
@background = @contents.copy_rect(0,0,@contents.w,@contents.h) #new而已。。
@background.fill_rect(0,0,@background.w, @background.h, 0xFFb2cefe)
@background.put(@chat_background,0,31-4)
@tab = Surface.load "graphics/system/tab.png"
@chat_input = Widget_InputBox.new(@x+8, @y+@height-24-10, @width-14, 24) do |key|
case key
when :ENTER
if !@chat_input.value.empty?
chatmessage = ChatMessage.new($game.user, @chat_input.value, @channel)
$game.chat chatmessage
Game_Event.push Game_Event::Chat.new(chatmessage) if $game.show_chat_self
true
end
end
end
@chat_input.refresh
@font = TTF.open("fonts/wqy-microhei.ttc", 14)
@scrollbar = Widget_ScrollBar.new(self,@x+@width-20-8,@y+31+3,@height-68)
@page_size = (@height-68)/WLH
@@list ||= {}
@list_splited = {}
@@list.each_pair do |channel, chatmessages|
chatmessages.each do |chatmessage|
add_split(chatmessage)
end
end
@channels = []
self.channel = :lobby
end
def add(chatmessage)
@@list[chatmessage.channel] ||= []
unless @channels.include? chatmessage.channel
@channels << chatmessage.channel
refresh
end
@@list[chatmessage.channel] << chatmessage
scroll_bottom = @items.size - self.scroll <= @page_size
add_split(chatmessage)
if chatmessage.channel == @channel
@scroll = [@items.size - @page_size, 0].max if scroll_bottom
refresh
end
end
def add_split(chatmessage)
@list_splited[chatmessage.channel] ||= []
@list_splited[chatmessage.channel] << [chatmessage, ""]
width = name_width(chatmessage)
line = 0
chatmessage.message.each_char do |char|
if char == "\n"
line += 1
width = 0
@list_splited[chatmessage.channel] << [chatmessage.message_color, ""]
else
char_width = @font.text_size(char)[0]
if char_width + width > @width-14-20
line += 1
width = char_width
@list_splited[chatmessage.channel] << [chatmessage.message_color, char]
else
@list_splited[chatmessage.channel].last[1] << char
width += char_width
end
end
end
end
def mousemoved(x,y)
if y-@y < 31 and (x-@x) < @channels.size * 100
self.index = @channels[(x-@x) / 100]
else
self.index = nil
end
end
def clicked
case @index
when nil
when Integer
else
self.channel = @index
end
end
def channel=(channel)
return if @channel == channel
@channel = channel
@channels << channel unless @channels.include? channel
@list_splited[channel] ||= []
@items = @list_splited[channel]
@scroll = [@items.size - @page_size, 0].max
refresh
end
def draw_item(index, status=0)
case index
when nil
when Integer #描绘聊天消息
draw_item_chatmessage(index, status)
else #描绘频道标签
draw_item_channel(index, status)
end
end
def draw_item_channel(channel, status)
index = @channels.index(channel)
Surface.blit(@tab,0,@channel == channel ? 0 : 31,100,31,@contents,index*100+3,0)
channel_name = ChatMessage.channel_name channel
x = index*100+(100 - @font.text_size(channel_name)[0])/2
draw_stroked_text(channel_name,x,8,1,@font, [255,255,255], ChatMessage.channel_color(channel))
end
def draw_item_chatmessage(index, status)
x,y = item_rect_chatmessage(index)
chatmessage, message = @items[index]
if chatmessage.is_a? ChatMessage
@font.draw_blended_utf8(@contents, chatmessage.user.name+':', x, y, *chatmessage.name_color) if chatmessage.name_visible?
@font.draw_blended_utf8(@contents, message, x+name_width(chatmessage), y, *chatmessage.message_color) unless chatmessage.message.empty?
else
@font.draw_blended_utf8(@contents, message, x, y, *chatmessage) unless message.empty?
end
end
def item_rect(index)
case index
when nil
when Integer #描绘聊天消息
item_rect_chatmessage(index)
else #描绘频道标签
item_rect_channel(index)
end
end
def item_rect_channel(channel)
[@channels.index(channel)*100+3, 0, 100, 31]
end
def item_rect_chatmessage(index)
[8, (index-@scroll)*WLH+31+3, @width, self.class::WLH]
end
def refresh
super
@channels.each {|channel|draw_item_channel(channel, @index==channel)}
end
def name_width(chatmessage)
chatmessage.name_visible? ? @font.text_size(chatmessage.user.name+':')[0] : 0
end
def index_legal?(index)
case index
when nil,Integer
super
else
@channels.include? index
end
end
def scroll_up
self.scroll -= 1
end
def scroll_down
self.scroll += 1
end
def update
@chat_input.update
end
#==============================================================================
# ■ Scene_Title
#------------------------------------------------------------------------------
#  title
#==============================================================================
require_relative 'widget_scrollbar'
require_relative 'widget_inputbox'
require_relative 'chatmessage'
require_relative 'window_scrollable'
class Window_Chat < Window_Scrollable
WLH=16
def initialize(x, y, width, height)
super(x,y,width,height)
if @width > 600 #判断大厅还是房间,这个判据比较囧,待优化
@chat_background = Surface.load("graphics/system/chat.png").display_format
else
@chat_background = Surface.load("graphics/system/chat_room.png").display_format
end
@background = @contents.copy_rect(0,0,@contents.w,@contents.h) #new而已。。
@background.fill_rect(0,0,@background.w, @background.h, 0xFFb2cefe)
@background.put(@chat_background,0,31-4)
@tab = Surface.load "graphics/system/tab.png"
@chat_input = Widget_InputBox.new(@x+8, @y+@height-24-10, @width-14, 24) do |key|
case key
when :ENTER
if !@chat_input.value.empty?
chatmessage = ChatMessage.new($game.user, @chat_input.value, @channel)
$game.chat chatmessage
Game_Event.push Game_Event::Chat.new(chatmessage) if $game.show_chat_self
true
end
end
end
@chat_input.refresh
@font = TTF.open("fonts/wqy-microhei.ttc", 14)
@scrollbar = Widget_ScrollBar.new(self,@x+@width-20-8,@y+31+3,@height-68)
@page_size = (@height-68)/WLH
@@list ||= {}
@list_splited = {}
@@list.each_pair do |channel, chatmessages|
chatmessages.each do |chatmessage|
add_split(chatmessage)
end
end
@channels = []
self.channel = :lobby
end
def add(chatmessage)
@@list[chatmessage.channel] ||= []
unless @channels.include? chatmessage.channel
@channels << chatmessage.channel
refresh
end
@@list[chatmessage.channel] << chatmessage
scroll_bottom = @items.size - self.scroll <= @page_size
add_split(chatmessage)
if chatmessage.channel == @channel
@scroll = [@items.size - @page_size, 0].max if scroll_bottom
refresh
end
end
def add_split(chatmessage)
@list_splited[chatmessage.channel] ||= []
@list_splited[chatmessage.channel] << [chatmessage, ""]
width = name_width(chatmessage)
line = 0
chatmessage.message.each_char do |char|
if char == "\n"
line += 1
width = 0
@list_splited[chatmessage.channel] << [chatmessage.message_color, ""]
else
char_width = @font.text_size(char)[0]
if char_width + width > @width-14-20
line += 1
width = char_width
@list_splited[chatmessage.channel] << [chatmessage.message_color, char]
else
@list_splited[chatmessage.channel].last[1] << char
width += char_width
end
end
end
end
def mousemoved(x,y)
if y-@y < 31 and (x-@x) < @channels.size * 100
self.index = @channels[(x-@x) / 100]
else
self.index = nil
end
end
def clicked
case @index
when nil
when Integer
else
self.channel = @index
end
end
def channel=(channel)
return if @channel == channel
@channel = channel
@channels << channel unless @channels.include? channel
@list_splited[channel] ||= []
@items = @list_splited[channel]
@scroll = [@items.size - @page_size, 0].max
refresh
end
def draw_item(index, status=0)
case index
when nil
when Integer #描绘聊天消息
draw_item_chatmessage(index, status)
else #描绘频道标签
draw_item_channel(index, status)
end
end
def draw_item_channel(channel, status)
index = @channels.index(channel)
Surface.blit(@tab,0,@channel == channel ? 0 : 31,100,31,@contents,index*100+3,0)
channel_name = ChatMessage.channel_name channel
x = index*100+(100 - @font.text_size(channel_name)[0])/2
draw_stroked_text(channel_name,x,8,1,@font, [255,255,255], ChatMessage.channel_color(channel))
end
def draw_item_chatmessage(index, status)
x,y = item_rect_chatmessage(index)
chatmessage, message = @items[index]
if chatmessage.is_a? ChatMessage
@font.draw_blended_utf8(@contents, chatmessage.user.name+':', x, y, *chatmessage.name_color) if chatmessage.name_visible?
@font.draw_blended_utf8(@contents, message, x+name_width(chatmessage), y, *chatmessage.message_color) unless chatmessage.message.empty?
else
@font.draw_blended_utf8(@contents, message, x, y, *chatmessage) unless message.empty?
end
end
def item_rect(index)
case index
when nil
when Integer #描绘聊天消息
item_rect_chatmessage(index)
else #描绘频道标签
item_rect_channel(index)
end
end
def item_rect_channel(channel)
[@channels.index(channel)*100+3, 0, 100, 31]
end
def item_rect_chatmessage(index)
[8, (index-@scroll)*WLH+31+3, @width, self.class::WLH]
end
def refresh
super
@channels.each {|channel|draw_item_channel(channel, @index==channel)}
end
def name_width(chatmessage)
chatmessage.name_visible? ? @font.text_size(chatmessage.user.name+':')[0] : 0
end
def index_legal?(index)
case index
when nil,Integer
super
else
@channels.include? index
end
end
def scroll_up
self.scroll -= 1
end
def scroll_down
self.scroll += 1
end
def update
@chat_input.update
end
end
\ No newline at end of file
class Window_Config < Window
def initialize(x,y)
super(x,y,$screen.w, $screen.h)
@checkbox = Surface.load('graphics/system/checkbox.png')
@button = Surface.load('graphics/system/button.png')
@background = Surface.load('graphics/config/background.png').display_format
@contents = Surface.load('graphics/config/background.png').display_format
@font = TTF.open('fonts/wqy-microhei.ttc', 20)
@index = nil
@items = {
:fullscreen => [200,160,120,WLH],
:bgm => [200,160+WLH,120,WLH],
:avatar_cache => [200+220, 160+WLH*2,@button.w/3, @button.h],
:return => [200,160+WLH*3+10,100,WLH]
}
refresh
end
def draw_item(index, status=0)
case index
when :fullscreen
Surface.blit(@checkbox, 20*status, $config['screen']['fullscreen'] ? 20 : 0, 20, 20, @contents, @items[:fullscreen][0],@items[:fullscreen][1])
case status
when 0
@font.draw_blended_utf8(@contents, "全屏模式", @items[:fullscreen][0]+24, @items[:fullscreen][1], 0xFF,0xFF,0xFF)
when 1
@font.draw_shaded_utf8(@contents, "全屏模式", @items[:fullscreen][0]+24, @items[:fullscreen][1], 0xFF,0xFF,0xFF, 0x11, 0x11, 0x11)
when 2
@font.draw_shaded_utf8(@contents, "全屏模式", @items[:fullscreen][0]+24, @items[:fullscreen][1], 0x11,0x11,0x11, 0xFF, 0xFF, 0xFF)
end
when :bgm
Surface.blit(@checkbox, 20*status, $config['bgm'] ? 20 : 0, 20, 20, @contents, @items[:bgm][0], @items[:bgm][1])
case status
when 0
@font.draw_blended_utf8(@contents, "BGM", @items[:bgm][0]+24, @items[:bgm][1], 0xFF,0xFF,0xFF)
when 1
@font.draw_shaded_utf8(@contents, "BGM", @items[:bgm][0]+24, @items[:bgm][1], 0xFF,0xFF,0xFF, 0x11, 0x11, 0x11)
when 2
@font.draw_shaded_utf8(@contents, "BGM", @items[:bgm][0]+24, @items[:bgm][1], 0x11,0x11,0x11, 0xFF, 0xFF, 0xFF)
end
when :avatar_cache
size = 0
count = 0
Dir.glob("graphics/avatars/*_*.png") do |file|
count += 1
size += File.size(file)
end
@font.draw_blended_utf8(@contents, "头像缓存: #{count}个文件, #{filesize_inspect(size)}", 200, @items[:avatar_cache][1], 0xFF,0xFF,0xFF)
Surface.blit(@button, @button.w/3*status, 0, @button.w/3, @button.h, @contents, @items[:avatar_cache][0],@items[:avatar_cache][1])
@font.draw_blended_utf8(@contents, "清空", @items[:avatar_cache][0]+10, @items[:avatar_cache][1]+5, 0xFF,0xFF,0xFF)
when :return
@font.draw_blended_utf8(@contents, "回到标题画面", @items[:return][0],@items[:return][1], 0xFF,0xFF,0xFF)
end
end
def item_rect(index)
@items[index]
end
def index=(index)
return if index == @index
if @index
clear(*item_rect(@index))
draw_item(@index, 0)
end
if index.nil? or !@items.include? index
@index = nil
else
@index = index
clear(*item_rect(@index))
draw_item(@index, 1)
end
end
def mousemoved(x,y)
self.index = @items.each do |index, item_rect|
if x.between?(@x+item_rect[0], @x+item_rect[0]+item_rect[2]) and y.between?(@y+item_rect[1], @y+item_rect[1]+item_rect[3])
break index
end
end
end
def refresh
clear
@items.each_key{|index|draw_item(index)}
end
def clicked
case @index
when :fullscreen
clear(*item_rect(@index))
$config['screen']['fullscreen'] = !$config['screen']['fullscreen']
$screen.destroy
style = HWSURFACE
style |= FULLSCREEN if $config['screen']["fullscreen"]
$screen = Screen.open($config['screen']["width"], $config['screen']["height"], 0, style)
draw_item(@index, 1)
when :bgm
clear(*item_rect(@index))
$config['bgm'] = !$config['bgm']
if $config['bgm']
$scene = Scene_Config.new
else
$scene.last_bgm = nil
Mixer.fade_out_music(800) if SDL.inited_system(INIT_AUDIO) != 0
end
draw_item(@index, 1)
when :avatar_cache
#clear(*item_rect(@index))
Dir.glob("graphics/avatars/*_*.png") do |file|
File.delete file
end
refresh
#draw_item(:avatar_cache,1)
when :return
$scene = Scene_Title.new
end
Config.save
end
def filesize_inspect(size)
case size
when 0...1024
size.to_s + "B"
when 1024...1024*1024
(size/1024).to_s + "KB"
else
(size/1024/1024).to_s + "MB"
end
end
class Window_Config < Window
def initialize(x,y)
super(x,y,$screen.w, $screen.h)
@checkbox = Surface.load('graphics/system/checkbox.png')
@button = Surface.load('graphics/system/button.png')
@background = Surface.load('graphics/config/background.png').display_format
@contents = Surface.load('graphics/config/background.png').display_format
@font = TTF.open('fonts/wqy-microhei.ttc', 20)
@index = nil
@items = {
:fullscreen => [200,160,120,WLH],
:bgm => [200,160+WLH,120,WLH],
:avatar_cache => [200+220, 160+WLH*2,@button.w/3, @button.h],
:return => [200,160+WLH*3+10,100,WLH]
}
refresh
end
def draw_item(index, status=0)
case index
when :fullscreen
Surface.blit(@checkbox, 20*status, $config['screen']['fullscreen'] ? 20 : 0, 20, 20, @contents, @items[:fullscreen][0],@items[:fullscreen][1])
case status
when 0
@font.draw_blended_utf8(@contents, "全屏模式", @items[:fullscreen][0]+24, @items[:fullscreen][1], 0xFF,0xFF,0xFF)
when 1
@font.draw_shaded_utf8(@contents, "全屏模式", @items[:fullscreen][0]+24, @items[:fullscreen][1], 0xFF,0xFF,0xFF, 0x11, 0x11, 0x11)
when 2
@font.draw_shaded_utf8(@contents, "全屏模式", @items[:fullscreen][0]+24, @items[:fullscreen][1], 0x11,0x11,0x11, 0xFF, 0xFF, 0xFF)
end
when :bgm
Surface.blit(@checkbox, 20*status, $config['bgm'] ? 20 : 0, 20, 20, @contents, @items[:bgm][0], @items[:bgm][1])
case status
when 0
@font.draw_blended_utf8(@contents, "BGM", @items[:bgm][0]+24, @items[:bgm][1], 0xFF,0xFF,0xFF)
when 1
@font.draw_shaded_utf8(@contents, "BGM", @items[:bgm][0]+24, @items[:bgm][1], 0xFF,0xFF,0xFF, 0x11, 0x11, 0x11)
when 2
@font.draw_shaded_utf8(@contents, "BGM", @items[:bgm][0]+24, @items[:bgm][1], 0x11,0x11,0x11, 0xFF, 0xFF, 0xFF)
end
when :avatar_cache
size = 0
count = 0
Dir.glob("graphics/avatars/*_*.png") do |file|
count += 1
size += File.size(file)
end
@font.draw_blended_utf8(@contents, "头像缓存: #{count}个文件, #{filesize_inspect(size)}", 200, @items[:avatar_cache][1], 0xFF,0xFF,0xFF)
Surface.blit(@button, @button.w/3*status, 0, @button.w/3, @button.h, @contents, @items[:avatar_cache][0],@items[:avatar_cache][1])
@font.draw_blended_utf8(@contents, "清空", @items[:avatar_cache][0]+10, @items[:avatar_cache][1]+5, 0xFF,0xFF,0xFF)
when :return
@font.draw_blended_utf8(@contents, "回到标题画面", @items[:return][0],@items[:return][1], 0xFF,0xFF,0xFF)
end
end
def item_rect(index)
@items[index]
end
def index=(index)
return if index == @index
if @index
clear(*item_rect(@index))
draw_item(@index, 0)
end
if index.nil? or !@items.include? index
@index = nil
else
@index = index
clear(*item_rect(@index))
draw_item(@index, 1)
end
end
def mousemoved(x,y)
self.index = @items.each do |index, item_rect|
if x.between?(@x+item_rect[0], @x+item_rect[0]+item_rect[2]) and y.between?(@y+item_rect[1], @y+item_rect[1]+item_rect[3])
break index
end
end
end
def refresh
clear
@items.each_key{|index|draw_item(index)}
end
def clicked
case @index
when :fullscreen
clear(*item_rect(@index))
$config['screen']['fullscreen'] = !$config['screen']['fullscreen']
$screen.destroy
style = HWSURFACE
style |= FULLSCREEN if $config['screen']["fullscreen"]
$screen = Screen.open($config['screen']["width"], $config['screen']["height"], 0, style)
draw_item(@index, 1)
when :bgm
clear(*item_rect(@index))
$config['bgm'] = !$config['bgm']
if $config['bgm']
$scene = Scene_Config.new
else
$scene.last_bgm = nil
Mixer.fade_out_music(800) if SDL.inited_system(INIT_AUDIO) != 0
end
draw_item(@index, 1)
when :avatar_cache
#clear(*item_rect(@index))
Dir.glob("graphics/avatars/*_*.png") do |file|
File.delete file
end
refresh
#draw_item(:avatar_cache,1)
when :return
$scene = Scene_Title.new
end
Config.save
end
def filesize_inspect(size)
case size
when 0...1024
size.to_s + "B"
when 1024...1024*1024
(size/1024).to_s + "KB"
else
(size/1024/1024).to_s + "MB"
end
end
end
\ No newline at end of file
class Window_Deck < Window
attr_reader :index
def initialize
@items = Dir.glob("ygocore/deck/*.ydk")[0, 10]
p @items
@background = Surface.load(@items.size > 4 ? 'graphics/lobby/host.png' : 'graphics/system/msgbox.png').display_format
super((1024-@background.w)/2, 230, @background.w, @background.h, 300)
@items_button = Surface.load("graphics/system/deck_buttons.png")
@items_buttons = {edit: "编辑", delete: "删除", export: "导出"}
button_y = @height - 36
@button = Surface.load("graphics/system/button.png")
@buttons = {import: "导入", edit: "编辑", close: "关闭"}
space = (@width - @buttons.size * @button.w / 3) / (@buttons.size + 1)
@buttons_pos = {}
@buttons.each_with_index do |button, index|
@buttons_pos[button[0]] = [(space+@button.w/3)*index+space, button_y, @button.w/3, @button.h]
end
@font = TTF.open("fonts/wqy-microhei.ttc", 16)
@title_color = [0xFF, 0xFF, 0xFF]
@color = [0x04, 0x47, 0x7c]
refresh
end
def refresh
clear
@font.draw_blended_utf8(@contents, "卡组编辑", (@width-@font.text_size("卡组编辑")[0])/2, 2, *@title_color)
@items = Dir.glob("ygocore/deck/*.ydk")[0, 10]
@background = Surface.load(@items.size > 4 ? 'graphics/lobby/host.png' : 'graphics/system/msgbox.png').display_format
@height = @background.h
@items.each_with_index do |deck, index|
@font.draw_blended_utf8(@contents, File.basename(deck, ".ydk"), 16, 28+WLH*index, *@color)
end
@items.size.times do |index|
@items_buttons.each_key do |key|
draw_item([index, key], self.index==[index, key] ? 1 : 0)
end
end
@buttons.each_key do |index|
draw_item(index, self.index==index ? 1 : 0)
end
end
def draw_item(index, status=0)
x, y=item_rect(index)
if index.is_a? Array
Surface.blit(@items_button, status*@items_button.w/3, @items_buttons.keys.index(index[1])*@items_button.h/3, @items_button.w/3, @items_button.h/3, @contents, x, y)
else
Surface.blit(@button, @button.w/3*status, 0, @button.w/3, @button.h, @contents, x, y)
text_size = @font.text_size(@buttons[index])
@font.draw_blended_utf8(@contents, @buttons[index], x+(@button.w/3-text_size[0])/2, y+(@button.h-text_size[1])/2, 0xFF, 0xFF, 0xFF)
end
end
def mousemoved(x, y)
new_index = nil
line = (y-@y-28)/WLH
if line.between?(0, @items.size-1)
i = (x - @x - (@width - @items_buttons.size * @items_button.w / 3)) / (@items_button.w/3)
if i >= 0
new_index = [line, @items_buttons.keys[i]]
else
new_index = [line, :edit]
end
else
@buttons_pos.each_key do |index|
if (x - @x).between?(@buttons_pos[index][0], @buttons_pos[index][0]+@buttons_pos[index][2]) and (y-@y).between?(@buttons_pos[index][1], @buttons_pos[index][1]+@buttons_pos[index][3])
new_index = index
break
end
end
end
self.index = new_index
end
def item_rect(index)
if index.is_a? Array
[
@width - (@items_button.w/3) * (@items_buttons.keys.reverse.index(index[1])+1),
28+WLH*index[0],
@items_button.w/3,
@items_button.h/3
]
else
@buttons_pos[index]
end
end
def index=(index)
return if index == @index
if @index
clear(*item_rect(@index))
draw_item(@index, 0)
end
@index = index
if @index
clear(*item_rect(@index))
draw_item(@index, 1)
end
end
def clicked
case self.index
when :import
import
refresh
when :edit
Ygocore.run_ygocore(:deck)
when :close
destroy
when Array
case index[1]
when :edit
Ygocore.run_ygocore(File.basename(@items[index[0]], ".ydk"))
when :delete
require_relative 'widget_msgbox'
Widget_Msgbox.new("删除卡组", "确定要删除卡组 #{File.basename(@items[index[0]], '.ydk')} 吗", buttons={ok: "确定", cancel: "取消"}) do |clicked|
if clicked == :ok
File.delete @items[index[0]]
refresh
end
end
when :export
export
end
end
end
def import
file = Dialog.get_open_file("导入卡组", "所有支持的卡组 (*.ydk;*.txt;*.deck)" => "*.ydk;*.txt;*.deck", "ygocore卡组 (*.ydk)" => "*.ydk", "OcgSoft卡组 (*.txt;*.deck)" => "*.txt;*.deck")
if !file.empty?
#fix for stdlib File.extname
file =~ /(\.deck|\.txt|\.ydk)$/i
extname = $1
Dir.mkdir "ygocore/deck" unless File.directory?("ygocore/deck")
open("ygocore/deck/#{File.basename(file, extname)+".ydk"}", 'w') do |dest|
if file =~ /(\.deck|\.txt)$/i
deck = Deck.load(file)
dest.puts("#main")
deck.main.each { |card| dest.puts card.number }
dest.puts("#extra")
deck.extra.each { |card| dest.puts card.number }
dest.puts("!side")
deck.side.each { |card| dest.puts card.number }
else
open(file) do |src|
dest.write src.read
end
end
end rescue ($log.error($!.inspect) { $!.backtrace.inspect }; Widget_Msgbox.new("导入卡组", "导入卡组失败", :ok => "确定"))
end
end
def export
require_relative 'dialog'
file = Dialog.get_open_file("导出卡组", {"ygocore卡组 (*.ydk)" => "*.ydk", "OcgSoft卡组 (*.txt)" => "*.txt"}, [".ydk", ".txt"])
if !file.empty?
@items[index[0]]
open(@items[index[0]]) do |src|
if file =~ /.txt$/i
main = []
extra = []
side = []
now_side = false
src.readlines.each do |line|
line.chomp!
if line[0, 1] == "#"
next
elsif line[0, 5] == "!side"
now_side = true
else
card = Card.find("number = '#{line.rjust(8, '0')}'")[0]
next if card.nil?
if now_side
side << card
elsif card.extra?
extra << card
else
main << card
end
end
end
open(file, 'w:GBK') do |dest|
main.each { |card| dest.puts "[#{card.name}]##" }
dest.puts "####"
side.each { |card| dest.puts "[#{card.name}]##" }
dest.puts "===="
extra.each { |card| dest.puts "[#{card.name}]##" }
end
else
open(file, 'w') do |dest|
dest.write src.read
end
end
end
end
end
class Window_Deck < Window
attr_reader :index
def initialize
@items = Dir.glob("ygocore/deck/*.ydk")[0, 10]
p @items
@background = Surface.load(@items.size > 4 ? 'graphics/lobby/host.png' : 'graphics/system/msgbox.png').display_format
super((1024-@background.w)/2, 230, @background.w, @background.h, 300)
@items_button = Surface.load("graphics/system/deck_buttons.png")
@items_buttons = {edit: "编辑", delete: "删除", export: "导出"}
button_y = @height - 36
@button = Surface.load("graphics/system/button.png")
@buttons = {import: "导入", edit: "编辑", close: "关闭"}
space = (@width - @buttons.size * @button.w / 3) / (@buttons.size + 1)
@buttons_pos = {}
@buttons.each_with_index do |button, index|
@buttons_pos[button[0]] = [(space+@button.w/3)*index+space, button_y, @button.w/3, @button.h]
end
@font = TTF.open("fonts/wqy-microhei.ttc", 16)
@title_color = [0xFF, 0xFF, 0xFF]
@color = [0x04, 0x47, 0x7c]
refresh
end
def refresh
clear
@font.draw_blended_utf8(@contents, "卡组编辑", (@width-@font.text_size("卡组编辑")[0])/2, 2, *@title_color)
@items = Dir.glob("ygocore/deck/*.ydk")[0, 10]
@background = Surface.load(@items.size > 4 ? 'graphics/lobby/host.png' : 'graphics/system/msgbox.png').display_format
@height = @background.h
@items.each_with_index do |deck, index|
@font.draw_blended_utf8(@contents, File.basename(deck, ".ydk"), 16, 28+WLH*index, *@color)
end
@items.size.times do |index|
@items_buttons.each_key do |key|
draw_item([index, key], self.index==[index, key] ? 1 : 0)
end
end
@buttons.each_key do |index|
draw_item(index, self.index==index ? 1 : 0)
end
end
def draw_item(index, status=0)
x, y=item_rect(index)
if index.is_a? Array
Surface.blit(@items_button, status*@items_button.w/3, @items_buttons.keys.index(index[1])*@items_button.h/3, @items_button.w/3, @items_button.h/3, @contents, x, y)
else
Surface.blit(@button, @button.w/3*status, 0, @button.w/3, @button.h, @contents, x, y)
text_size = @font.text_size(@buttons[index])
@font.draw_blended_utf8(@contents, @buttons[index], x+(@button.w/3-text_size[0])/2, y+(@button.h-text_size[1])/2, 0xFF, 0xFF, 0xFF)
end
end
def mousemoved(x, y)
new_index = nil
line = (y-@y-28)/WLH
if line.between?(0, @items.size-1)
i = (x - @x - (@width - @items_buttons.size * @items_button.w / 3)) / (@items_button.w/3)
if i >= 0
new_index = [line, @items_buttons.keys[i]]
else
new_index = [line, :edit]
end
else
@buttons_pos.each_key do |index|
if (x - @x).between?(@buttons_pos[index][0], @buttons_pos[index][0]+@buttons_pos[index][2]) and (y-@y).between?(@buttons_pos[index][1], @buttons_pos[index][1]+@buttons_pos[index][3])
new_index = index
break
end
end
end
self.index = new_index
end
def item_rect(index)
if index.is_a? Array
[
@width - (@items_button.w/3) * (@items_buttons.keys.reverse.index(index[1])+1),
28+WLH*index[0],
@items_button.w/3,
@items_button.h/3
]
else
@buttons_pos[index]
end
end
def index=(index)
return if index == @index
if @index
clear(*item_rect(@index))
draw_item(@index, 0)
end
@index = index
if @index
clear(*item_rect(@index))
draw_item(@index, 1)
end
end
def clicked
case self.index
when :import
import
refresh
when :edit
Ygocore.run_ygocore(:deck)
when :close
destroy
when Array
case index[1]
when :edit
Ygocore.run_ygocore(File.basename(@items[index[0]], ".ydk"))
when :delete
require_relative 'widget_msgbox'
Widget_Msgbox.new("删除卡组", "确定要删除卡组 #{File.basename(@items[index[0]], '.ydk')} 吗", buttons={ok: "确定", cancel: "取消"}) do |clicked|
if clicked == :ok
File.delete @items[index[0]]
refresh
end
end
when :export
export
end
end
end
def import
file = Dialog.get_open_file("导入卡组", "所有支持的卡组 (*.ydk;*.txt;*.deck)" => "*.ydk;*.txt;*.deck", "ygocore卡组 (*.ydk)" => "*.ydk", "OcgSoft卡组 (*.txt;*.deck)" => "*.txt;*.deck")
if !file.empty?
#fix for stdlib File.extname
file =~ /(\.deck|\.txt|\.ydk)$/i
extname = $1
Dir.mkdir "ygocore/deck" unless File.directory?("ygocore/deck")
open("ygocore/deck/#{File.basename(file, extname)+".ydk"}", 'w') do |dest|
if file =~ /(\.deck|\.txt)$/i
deck = Deck.load(file)
dest.puts("#main")
deck.main.each { |card| dest.puts card.number }
dest.puts("#extra")
deck.extra.each { |card| dest.puts card.number }
dest.puts("!side")
deck.side.each { |card| dest.puts card.number }
else
open(file) do |src|
dest.write src.read
end
end
end rescue ($log.error($!.inspect) { $!.backtrace.inspect }; Widget_Msgbox.new("导入卡组", "导入卡组失败", :ok => "确定"))
end
end
def export
require_relative 'dialog'
file = Dialog.get_open_file("导出卡组", {"ygocore卡组 (*.ydk)" => "*.ydk", "OcgSoft卡组 (*.txt)" => "*.txt"}, [".ydk", ".txt"])
if !file.empty?
@items[index[0]]
open(@items[index[0]]) do |src|
if file =~ /.txt$/i
main = []
extra = []
side = []
now_side = false
src.readlines.each do |line|
line.chomp!
if line[0, 1] == "#"
next
elsif line[0, 5] == "!side"
now_side = true
else
card = Card.find("number = '#{line.rjust(8, '0')}'")[0]
next if card.nil?
if now_side
side << card
elsif card.extra?
extra << card
else
main << card
end
end
end
open(file, 'w:GBK') do |dest|
main.each { |card| dest.puts "[#{card.name}]##" }
dest.puts "####"
side.each { |card| dest.puts "[#{card.name}]##" }
dest.puts "===="
extra.each { |card| dest.puts "[#{card.name}]##" }
end
else
open(file, 'w') do |dest|
dest.write src.read
end
end
end
end
end
end
\ No newline at end of file
require_relative 'window_host'
class Window_LobbyButtons < Window_List
def initialize(x, y)
@items = ["常见问题", "卡组编辑", "建立房间"]
@button = Surface.load("graphics/lobby/button.png")
super(x, y, @items.size*@button.w/3+@items.size*4, 30)
@font = TTF.open("fonts/wqy-microhei.ttc", 15)
refresh
end
def draw_item(index, status=0)
x, y=item_rect(index)
Surface.blit(@button, status*@button.w/3, 0, @button.w/3, @button.h, @contents, x, y)
draw_stroked_text(@items[index], x+8, y+3, 2, @font, [0xdf, 0xf1, 0xff], [0x27, 0x43, 0x59])
end
def item_rect(index)
[index*@button.w/3+(index)*4, 0, @button.w/3, @height]
end
def mousemoved(x, y)
if (x-@x) % (@button.w/3+4) >= @button.w/3
self.index = nil
else
self.index = (x-@x)/(@button.w/3+4)
end
end
def lostfocus(active_window = nil)
self.index = nil
end
def clicked
case @index
when 0 #常见问题
require_relative 'dialog'
Dialog.web "http://my-card.in/login?user[name]=#{CGI.escape $game.user.name}&user[password]=#{CGI.escape $game.password}&continue=/topics/1453"
when 1 #卡组编辑
require_relative 'deck'
$game.class.deck_edit
when 2 #建立房间
@host_window = Window_Host.new(300, 200)
end
end
def update
@host_window.update if @host_window and !@host_window.destroyed?
end
end
require_relative 'window_host'
class Window_LobbyButtons < Window_List
def initialize(x, y)
@items = ["常见问题", "卡组编辑", "建立房间"]
@button = Surface.load("graphics/lobby/button.png")
super(x, y, @items.size*@button.w/3+@items.size*4, 30)
@font = TTF.open("fonts/wqy-microhei.ttc", 15)
refresh
end
def draw_item(index, status=0)
x, y=item_rect(index)
Surface.blit(@button, status*@button.w/3, 0, @button.w/3, @button.h, @contents, x, y)
draw_stroked_text(@items[index], x+8, y+3, 2, @font, [0xdf, 0xf1, 0xff], [0x27, 0x43, 0x59])
end
def item_rect(index)
[index*@button.w/3+(index)*4, 0, @button.w/3, @height]
end
def mousemoved(x, y)
if (x-@x) % (@button.w/3+4) >= @button.w/3
self.index = nil
else
self.index = (x-@x)/(@button.w/3+4)
end
end
def lostfocus(active_window = nil)
self.index = nil
end
def clicked
case @index
when 0 #常见问题
require_relative 'dialog'
Dialog.web "http://my-card.in/login?user[name]=#{CGI.escape $game.user.name}&user[password]=#{CGI.escape $game.password}&continue=/topics/1453"
when 1 #卡组编辑
require_relative 'deck'
$game.class.deck_edit
when 2 #建立房间
@host_window = Window_Host.new(300, 200)
end
end
def update
@host_window.update if @host_window and !@host_window.destroyed?
end
end
#encoding: UTF-8
#==============================================================================
# ■ Window_Roomitems
#------------------------------------------------------------------------------
#  大厅内房间列表
#==============================================================================
require_relative 'window_scrollable'
require_relative 'window_join'
class Window_RoomList < Window_Scrollable
attr_reader :items
WLH = 48
def initialize(x, y, items)
@button = Surface.load('graphics/lobby/room.png')
@button.set_alpha(RLEACCEL, 255)
#@background = Surface.load 'graphics/lobby/roomitems.png'
#@contents = Surface.load 'graphics/lobby/roomitems.png'
super(x,y,@button.w / 3, ($config['screen']['height'] - 288) / 48 * 48)
@item_max = 0
@font = TTF.open("fonts/wqy-microhei.ttc", 16)
@color = [0x03, 0x11, 0x22]
@scrollbar = Widget_ScrollBar.new(self,@x+@width,@y,@height)
self.items = items
end
def draw_item(index, status=0)
y = item_rect(index)[1]
room = @items[index]
Surface.blit(@button, @width*status, room.full? ? WLH : 0, @width, WLH, @contents, 0, y)
@font.draw_blended_utf8(@contents, room.id.to_s, 24, y+8, *@color)
@font.draw_blended_utf8(@contents, room.full? ? "【决斗中】" : room.private? ? "【私密房】" : "【等待中】", 8, y+24, *@color)
@font.draw_blended_utf8(@contents, room.name, 128, y+8, *room.color) unless room.name.empty? or room.name.size > 100
$log.error('标题过长') {room.name} if room.name.size > 100
@font.draw_blended_utf8(@contents, room.player1.name, 128, y+24, *room.player1.color) if room.player1 and !room.player1.name.empty?
@font.draw_blended_utf8(@contents, room.player2.name, 320, y+24, *room.player2.color) if room.player2 and !room.player2.name.empty?
room.extra.each_with_index do |extra, index|
str, color = extra
@font.draw_blended_utf8(@contents, str, 300+index*96, y+8, *color)
end
end
def update
@join_window.update if @join_window and !@join_window.destroyed?
end
def mousemoved(x,y)
return unless self.include?(x,y)
self.index = (y - @y) / WLH + @scroll
end
def clicked
return unless @index and room = @items[@index]
if room.full?
@joinroom_msgbox = Widget_Msgbox.new("加入房间", "正在加入观战")
$game.watch room
else
if room.private
@join_window = Window_Join.new(0,0,room)
else
@joinroom_msgbox = Widget_Msgbox.new("加入房间", "正在加入房间")
$game.join room
end
end
end
#encoding: UTF-8
#==============================================================================
# ■ Window_Roomitems
#------------------------------------------------------------------------------
#  大厅内房间列表
#==============================================================================
require_relative 'window_scrollable'
require_relative 'window_join'
class Window_RoomList < Window_Scrollable
attr_reader :items
WLH = 48
def initialize(x, y, items)
@button = Surface.load('graphics/lobby/room.png')
@button.set_alpha(RLEACCEL, 255)
#@background = Surface.load 'graphics/lobby/roomitems.png'
#@contents = Surface.load 'graphics/lobby/roomitems.png'
super(x,y,@button.w / 3, ($config['screen']['height'] - 288) / 48 * 48)
@item_max = 0
@font = TTF.open("fonts/wqy-microhei.ttc", 16)
@color = [0x03, 0x11, 0x22]
@scrollbar = Widget_ScrollBar.new(self,@x+@width,@y,@height)
self.items = items
end
def draw_item(index, status=0)
y = item_rect(index)[1]
room = @items[index]
Surface.blit(@button, @width*status, room.full? ? WLH : 0, @width, WLH, @contents, 0, y)
@font.draw_blended_utf8(@contents, room.id.to_s, 24, y+8, *@color)
@font.draw_blended_utf8(@contents, room.full? ? "【决斗中】" : room.private? ? "【私密房】" : "【等待中】", 8, y+24, *@color)
@font.draw_blended_utf8(@contents, room.name, 128, y+8, *room.color) unless room.name.empty? or room.name.size > 100
$log.error('标题过长') {room.name} if room.name.size > 100
@font.draw_blended_utf8(@contents, room.player1.name, 128, y+24, *room.player1.color) if room.player1 and !room.player1.name.empty?
@font.draw_blended_utf8(@contents, room.player2.name, 320, y+24, *room.player2.color) if room.player2 and !room.player2.name.empty?
room.extra.each_with_index do |extra, index|
str, color = extra
@font.draw_blended_utf8(@contents, str, 300+index*96, y+8, *color)
end
end
def update
@join_window.update if @join_window and !@join_window.destroyed?
end
def mousemoved(x,y)
return unless self.include?(x,y)
self.index = (y - @y) / WLH + @scroll
end
def clicked
return unless @index and room = @items[@index]
if room.full?
@joinroom_msgbox = Widget_Msgbox.new("加入房间", "正在加入观战")
$game.watch room
else
if room.private
@join_window = Window_Join.new(0,0,room)
else
@joinroom_msgbox = Widget_Msgbox.new("加入房间", "正在加入房间")
$game.join room
end
end
end
end
\ No newline at end of file
require_relative 'window_list'
class Window_Title < Window_List
Button_Count = 5
WLH = 50
attr_reader :x, :y, :width, :height, :single_height, :index
def initialize(x,y)
@button = Surface.load("graphics/system/titlebuttons.png")
@button.set_alpha(RLEACCEL,255)
@single_height = @button.h / Button_Count
super(x,y,@button.w / 3,WLH * Button_Count - (WLH - @button.h / Button_Count))
@cursor_se = Mixer::Wave.load 'audio/se/cursor.ogg' if SDL.inited_system(INIT_AUDIO) != 0
self.items = [:决斗开始, :单人模式, :卡组编成, :选项设置, :退出游戏]
end
def index=(index)
if index and @index != index
Mixer.play_channel(-1,@cursor_se,0) if SDL.inited_system(INIT_AUDIO) != 0
end
super
end
def mousemoved(x,y)
self.index = (y - @y) / WLH
end
def draw_item(index, status=0)
Surface.blit(@button, @width*status, @single_height*index, @width, @single_height, @contents, 0, WLH*index)
end
def clicked
$scene.determine if $scene.is_a? Scene_Title
end
def clear(x=0,y=0,width=@width,height=@height)
@contents.fill_rect(x,y,width, height, 0x00000000)
end
require_relative 'window_list'
class Window_Title < Window_List
Button_Count = 5
WLH = 50
attr_reader :x, :y, :width, :height, :single_height, :index
def initialize(x,y)
@button = Surface.load("graphics/system/titlebuttons.png")
@button.set_alpha(RLEACCEL,255)
@single_height = @button.h / Button_Count
super(x,y,@button.w / 3,WLH * Button_Count - (WLH - @button.h / Button_Count))
@cursor_se = Mixer::Wave.load 'audio/se/cursor.ogg' if SDL.inited_system(INIT_AUDIO) != 0
self.items = [:决斗开始, :单人模式, :卡组编成, :选项设置, :退出游戏]
end
def index=(index)
if index and @index != index
Mixer.play_channel(-1,@cursor_se,0) if SDL.inited_system(INIT_AUDIO) != 0
end
super
end
def mousemoved(x,y)
self.index = (y - @y) / WLH
end
def draw_item(index, status=0)
Surface.blit(@button, @width*status, @single_height*index, @width, @single_height, @contents, 0, WLH*index)
end
def clicked
$scene.determine if $scene.is_a? Scene_Title
end
def clear(x=0,y=0,width=@width,height=@height)
@contents.fill_rect(x,y,width, height, 0x00000000)
end
end
\ No newline at end of file
#encoding: UTF-8
#==============================================================================
# Window_UserInfo
#------------------------------------------------------------------------------
# 游戏大厅显示用户信息的类
#==============================================================================
class Window_UserInfo < Window
def initialize(x, y, user)
@avatar_boarder = Surface.load("graphics/lobby/avatar_boader.png")
super(x,y,280,144)
@font = TTF.open('fonts/wqy-microhei.ttc', 16)
@user = user
@background = Surface.load("graphics/lobby/userinfo.png").display_format
refresh
end
def refresh
@contents.put(@background, 0, 0)
@thread = @user.avatar(:middle) do |avatar|
clear(0,0,@avatar_boarder.w, @avatar_boarder.h)
@contents.put(avatar, 12, 12)
@contents.put(@avatar_boarder, 0, 0)
end
@font.draw_blended_utf8(@contents, @user.name, 160, 12, 0x00,0x00,0x00) unless @user.name.empty?
@font.draw_blended_utf8(@contents, "id: #{@user.id}" , 160, 12+16*2, 0x00,0x00,0x00)
@font.draw_blended_utf8(@contents, "Lv: #{@user.level}" , 160, 12+16*3, 0x00,0x00,0x00) if @user.respond_to? :level and @user.level #TODO:规范化,level是iduel专属的,但是又不太想让iduel来重定义这个window
@font.draw_blended_utf8(@contents, "经验: #{@user.exp}", 160, 12+16*4, 0x00,0x00,0x00) if @user.respond_to? :exp and @user.exp
end
def dispose
@thread.exit
super
end
end
#encoding: UTF-8
#==============================================================================
# Window_UserInfo
#------------------------------------------------------------------------------
# 游戏大厅显示用户信息的类
#==============================================================================
class Window_UserInfo < Window
def initialize(x, y, user)
@avatar_boarder = Surface.load("graphics/lobby/avatar_boader.png")
super(x,y,280,144)
@font = TTF.open('fonts/wqy-microhei.ttc', 16)
@user = user
@background = Surface.load("graphics/lobby/userinfo.png").display_format
refresh
end
def refresh
@contents.put(@background, 0, 0)
@thread = @user.avatar(:middle) do |avatar|
clear(0,0,@avatar_boarder.w, @avatar_boarder.h)
@contents.put(avatar, 12, 12)
@contents.put(@avatar_boarder, 0, 0)
end
@font.draw_blended_utf8(@contents, @user.name, 160, 12, 0x00,0x00,0x00) unless @user.name.empty?
@font.draw_blended_utf8(@contents, "id: #{@user.id}" , 160, 12+16*2, 0x00,0x00,0x00)
@font.draw_blended_utf8(@contents, "Lv: #{@user.level}" , 160, 12+16*3, 0x00,0x00,0x00) if @user.respond_to? :level and @user.level #TODO:规范化,level是iduel专属的,但是又不太想让iduel来重定义这个window
@font.draw_blended_utf8(@contents, "经验: #{@user.exp}", 160, 12+16*4, 0x00,0x00,0x00) if @user.respond_to? :exp and @user.exp
end
def dispose
@thread.exit
super
end
end
#encoding: UTF-8
load 'lib/ygocore/window_login.rb'
require 'eventmachine'
require 'open-uri'
require 'yaml'
class Ygocore < Game
attr_reader :username
attr_accessor :password
@@config = YAML.load_file("lib/ygocore/server.yml")
def initialize
super
load 'lib/ygocore/event.rb'
load 'lib/ygocore/user.rb'
load 'lib/ygocore/room.rb'
load 'lib/ygocore/scene_lobby.rb'
require 'json'
require 'xmpp4r/client'
require 'xmpp4r/muc'
end
def refresh_interval
60
end
def login(username, password)
@username = username
@password = password
@nickname_conflict = []
@@im = Jabber::Client.new(Jabber::JID::new(@username, 'my-card.in', 'mycard'))
@@im_room = Jabber::MUC::MUCClient.new(@@im)
#Jabber.debug = true
@@im.on_exception do |exception, c, where|
$log.error('聊天出错') { [exception, c, where] }
if where == :close
Game_Event.push(Game_Event::Chat.new(ChatMessage.new(User.new(:system, 'System'), '聊天连接断开, 可能是网络问题或帐号从其他地点登录')))
else
Game_Event.push(Game_Event::Chat.new(ChatMessage.new(User.new(:system, 'System'), '聊天连接断开, 5秒后重新连接')))
sleep 5
im_connect
end
end
@@im_room.add_message_callback do |m|
user = m.from.resource == nickname ? @user : User.new(m.from.resource.to_sym, m.from.resource)
Game_Event.push Game_Event::Chat.new ChatMessage.new(user, m.body, :lobby) rescue $log.error('收到聊天消息') { $! }
end
@@im_room.add_private_message_callback do |m|
if m.body #忽略无消息的正在输入等内容
user = m.from.resource == nickname ? @user : User.new(m.from.resource.to_sym, m.from.resource)
Game_Event.push Game_Event::Chat.new ChatMessage.new(user, m.body, user) rescue $log.error('收到私聊消息') { $! }
end
end
@@im_room.add_join_callback do |m|
Game_Event.push Game_Event::NewUser.new User.new m.from.resource.to_sym, m.from.resource
end
@@im_room.add_leave_callback do |m|
Game_Event.push Game_Event::MissingUser.new User.new m.from.resource.to_sym, m.from.resource
end
connect
im_connect
end
def nickname
return @nickname if @nickname
if @nickname_conflict.include? @username
1.upto(9) do |i|
result = "#{@username}-#{i}"
return result unless @nickname_conflict.include? result
end
raise 'can`t get available nickname'
else
@username
end
end
def connect
@recv = Thread.new do
EventMachine::run {
EventMachine::connect "bbs.66rpg.com", 9998, Client
}
end
end
def im_connect
Thread.new {
begin
@@im.allow_tls = false
@@im.use_ssl = true
@@im.connect('my-card.in', 5223)
#ruby19/windows下 使用tls连接时会卡住
@@im.auth(@password)
@@im.send(Jabber::Presence.new.set_type(:available))
begin
nickname = nickname()
@@im_room.join(Jabber::JID.new('lobby@conference.my-card.in/' + nickname))
rescue Jabber::ServerError => exception
if exception.error.error == 'conflict'
@nickname_conflict << nickname
retry
end
end
Game_Event.push Game_Event::AllUsers.new @@im_room.roster.keys.collect { |nick| User.new(nick.to_sym, nick) } rescue p $!
rescue StandardError => exception
$log.error('聊天连接出错') { exception }
Game_Event.push(Game_Event::Chat.new(ChatMessage.new(User.new(:system, 'System'), '聊天服务器连接失败')))
end
}
end
def chat(chatmessage)
case chatmessage.channel
when :lobby
msg = Jabber::Message::new(nil, chatmessage.message)
@@im_room.send msg
when User
msg = Jabber::Message::new(nil, chatmessage.message)
@@im_room.send msg, chatmessage.channel.id
#send(:chat, channel: chatmessage.channel.id, message: chatmessage.message, time: chatmessage.time)
end
end
def host(room_name, room_config)
room = Room.new(0, room_name)
room.pvp = room_config[:pvp]
room.match = room_config[:match]
room.tag = room_config[:tag]
room.password = room_config[:password]
room.ot = room_config[:ot]
room.lp = room_config[:lp]
if $game.rooms.any? { |game_room| game_room.name == room_name }
Widget_Msgbox.new("建立房间", "房间名已存在", :ok => "确定")
else
Game_Event.push Game_Event::Join.new(room)
end
end
def watch(room)
Widget_Msgbox.new("加入房间", "游戏已经开始", :ok => "确定")
end
def join(room)
Game_Event.push Game_Event::Join.new(room)
end
def refresh
send(:refresh)
end
def send(header, data=nil)
$log.info('发送消息') { {header: header, data: data} }
Client::MycardChannel.push header: header, data: data
end
def exit
@recv.exit if @recv
@recv = nil
end
def ygocore_path
"ygocore/ygopro_vs.exe"
end
def self.register
Dialog.web @@config['register']
end
def server
@@config['server']
end
def port
@@config['port']
end
def server=(server)
@@config['server'] = server
end
def port=(port)
@@config['port'] = port
end
def self.run_ygocore(option, image_downloading=false)
if !image_downloading and !Update.images.empty?
return Widget_Msgbox.new("加入房间", "卡图正在下载中,可能显示不出部分卡图", :ok => "确定") { run_ygocore(option, true) }
end
path = 'ygocore/ygopro_vs.exe'
Widget_Msgbox.new("ygocore", "正在启动ygocore") rescue nil
#写入配置文件并运行ygocore
Dir.chdir(File.dirname(path)) do
case option
when Room
room = option
room_name = if room.ot != 0 or room.lp != 8000
mode = case when room.match? then
1; when room.tag? then
2
else
0
end
room_name = "#{room.ot}#{mode}FFF#{room.lp},5,1,#{room.name}"
elsif room.tag?
"T#" + room.name
elsif room.pvp? and room.match?
"PM#" + room.name
elsif room.pvp?
"P#" + room.name
elsif room.match?
"M#" + room.name
else
room.name
end
if room.password and !room.password.empty?
room_name += "$" + room.password
end
system_conf = {}
begin
IO.readlines('system.conf').each do |line|
line.force_encoding "UTF-8"
next if line[0, 1] == '#'
field, contents = line.chomp.split(' = ', 2)
system_conf[field] = contents
end
rescue
system_conf['antialias'] = 2
system_conf['textfont'] = 'c:/windows/fonts/simsun.ttc 14'
system_conf['numfont'] = 'c:/windows/fonts/arialbd.ttf'
end
(system_conf['nickname'] = "#{$game.user.name}#{"$" unless $game.password.nil? or $game.password.empty?}#{$game.password}") rescue nil
system_conf['lastip'] = $game.server
system_conf['lastport'] = $game.port.to_s
system_conf['roompass'] = room_name
open('system.conf', 'w') { |file| file.write system_conf.collect { |key, value| "#{key} = #{value}" }.join("\n") }
args = '-j'
when :replay
args = '-r'
when :deck
args = '-d'
when String
system_conf = {}
begin
IO.readlines('system.conf').each do |line|
line.force_encoding "UTF-8"
next if line[0, 1] == '#'
field, contents = line.chomp.split(' = ', 2)
system_conf[field] = contents
end
rescue
system_conf['antialias'] = 2
system_conf['textfont'] = 'c:/windows/fonts/simsun.ttc 14'
system_conf['numfont'] = 'c:/windows/fonts/arialbd.ttf'
end
system_conf['lastdeck'] = option
open('system.conf', 'w') { |file| file.write system_conf.collect { |key, value| "#{key} = #{value}" }.join("\n") }
args = '-d'
end
IO.popen("ygopro_vs.exe #{args}")
WM.iconify rescue nil
end
Widget_Msgbox.destroy rescue nil
end
def self.replay(file, skip_image_downloading = false)
require 'fileutils'
FileUtils.mv Dir.glob('ygocore/replay/*.yrp'), 'replay/'
FileUtils.copy_file(file, "ygocore/replay/#{File.basename(file)}")
run_ygocore(:replay, skip_image_downloading)
end
private
def self.get_announcements
#公告
$config['ygocore'] ||= {}
$config['ygocore']['announcements'] ||= [Announcement.new("正在读取公告...", nil, nil)]
Thread.new do
begin
open(@@config['api']) do |file|
file.set_encoding "GBK"
announcements = []
file.read.encode("UTF-8").scan(/<div style="color:red" >公告:(.*?)<\/div>/).each do |title, others|
announcements << Announcement.new(title, @@config['index'], nil)
end
$config['ygocore']['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
module Client
MycardChannel = EM::Channel.new
include EM::P::ObjectProtocol
def post_init
send_object header: :login, data: {name: $game.username, password: $game.password}
MycardChannel.subscribe { |msg| send_object(msg) }
end
def receive_object obj
$log.info('收到消息') { obj.inspect }
Game_Event.push Game_Event.parse obj[:header], obj[:data]
end
def unbind
Game_Event.push Game_Event::Error.new('ygocore', '网络连接中断', true)
end
end
get_announcements
#encoding: UTF-8
load 'lib/ygocore/window_login.rb'
require 'eventmachine'
require 'open-uri'
require 'yaml'
class Ygocore < Game
attr_reader :username
attr_accessor :password
@@config = YAML.load_file("lib/ygocore/server.yml")
def initialize
super
load 'lib/ygocore/event.rb'
load 'lib/ygocore/user.rb'
load 'lib/ygocore/room.rb'
load 'lib/ygocore/scene_lobby.rb'
require 'json'
require 'xmpp4r/client'
require 'xmpp4r/muc'
end
def refresh_interval
60
end
def login(username, password)
@username = username
@password = password
@nickname_conflict = []
@@im = Jabber::Client.new(Jabber::JID::new(@username, 'my-card.in', 'mycard'))
@@im_room = Jabber::MUC::MUCClient.new(@@im)
#Jabber.debug = true
@@im.on_exception do |exception, c, where|
$log.error('聊天出错') { [exception, c, where] }
if where == :close
Game_Event.push(Game_Event::Chat.new(ChatMessage.new(User.new(:system, 'System'), '聊天连接断开, 可能是网络问题或帐号从其他地点登录')))
else
Game_Event.push(Game_Event::Chat.new(ChatMessage.new(User.new(:system, 'System'), '聊天连接断开, 5秒后重新连接')))
sleep 5
im_connect
end
end
@@im_room.add_message_callback do |m|
user = m.from.resource == nickname ? @user : User.new(m.from.resource.to_sym, m.from.resource)
Game_Event.push Game_Event::Chat.new ChatMessage.new(user, m.body, :lobby) rescue $log.error('收到聊天消息') { $! }
end
@@im_room.add_private_message_callback do |m|
if m.body #忽略无消息的正在输入等内容
user = m.from.resource == nickname ? @user : User.new(m.from.resource.to_sym, m.from.resource)
Game_Event.push Game_Event::Chat.new ChatMessage.new(user, m.body, user) rescue $log.error('收到私聊消息') { $! }
end
end
@@im_room.add_join_callback do |m|
Game_Event.push Game_Event::NewUser.new User.new m.from.resource.to_sym, m.from.resource
end
@@im_room.add_leave_callback do |m|
Game_Event.push Game_Event::MissingUser.new User.new m.from.resource.to_sym, m.from.resource
end
connect
im_connect
end
def nickname
return @nickname if @nickname
if @nickname_conflict.include? @username
1.upto(9) do |i|
result = "#{@username}-#{i}"
return result unless @nickname_conflict.include? result
end
raise 'can`t get available nickname'
else
@username
end
end
def connect
@recv = Thread.new do
EventMachine::run {
EventMachine::connect "bbs.66rpg.com", 9998, Client
}
end
end
def im_connect
Thread.new {
begin
@@im.allow_tls = false
@@im.use_ssl = true
@@im.connect('my-card.in', 5223)
#ruby19/windows下 使用tls连接时会卡住
@@im.auth(@password)
@@im.send(Jabber::Presence.new.set_type(:available))
begin
nickname = nickname()
@@im_room.join(Jabber::JID.new('lobby@conference.my-card.in/' + nickname))
rescue Jabber::ServerError => exception
if exception.error.error == 'conflict'
@nickname_conflict << nickname
retry
end
end
Game_Event.push Game_Event::AllUsers.new @@im_room.roster.keys.collect { |nick| User.new(nick.to_sym, nick) } rescue p $!
rescue StandardError => exception
$log.error('聊天连接出错') { exception }
Game_Event.push(Game_Event::Chat.new(ChatMessage.new(User.new(:system, 'System'), '聊天服务器连接失败')))
end
}
end
def chat(chatmessage)
case chatmessage.channel
when :lobby
msg = Jabber::Message::new(nil, chatmessage.message)
@@im_room.send msg
when User
msg = Jabber::Message::new(nil, chatmessage.message)
@@im_room.send msg, chatmessage.channel.id
#send(:chat, channel: chatmessage.channel.id, message: chatmessage.message, time: chatmessage.time)
end
end
def host(room_name, room_config)
room = Room.new(0, room_name)
room.pvp = room_config[:pvp]
room.match = room_config[:match]
room.tag = room_config[:tag]
room.password = room_config[:password]
room.ot = room_config[:ot]
room.lp = room_config[:lp]
if $game.rooms.any? { |game_room| game_room.name == room_name }
Widget_Msgbox.new("建立房间", "房间名已存在", :ok => "确定")
else
Game_Event.push Game_Event::Join.new(room)
end
end
def watch(room)
Widget_Msgbox.new("加入房间", "游戏已经开始", :ok => "确定")
end
def join(room)
Game_Event.push Game_Event::Join.new(room)
end
def refresh
send(:refresh)
end
def send(header, data=nil)
$log.info('发送消息') { {header: header, data: data} }
Client::MycardChannel.push header: header, data: data
end
def exit
@recv.exit if @recv
@recv = nil
end
def ygocore_path
"ygocore/ygopro_vs.exe"
end
def self.register
Dialog.web @@config['register']
end
def server
@@config['server']
end
def port
@@config['port']
end
def server=(server)
@@config['server'] = server
end
def port=(port)
@@config['port'] = port
end
def self.run_ygocore(option, image_downloading=false)
if !image_downloading and !Update.images.empty?
return Widget_Msgbox.new("加入房间", "卡图正在下载中,可能显示不出部分卡图", :ok => "确定") { run_ygocore(option, true) }
end
path = 'ygocore/ygopro_vs.exe'
Widget_Msgbox.new("ygocore", "正在启动ygocore") rescue nil
#写入配置文件并运行ygocore
Dir.chdir(File.dirname(path)) do
case option
when Room
room = option
room_name = if room.ot != 0 or room.lp != 8000
mode = case when room.match? then
1; when room.tag? then
2
else
0
end
room_name = "#{room.ot}#{mode}FFF#{room.lp},5,1,#{room.name}"
elsif room.tag?
"T#" + room.name
elsif room.pvp? and room.match?
"PM#" + room.name
elsif room.pvp?
"P#" + room.name
elsif room.match?
"M#" + room.name
else
room.name
end
if room.password and !room.password.empty?
room_name += "$" + room.password
end
system_conf = {}
begin
IO.readlines('system.conf').each do |line|
line.force_encoding "UTF-8"
next if line[0, 1] == '#'
field, contents = line.chomp.split(' = ', 2)
system_conf[field] = contents
end
rescue
system_conf['antialias'] = 2
system_conf['textfont'] = 'c:/windows/fonts/simsun.ttc 14'
system_conf['numfont'] = 'c:/windows/fonts/arialbd.ttf'
end
(system_conf['nickname'] = "#{$game.user.name}#{"$" unless $game.password.nil? or $game.password.empty?}#{$game.password}") rescue nil
system_conf['lastip'] = $game.server
system_conf['lastport'] = $game.port.to_s
system_conf['roompass'] = room_name
open('system.conf', 'w') { |file| file.write system_conf.collect { |key, value| "#{key} = #{value}" }.join("\n") }
args = '-j'
when :replay
args = '-r'
when :deck
args = '-d'
when String
system_conf = {}
begin
IO.readlines('system.conf').each do |line|
line.force_encoding "UTF-8"
next if line[0, 1] == '#'
field, contents = line.chomp.split(' = ', 2)
system_conf[field] = contents
end
rescue
system_conf['antialias'] = 2
system_conf['textfont'] = 'c:/windows/fonts/simsun.ttc 14'
system_conf['numfont'] = 'c:/windows/fonts/arialbd.ttf'
end
system_conf['lastdeck'] = option
open('system.conf', 'w') { |file| file.write system_conf.collect { |key, value| "#{key} = #{value}" }.join("\n") }
args = '-d'
end
IO.popen("ygopro_vs.exe #{args}")
WM.iconify rescue nil
end
Widget_Msgbox.destroy rescue nil
end
def self.replay(file, skip_image_downloading = false)
require 'fileutils'
FileUtils.mv Dir.glob('ygocore/replay/*.yrp'), 'replay/'
FileUtils.copy_file(file, "ygocore/replay/#{File.basename(file)}")
run_ygocore(:replay, skip_image_downloading)
end
private
def self.get_announcements
#公告
$config['ygocore'] ||= {}
$config['ygocore']['announcements'] ||= [Announcement.new("正在读取公告...", nil, nil)]
Thread.new do
begin
open(@@config['api']) do |file|
file.set_encoding "GBK"
announcements = []
file.read.encode("UTF-8").scan(/<div style="color:red" >公告:(.*?)<\/div>/).each do |title, others|
announcements << Announcement.new(title, @@config['index'], nil)
end
$config['ygocore']['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
module Client
MycardChannel = EM::Channel.new
include EM::P::ObjectProtocol
def post_init
send_object header: :login, data: {name: $game.username, password: $game.password}
MycardChannel.subscribe { |msg| send_object(msg) }
end
def receive_object obj
$log.info('收到消息') { obj.inspect }
Game_Event.push Game_Event.parse obj[:header], obj[:data]
end
def unbind
Game_Event.push Game_Event::Error.new('ygocore', '网络连接中断', true)
end
end
get_announcements
end
\ No newline at end of file
class User
attr_reader :certified
def initialize(id, name = "", certified = true)
@id = id
@name = name
@certified = certified
end
def set(id, name = :keep, certified = :keep)
@id = id unless id == :keep
@name = name unless name == :keep
@certified = certified unless certified == :keep
end
def color
@certified ? [0,0,0] : [128,128,128]
end
def space
if @certified
Dialog.web "http://my-card.in/users/#{CGI.escape @id.to_s}"
else
Widget_Msgbox.new("查看资料", "用户#{@name}没有注册", :ok => "确定")
end
end
def avatar(size = :small)
cache = "graphics/avatars/mycard_#{@id}_#{size}.png"
result = Surface.load(cache) rescue Surface.load("graphics/avatars/loading_#{size}.gif")
scene = $scene
if block_given?
yield result
Thread.new do
require 'cgi'
open("http://my-card.in/users/#{CGI.escape @id.to_s}.png", 'rb') {|io|open(cache, 'wb') {|c|c.write io.read}} rescue cache = "graphics/avatars/noavatar_#{size}.gif"
(yield Surface.load(cache) if scene == $scene) rescue nil
end
else
result
end
end
end
class User
attr_reader :certified
def initialize(id, name = "", certified = true)
@id = id
@name = name
@certified = certified
end
def set(id, name = :keep, certified = :keep)
@id = id unless id == :keep
@name = name unless name == :keep
@certified = certified unless certified == :keep
end
def color
@certified ? [0,0,0] : [128,128,128]
end
def space
if @certified
Dialog.web "http://my-card.in/users/#{CGI.escape @id.to_s}"
else
Widget_Msgbox.new("查看资料", "用户#{@name}没有注册", :ok => "确定")
end
end
def avatar(size = :small)
cache = "graphics/avatars/mycard_#{@id}_#{size}.png"
result = Surface.load(cache) rescue Surface.load("graphics/avatars/loading_#{size}.gif")
scene = $scene
if block_given?
yield result
Thread.new do
require 'cgi'
open("http://my-card.in/users/#{CGI.escape @id.to_s}.png", 'rb') {|io|open(cache, 'wb') {|c|c.write io.read}} rescue cache = "graphics/avatars/noavatar_#{size}.gif"
(yield Surface.load(cache) if scene == $scene) rescue nil
end
else
result
end
end
end
class Window_Login
def clicked
return if @last_clicked and Time.now - @last_clicked < 3 #防止重复点击
case @index
when :login
Widget_Msgbox.new("ygocore", "正在登录")
$scene.draw #强制重绘一次,下面会阻塞
$game = Ygocore.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
Ygocore.register
@last_clicked = Time.now
when :replay
file = Dialog.get_open_file("播放录像", "ygocore录像 (*.yrp)" => "*.yrp")
if !file.empty? and File.file? file
Ygocore.replay file
end
@last_clicked = Time.now
end
end
class Window_Login
def clicked
return if @last_clicked and Time.now - @last_clicked < 3 #防止重复点击
case @index
when :login
Widget_Msgbox.new("ygocore", "正在登录")
$scene.draw #强制重绘一次,下面会阻塞
$game = Ygocore.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
Ygocore.register
@last_clicked = Time.now
when :replay
file = Dialog.get_open_file("播放录像", "ygocore录像 (*.yrp)" => "*.yrp")
if !file.empty? and File.file? file
Ygocore.replay file
end
@last_clicked = Time.now
end
end
end
\ No newline at end of file
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