Posts filled under: ruby
WordSquared bot
Looks like i wrote a good enough bot for http://wordsquared.com/
Version 0.1b at youtube: http://www.youtube.com/watch?v=NilCjtRIvng
It was more laggy, than current :)
As below log shows, its completing words with 2-4w per 1s, but this affected only by my current internet connection.
Later i’ll move it to dedicated server in hetzner.de to test European’s speed.
P.S. from 3k point to 10k in 10 mins :) P.S.S. Still using http://wordsolver.net/ word’s database -.-
Logged as Bubonic Pestilence
Loading game .. OK
@ws.tiles: 1.678851842880249 parse: 0.00460505485534668
9958 6998 A DIRECTION: bottom SIZE: 11 WORD: ALB
9918 6997 H DIRECTION: left SIZE: 11 WORD: LECH
9958 6997 L DIRECTION: left SIZE: 11 WORD: EXCEL
9958 6996 B DIRECTION: right SIZE: 11 WORD: BECK
9959 6996 E DIRECTION: bottom SIZE: 11 WORD: EMEU
9961 6996 K DIRECTION: bottom SIZE: 11 WORD: KAYO
9921 6995 O DIRECTION: bottom SIZE: 11 WORD: OAT
9923 6995 E DIRECTION: top SIZE: 3 WORD: DYE
9961 6995 A DIRECTION: right SIZE: 11 WORD: AFT
9963 6995 T DIRECTION: bottom SIZE: 11 WORD: TAXI
9921 6994 A DIRECTION: left SIZE: 11 WORD: RAJA
9950 6994 J DIRECTION: right SIZE: 8 WORD: JAWS
9951 6994 A DIRECTION: top SIZE: 9 WORD: HANSA
9952 6994 W DIRECTION: top SIZE: 8 WORD: SHAW
9953 6994 S DIRECTION: bottom SIZE: 5 WORD: SAINS
9959 6994 E DIRECTION: left SIZE: 5 WORD: HAME
9963 6994 A DIRECTION: right SIZE: 11 WORD: AHI
9921 6993 T DIRECTION: right SIZE: 2 WORD: TI
9922 6993 I DIRECTION: bottom SIZE: 3 WORD: IRE
9945 6993 R DIRECTION: left SIZE: 3 WORD: PUR
9950 6993 A DIRECTION: left SIZE: 3 WORD: BA
9953 6993 A DIRECTION: right SIZE: 3 WORD: AVE
9955 6993 E DIRECTION: bottom SIZE: 6 WORD: EDS
9953 6992 I DIRECTION: left SIZE: 2 WORD: TI
9963 6992 I DIRECTION: right SIZE: 11 WORD: IN
9922 6991 E DIRECTION: left SIZE: 11 WORD: RE
9925 6990 E DIRECTION: bottom SIZE: 11 WORD: EF
9926 6990 A DIRECTION: bottom SIZE: 11 WORD: ADZ
9951 6985 E DIRECTION: bottom SIZE: 11 WORD: EF
9957 7029 I DIRECTION: left SIZE: 11 WORD: QI
9959 7029 I DIRECTION: right SIZE: 11 WORD: IF
9891 7028 R DIRECTION: right SIZE: 2 WORD: RE
9897 7028 B DIRECTION: bottom SIZE: 2 WORD: BE
9940 7028 E DIRECTION: right SIZE: 4 WORD: ED
9897 7027 E DIRECTION: left SIZE: 5 WORD: DICE
9897 7025 E DIRECTION: left SIZE: 11 WORD: WE
9942 7025 O DIRECTION: bottom SIZE: 3 WORD: OS
9961 7025 D DIRECTION: right SIZE: 11 WORD: DIG
9962 7025 I DIRECTION: top SIZE: 11 WORD: QI
9963 7025 G DIRECTION: bottom SIZE: 11 WORD: GINKS
9954 7024 Y DIRECTION: top SIZE: 11 WORD: BY
Dofus first AI… Roaming between wheet :) That later it will farm…
Ruby & Binary data… My way of parsing:
Wrote class, that help me reading binary data:
Usage
"\x11\x5f\x14".log # show hexdump
"\x40\x40".readShort # & etc
Code
module NetString
LITTLE_ENDIAN = 1
BIG_ENDIAN = 2
SYS_ENDIAN = ([42].pack('i')[0].ord == 42) ? LITTLE_ENDIAN : BIG_ENDIAN
def endian
#@endian = SYS_ENDIAN if @endian.nil?
@endian = BIG_ENDIAN if @endian.nil?
@endian
end
def endianess=(endian)
unless [BIG_ENDIAN, LITTLE_ENDIAN].include? endian
raise 'Endianess should be set with const: NetString::LITTLE_ENDIAN or NetString::BIG_ENDIAN'
exit
end
@endian = endian
end
def endianess data
endian
if @endian != SYS_ENDIAN
data.reverse!
end
end
def nsRead l, endian = true
case self
when String
self.force_encoding 'ASCII-8BIT' if self.encoding.to_s == 'UTF-8'
data = slice!(0, l)
when File, StringIO
data = read(l)
end
unless data.bytes.to_a.size == l
self.log "self"
pp l
data.log "data"
end
raise 'NetString: incorrect length data read' unless data.bytes.to_a.size == l
endianess(data) if endian
data
end
def readByte; nsRead(1, false).unpack('c').first.to_i; end ## signed
def readUByte; nsRead(1, false).unpack('C').first.to_i; end
def readBoolean; !(readByte == 0); end
def readShort; nsRead(2).unpack('s').first.to_i; end ## signed
def readUShort; nsRead(2).unpack('S').first.to_i; end
def readInt; nsRead(4).unpack('l').first.to_i; end ## signed
def readUInt; nsRead(4).unpack('L').first.to_i; end
def readDouble; nsRead(8, false).unpack('G').first.to_i; end ## Double-precision float
def readFloat; puts '----------- CHECK ME READ FLOAT -----------'; nsRead(8).unpack('g').first.to_i; end ## Single-precision float
def readQuad; nsRead(8).unpack('Q').first.to_i; end
def readLongLong; a = readInt; b = readInt; a | (b << 32); end
def readBytesAsString l; nsRead(l, false); end
def readString; str = ''; while (char = readBytesAsString(1)) != "\x00"; str << char; end; str; end
def readUTFString; s = readShort; readBytesAsString s; end
alias_method :readUnsignedByte, :readUByte
alias_method :readUnsignedShort, :readUShort
alias_method :readUnsignedInt, :readUInt
alias_method :readUTF, :readUTFString
def nsWrite data, endian = true
endianess(data) if endian
case self.class.to_s
when 'String'
concat(data)
when 'File'
print data
end
self
end
def writeByte data; nsWrite([data].pack('c'), false); end
def writeUByte data; nsWrite([data].pack('C'), false); end
def writeBoolean data; nsWrite([data.to_i].pack('C'), false); end
def writeShort data; nsWrite([data].pack('s')); end
def writeUShort data; nsWrite([data].pack('S')); end
def writeInt data; nsWrite([data].pack('l')); end
def writeUInt data; nsWrite([data].pack('L')); end
def writeDouble; puts '----------- CHECK ME WRITE DOUBLE -----------', nsWrite([data].pack('G')); end ## Double-precision float
def writeFloat; puts '----------- CHECK ME WRITE FLOAT -----------', nsWrite([data].pack('g')); end ## Single-precision float
def writeQuad data; nsWrite([data].pack('Q')); end
def writeBytesAsString data; nsWrite(data, false); end
def writeString data; nsWrite(data + "\x00", false); end
def writeUTFString data; writeUShort(data.size); nsWrite(data, false); end
def hexed(short = false)
f = '%02X'
j = ' '
if short
f = '%02x'
j = ''
end
h = bytes.to_a.collect { |c| f % c }
h.join j
end
def to_ansi
string = ''
t = bytes.to_a.each do |byte|
byte = 46 if byte < 33 or byte > 126
string += ' ' + byte.chr
end
string.strip
end
def log(name = nil, short = false)
puts rlog(name, short)
end
def rlog(name, short = false)
name = 'DATA DUMP' if name.nil?
pad = '-' * 25
firstline = "#{pad} #{name} (#{length}) #{pad}"
endline = '-' * firstline.length
firstline << "\n" <<
to_ansi << "\n" <<
hexed(short) << "\n" <<
endline
end
def to_block(l = 50, params = {})
l /= 2
self.strip!
puts "#{'-' * l} #{self} #{'-' * l}\n"
params.each { |k, v| puts "#{k}: #{v}" } if params.size
yield
puts "#{'-' * (2 * l + length + 2)}"
end
end
class String
include NetString
end
class IO
include NetString
end
class StringIO
include NetString
end
Btw, it’s in beta currently, because i didn’t check float/double methods enough :)
Flickr & Ruby…
Simple ruby script, for downloading flickr’s photosets
Requirements
sudo gem install flickraw mechanize
Usage
ruby flickr.rb
Code
#!/usr/local/rvm/ruby
# encoding: utf-8
require "fileutils"
require "flickraw"
require "mechanize"
m = Mechanize.new
FlickRaw.api_key = "<YOU_API_KEY>"
FlickRaw.shared_secret = "<YOR_API_SECRET>"
photosets = %w{<PHOTOSTREAM_ID> <PHOTOSTREAM_ID> <PHOTOSTREAM_ID> <PHOTOSTREAM_ID>}
photosets.each do |photoset_id|
list = flickr.photosets.getPhotos(photoset_id: photoset_id, extras: 'url_o, url_l, url_m')
h = list.to_hash
h["photo"].each do |p|
url = p["url_o"] || p["url_l"] || p["url_m"]
filedir = "flickr/#{photoset_id}"
filename = File.basename(url)
filepath = "#{filedir}/#{filename}"
next if File.exists?(filepath)
file = m.get(url)
FileUtils.mkdir_p(filedir)
file.save_as(filepath)
end
end
Oh yeah!
Now it can login, move, and say through console :)
[ INFO] [D2I] Parsing i18n_en.d2i
[ INFO] [D2O] Parsing InfoMessages.d2o
[ INFO] [D2O] Parsing Servers.d2o
[ INFO] [D2O] Parsing ChatChannels.d2o
[ INFO] Connected
[ OK] Authentification successful
[ INFO] Connected
[ OK] Ticket accepted
[ INFO] Position in character selection queue: 1 / 1
[ INFO] Position in character selection queue: 0 / 0
[ INFO] Position in character selection queue: 0 / 0
[ INFO] Character weight: 14 / 1000
[ OK] Welcome to DOFUS, and welcome to the World of Twelve! Remember that it is <b>strictly forbidden</b> to disclose your account name or password.
[ OK] This account was last accessed on 13/07/2011 at 05:02.
[CHAT] [GENERAL] : oops
[CHAT] [GENERAL] : like i didn't did it wrong?!
[CHAT] [GENERAL] : heh
[CHAT] [PRIVATE] : asd
[CHAT] [PRIVATE] : wanna join me ? )
say hellow world )
[CHAT] [GENERAL] : hellow world )
say bla bla bla
[CHAT] [GENERAL] : bla bla bla
Dofus «login -> game» sequence
Just got it…
def check_connection
recv # receive packets
case @state
when STATE_NOT_CONNECTED
reconnect
when STATE_CONNECTED_TO_LOGIN
@packets.pop do |packet|
case packet
when Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
if packet.requiredVersion > $config.protocol_build
log("Current protocol build: #{$config.protocol_build}, required build: #{packet.requiredVersion}", Logger::FATAL)
end
if packet.currentVersion < $config.protocol_required_build
log("Current protocol build: #{$config.protocol_required_build}, is too new for the server version: #{packet.currentVersion}", Logger::FATAL)
end
when HelloConnectMessage
$config.session_key = packet.sessionKey
im = IdentificationMessage.new
bytes = im.build!({
username: $config.username,
password: $config.password,
version: $config.version,
session_key: $config.session_key
})
send_data bytes
when Com::AnkamaGames::Dofus::Network::Messages::Queues::LoginQueueStatusMessage
l("Position in login queue: #{packet.position} / #{packet.total}")
when IdentificationSuccessMessage
l('Authentification successful', Logger::OK)
@state = STATE_SERVERS_LIST
else
l("Incorrect packet at $net.STATE_CONNECTED_TO_LOGIN: #{packet.class}", Logger::FATAL)
end
end
when STATE_SERVERS_LIST
@packets.pop do |packet|
case packet
when ServersListMessage
if !$config.server_id
"Select server:".to_block(10) {
packet.servers.select { |s| s.status == s.class::STATUS_ONLINE }.each do |s|
printf("%5d %s %d %s\n", s.id, "-", s.charactersCount, s.status_t)
end
}
while line = gets do
line.strip!
next if line.empty?
exit if line.to_i == 0
server = packet.servers.find { |s| s.id == line.to_i }
next unless server
$config.server_id = server.id
break
end
end
ssm = ServerSelectionMessage.new.build!($config.server_id)
send_data ssm
when SelectedServerDataMessage
@ip = packet.address
@port = packet.port
$config.ticket = packet.ticket
reconnect
@state = STATE_CONNECTED_TO_GAME
else
l("Incorrect packet at $net.STATE_SERVERS_LIST: #{packet.class}", Logger::FATAL)
end
end
when STATE_CONNECTED_TO_GAME
@packets.pop do |packet|
case packet
when Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
if packet.requiredVersion > $config.protocol_build
log("Current protocol build: #{$config.protocol_build}, required build: #{packet.requiredVersion}", Logger::FATAL)
end
if packet.currentVersion < $config.protocol_required_build
log("Current protocol build: #{$config.protocol_required_build}, is too new for the server version: #{packet.currentVersion}", Logger::FATAL)
end
when HelloGameMessage
atm = AuthenticationTicketMessage.new.build!('en', $config.ticket)
send_data atm
when AuthenticationTicketAcceptedMessage
l("Ticket accepted", Logger::OK)
when Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicTimeMessage
# nothing to do, just ignore
when Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AccountCapabilitiesMessage
$config.account_id = packet.account_id
clrm = Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListRequestMessage.new.build!
send_data clrm
@state = STATE_CHARACTER_SELECTION
else
l("Incorrect packet at $net.STATE_CONNECTED_TO_GAME: #{packet.class}", Logger::FATAL)
end
end
when STATE_CHARACTER_SELECTION
@packets.pop do |packet|
case packet
when Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
l("Position in character selection queue: #{packet.position} / #{packet.total}")
when Com::AnkamaGames::Dofus::Network::Messages::Secure::TrustStatusMessage,
Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
# nothing to do, ignore
when Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListMessage
characters = packet.characters
if !$config.character_id && characters.size > 0
puts "Choose your character:"
fields = sprintf("%20s | %5s | %5s | %6s", 'Name', 'Level', 'Class', 'Sex')
puts fields, '-' * fields.size
characters.each do |c|
puts sprintf("%20s | %5d | %5d | %6s", c.name, c.level, c.breed, c.sex ? 'Male' : 'Female')
end
while line = gets do
line.strip!
break if line.empty?
character = characters.find { |c| c.name.downcase == line.downcase }
next unless character
$config.character_id = character.id
break
end
csm = Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharacterSelectionMessage.new.build!($config.character_id)
send_data csm
@state = STATE_IN_GAME
elsif characters.size == 0
l("No character created", Logger::FATAL)
exit
end
else
l("Incorrect packet at $net.STATE_CHARACTER_SELECTION: #{packet.class}", Logger::FATAL)
end
end
when STATE_IN_GAME
else
l("Unknown state #{state} for $net", Logger::FATAL);
exit
end
end
Output
[user host-122 ~/Documents/Projects/dofus] ./run.rb
[ INFO] [D2O] Parsing Servers.d2o
[ INFO] Connected
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::HelloConnectMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::IdentificationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::IdentificationSuccessMessage
[ OK] Authentification successful
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::ServersListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::ServerSelectionMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Connection::SelectedServerDataMessage
[ INFO] Connected
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Handshake::ProtocolRequired
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::HelloGameMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AuthenticationTicketMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AuthenticationTicketAcceptedMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicTimeMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Approach::AccountCapabilitiesMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Secure::TrustStatusMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
[ OK] Ticket accepted
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListRequestMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
[ INFO] Position in character selection queue: 1 / 1
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Queues::QueueStatusMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharactersListMessage
[ INFO] Position in character selection queue: 0 / 0
[ INFO] Position in character selection queue: 0 / 0
Choose your character:
Name | Level | Class | Sex
---------------------------------------------
Char1 | 2 | 5 | Male
Char2 | 4 | 3 | Female
Char3 | 19 | 9 | Female
Char1
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharacterSelectionMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::BasicNoOperationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Context::Notification::NotificationListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Character::Choice::CharacterSelectedSuccessMessage
[ INFO] Selected character: [------] Char1 (2)
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Items::InventoryContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Items::SetUpdateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Shortcut::ShortcutBarContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Shortcut::ShortcutBarContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Context::Roleplay::Emote::EmoteListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Pvp::AlignmentRankUpdateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Pvp::AlignmentSubAreasListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Chat::Channel::EnabledChannelsMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Spells::SpellListMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Shortcut::ShortcutBarContentMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Initialization::SetCharacterRestrictionsMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Inventory::Items::InventoryWeightMessage
[ INFO] Character weight: 14 / 1000
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::FriendWarnOnConnectionStateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::GuildMemberWarnOnConnectionStateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::FriendWarnOnLevelGainStateMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[ WARN] Check Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[ WARN] Check Com::AnkamaGames::Dofus::Network::Messages::Game::Basic::TextInformationMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Initialization::ServerExperienceModificatorMessage
[DEBUG] Com::AnkamaGames::Dofus::Network::Messages::Game::Friend::SpouseStatusMessage
P.S. Please don’t blame my ugly code :)
YouTube Video Uploader
Wrote script to upload bunch of videos to youtube through YouTube API:
To get developer’s key, visit: http://code.google.com/apis/youtube/dashboard/gwt/index.html
Thanks to kylejginavan@github for this cool gem: YouTube It
Usage:
ruby youtube-it.rb --user <user@gmail.com> --password <password_for_gmail> --key <your_dev_key> *.avi
Before run
gem install youtube_it -r
Code:
# encoding: utf-8
require "rubygems"
require "openssl"
OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE
require "youtube_it"
require "fileutils"
require "ostruct"
require "optparse"
$stdout.sync = true
options = OpenStruct.new
optparse = OptionParser.new do |opts|
opts.banner = "Usage: #{$0} [options] file1[ file2 ...]"
opts.on("-u", "--user USERNAME", "[REQUIRED] Specify username for youtube account") do |username|
options.username = username
end
opts.on(:REQUIRED, "-p", "--password PASSWORD", "[REQUIRED] Specify password for youtube account") do |password|
options.password = password
end
opts.on("-k", "--key KEY", "[REQUIRED] Specify developer's key for youtube account") do |dev_key|
options.dev_key = dev_key
end
opts.on_tail("-h", "--help", "Display this screen") do
puts opts
exit
end
end
optparse.parse!
if options.username.nil? || options.password.nil? || options.dev_key.nil? || ARGV.size == 0
puts optparse
exit
end
client = YouTubeIt::Client.new({
:username => options.username,
:password => options.password,
:dev_key => options.dev_key
})
ARGV.each do |filepath|
(puts "File #{filepath} doesn't exists. Skipping."; next) unless File.exists?(filepath)
begin
print filepath
title = File.basename(filepath, File.extname(filepath))
title[0] = title[0, 1].upcase
title.gsub!(/\s*(\-|_)\s*/iu, ' ')
client.video_upload(File.open(filepath), {
:title => title,
:description => title,
:category => "Travel"
})
puts " .. OK!"
rescue Exception => e
puts "", e, "Sleeping 30s", ""
sleep 30
retry
end
end
Awful “command” for TextMate
Are anyone capable to explain usage of this script?
#!/opt/local/bin/ruby
DOFUS_DIR = File.expand_path("~/Documents/Projects/DofusApp/source")
def tabs size = 3
" " * size
end
filepath_rb = ENV["TM_FILEPATH"]
filepath_as = filepath_rb.gsub(File.expand_path('~/Documents/Projects/dofus/includes'), '')
filepath_as = DOFUS_DIR + File.join(File.dirname(filepath_as).downcase, File.basename(filepath_as, File.extname(filepath_as)) + ".as")
raise unless File.exists?(filepath_as)
File.open(filepath_as) do |f|
data = f.read
as_tabs, code = data.scan(/([ \t]+)public function deserializeAs_.+?:void\s*\{\s+(.+?)\s+return.+\1\}/miu).first
new_code = code.lines.
map { |l| l.strip!; tabs + l }.
join("\n").
gsub("this.", "@").
gsub("();", "").
gsub(/var loc\d+:\*=(0|null);\s*/ium, "").
gsub(/super\.deserialize\(arg1\);/ium, "super data\n#{tabs}").
gsub(/com\.ankamagames\.jerakine\.network\.utils\.BooleanByteWrapper\.getFlag\(loc\d+,\s*(\d+)\);/iu, "BBW.get(byte, \\1)").
gsub(/if \([^\(\)]+\) \{\s+throw new Error[^\n]+\s+\}[\s\n\t]*/ium, "").
gsub(/[ \t]+var loc\d+:\*=\s*arg\d+\.readUnsignedShort\s+while.+\s+loc\d+ = arg1.(\w+)\s+(@\w+).+\s+.+\s+\}/u, <<-EOD).
#{tabs}
#{tabs}\\2 = []
#{tabs}data.readUShort.times {
#{tabs} \\2 << data.\\1
#{tabs}}
EOD
gsub(/[ \t]+var loc\d+:\*=\s*arg\d+\.readUnsignedShort\s+while.+\s+\(loc\d+ = new com[^A-Z]+(\w+).+\s+(@\w+).+\s+.+\s+\}/u, <<-EOD).
#{tabs}
#{tabs}\\2 = []
#{tabs}data.readUShort.times {
#{tabs} (obj = \\1.new).deserialize(data)
#{tabs} \\2 << obj
#{tabs}}
EOD
gsub(/[ \t]+var loc\d+:\*=\s*arg\d+\.readUnsignedShort\s+while.+\s*{\s*if \(\(loc\d+ = \w+.(read\w+).+\s*throw new Error.+\s+\}\s.+(@\w+).+\s+\+\+loc\d.+\s.+/iu, <<-EOD).
#{tabs}
#{tabs}\\2 = []
#{tabs}data.readUShort.times {
#{tabs} \\2 << data.\\1
#{tabs}}
EOD
gsub(/[^\n]+var loc\d+:\*=\s*arg\d+\.readUnsignedShort\s+while\s*\([^)]+\)\s*{\s*loc\d+ = \w+\.readUnsignedShort\s\s*\(loc\d+ = [\w\.]+ProtocolTypeManager\.getInstance.+\.deserialize\((.+)\)[^@]+(@\w+)[^}]+}\n/iu, <<-EOD).
#{tabs}
#{tabs}\\2 = []
#{tabs}data.readUShort.times {
#{tabs} type_id = data.readUShort
#{tabs} (obj = Types.get(type_id)).deserialize(\\1)
#{tabs} \\2 << obj
#{tabs}}
#{tabs}
EOD
gsub(/var loc\d:\*=arg1.readUnsignedShort\s+(@\w+) = .+ProtocolTypeManager.getInstance[^A-Z]+(\w+).+\s+\1.+/u, <<-EOD).
#{tabs}
#{tabs}type_id = data.readUShort
#{tabs}(\\1 = Types.get(type_id)).deserialize(data)
#{tabs}
EOD
gsub(/\s+(\S+) = new com.ankamagames[^A-Z]+(\w+)/u, "\n#{tabs}\n#{tabs}\\1 = \\2.new").
gsub(".deserialize(arg1);", ".deserialize(arg1)\n#{tabs}").
gsub("arg1", "data").
strip
print "#{new_code}
#{tabs}
#{tabs}false"
end
Халява MLGame ячейки!
Oops, найдена бага, последняя координата +1 надо :)
i.e. 68-1-51 => 68-1-52
Может быть кому нужны ячейки для городов > 38 клеток? )
[68-1-51] DEADLAND 41
[68-3-15] DEADLAND 41
[68-3-16] DEADLAND 39
[68-3-22] DEADLAND 42
[68-4-13] CURSEDFOREST 40
[69-4-62] HOLYLAND 39
[70-3-03] FOREST 39
[70-4-31] HOLYLAND 43
[70-5-15] MAGICFOREST 43
[72-1-32] DEADLAND 39
[72-2-16] MOUNTAIN 40
[72-2-38] HOLYLAND 41
[72-4-11] STEPPE 42
[73-2-02] FOREST 40
[73-2-33] FOREST 40
[73-2-44] FOREST 41
Ещё один добрый человек поделился:
[53-21-53] STEPPE 39
[56-22-22] CURSEDFOREST 40
[56-22-26] FOREST 41
[57-20-51] DEADLAND 42
[57-22-52] MAGICFOREST 42
[58-21-44] STEPPE 39
[58-22-46] FOREST 42
[59-21-01] MOUNTAIN 39
[59-22-12] FOREST 40
[59-22-14] MAGICFOREST 43
[59-22-36] MAGICFOREST 43
[59-22-60] DEADLAND 39
[60-20-45] DEADLAND 43
[60-21-49] CURSEDFOREST 39
[61-20-22] HOLYLAND 42
Сканер “уже открытых” ячеек на карте
Сборщик уже исследованных ячеек… точнее его вывод:
[65-3-39] DESERT 29
[65-3-47] DESERT 29
[65-3-48] DESERT 22
[65-4-01] CURSEDFOREST 29
[65-4-03] CURSEDFOREST 37
[68-1-10] CURSEDFOREST 32
[68-1-11] CURSEDFOREST 22
[68-1-12] CURSEDFOREST 34
[68-1-13] CURSEDFOREST 37
[68-1-14] CURSEDFOREST 22
[68-4-12] STEPPE 24
[68-4-13] CURSEDFOREST 40
[68-4-14] DEADLAND 35
[68-4-15] DEADLAND 28
[69-2-60] HOLYLAND 28
[69-2-61] HOLYLAND 22
[69-3-00] MOUNTAIN 28
[69-3-01] MOUNTAIN 22
[70-1-49] HOLYLAND 23
[70-1-51] HOLYLAND 22
[70-1-52] HOLYLAND 37
[70-1-54] FOREST 27
[70-1-56] MAGICFOREST 38
[70-1-58] MAGICFOREST 24
[70-1-62] HOLYLAND 34
[70-5-12] MAGICFOREST 23
[70-5-13] MAGICFOREST 31
[70-5-15] MAGICFOREST 43
[70-5-17] MAGICFOREST 23
[70-5-18] STEPPE 28
[70-5-19] STEPPE 33
[70-5-20] STEPPE 26
[71-3-03] MAGICFOREST 23
[71-3-05] MAGICFOREST 36
[71-3-06] MAGICFOREST 26
[71-3-08] MAGICFOREST 22
[71-3-09] HOLYLAND 27
[72-2-32] MAGICFOREST 26
[72-2-33] STEPPE 33
[72-2-34] MAGICFOREST 22
