forked from OpenNeo/impress
core of pet loading, still needs get image hash, download assets
This commit is contained in:
parent
8b7b40019d
commit
bb233359d8
13 changed files with 361 additions and 13 deletions
13
Gemfile
13
Gemfile
|
@ -1,22 +1,19 @@
|
|||
source 'http://rubygems.org'
|
||||
|
||||
gem 'rails', '3.0.0'
|
||||
|
||||
gem 'sqlite3-ruby', :require => 'sqlite3'
|
||||
|
||||
gem 'haml', '~> 3.0.18'
|
||||
|
||||
gem 'will_paginate', '~> 3.0.pre2'
|
||||
|
||||
gem 'rdiscount', '~> 1.6.5'
|
||||
|
||||
gem 'compass', '~> 0.10.1'
|
||||
gem 'haml', '~> 3.0.18'
|
||||
gem 'rdiscount', '~> 1.6.5'
|
||||
gem 'RocketAMF', '~> 0.2.1'
|
||||
gem 'will_paginate', '~> 3.0.pre2'
|
||||
|
||||
group :development do
|
||||
gem 'mysql'
|
||||
end
|
||||
|
||||
group :test do
|
||||
gem 'rspec-rails', '~> 2.0.0.beta.22'
|
||||
gem 'factory_girl_rails', '~> 1.0'
|
||||
gem 'rspec-rails', '~> 2.0.0.beta.22'
|
||||
end
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
RocketAMF (0.2.1)
|
||||
abstract (1.0.0)
|
||||
actionmailer (3.0.0)
|
||||
actionpack (= 3.0.0)
|
||||
|
@ -92,6 +93,7 @@ PLATFORMS
|
|||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
RocketAMF (~> 0.2.1)
|
||||
compass (~> 0.10.1)
|
||||
factory_girl_rails (~> 1.0)
|
||||
haml (~> 3.0.18)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
class Item < ActiveRecord::Base
|
||||
include SwfAssetParent
|
||||
|
||||
SwfAssetType = 'object'
|
||||
|
||||
has_many :parent_swf_asset_relationships, :foreign_key => 'parent_id',
|
||||
:conditions => {:swf_asset_type => SwfAssetType}
|
||||
has_many :swf_assets, :through => :parent_swf_asset_relationships
|
||||
|
||||
NCRarities = [0, 500]
|
||||
PaintbrushSetDescription = 'This item is part of a deluxe paint brush set!'
|
||||
|
||||
|
@ -102,6 +104,89 @@ class Item < ActiveRecord::Base
|
|||
}
|
||||
end
|
||||
|
||||
def before_save
|
||||
sold_in_mall = false
|
||||
end
|
||||
|
||||
def origin_registry_info=(info)
|
||||
# bear in mind that numbers from registries are floats
|
||||
self.species_support_ids = info[:species_support].map(&:to_i)
|
||||
attribute_names.each do |attribute|
|
||||
value = info[attribute.to_sym]
|
||||
if value
|
||||
value = value.to_i if value.is_a? Float
|
||||
self[attribute] = value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.collection_from_pet_type_and_registries(pet_type, info_registry, asset_registry)
|
||||
# bear in mind that registries are arrays with many nil elements,
|
||||
# due to how the parser works
|
||||
items = {}
|
||||
item_ids = []
|
||||
info_registry.each do |info|
|
||||
if info
|
||||
item_ids << info[:obj_info_id].to_i
|
||||
end
|
||||
end
|
||||
existing_relationships_by_item_id_and_swf_asset_id = {}
|
||||
existing_items = Item.find_all_by_id(item_ids, :include => :parent_swf_asset_relationships)
|
||||
existing_items.each do |item|
|
||||
items[item.id] = item
|
||||
relationships_by_swf_asset_id = {}
|
||||
item.parent_swf_asset_relationships.each do |relationship|
|
||||
relationships_by_swf_asset_id[relationship.swf_asset_id] = relationship
|
||||
end
|
||||
existing_relationships_by_item_id_and_swf_asset_id[item.id] =
|
||||
relationships_by_swf_asset_id
|
||||
end
|
||||
swf_asset_ids = []
|
||||
asset_registry.each_with_index do |asset_data, index|
|
||||
swf_asset_ids << index if asset_data
|
||||
end
|
||||
existing_swf_assets = SwfAsset.find_all_by_id(swf_asset_ids)
|
||||
existing_swf_assets_by_id = {}
|
||||
existing_swf_assets.each do |swf_asset|
|
||||
existing_swf_assets_by_id[swf_asset.id] = swf_asset
|
||||
end
|
||||
relationships_by_item_id = {}
|
||||
asset_registry.each do |asset_data|
|
||||
if asset_data
|
||||
item_id = asset_data[:obj_info_id].to_i
|
||||
item = items[item_id]
|
||||
unless item
|
||||
item = Item.new
|
||||
item.id = item_id
|
||||
items[item_id] = item
|
||||
end
|
||||
item.origin_registry_info = info_registry[item.id]
|
||||
swf_asset_id = asset_data[:asset_id].to_i
|
||||
swf_asset = existing_swf_assets[swf_asset_id]
|
||||
unless swf_asset
|
||||
swf_asset = SwfAsset.new
|
||||
swf_asset.id = swf_asset_id
|
||||
end
|
||||
swf_asset.origin_object_data = asset_data
|
||||
swf_asset.origin_pet_type = pet_type
|
||||
relationship = existing_relationships_by_item_id_and_swf_asset_id[item.id][swf_asset_id] rescue nil
|
||||
unless relationship
|
||||
relationship = ParentSwfAssetRelationship.new
|
||||
relationship.parent_id = item.id
|
||||
relationship.swf_asset_type = SwfAssetType
|
||||
relationship.swf_asset_id = swf_asset.id
|
||||
end
|
||||
relationship.swf_asset = swf_asset
|
||||
relationships_by_item_id[item_id] ||= []
|
||||
relationships_by_item_id[item_id] << relationship
|
||||
end
|
||||
end
|
||||
relationships_by_item_id.each do |item_id, relationships|
|
||||
items[item_id].parent_swf_asset_relationships = relationships
|
||||
end
|
||||
items.values
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
SearchFilterScopes = []
|
||||
|
|
55
app/models/pet.rb
Normal file
55
app/models/pet.rb
Normal file
|
@ -0,0 +1,55 @@
|
|||
class Pet < ActiveRecord::Base
|
||||
GATEWAY_URL = 'http://www.neopets.com/amfphp/gateway.php'
|
||||
AMF_SERVICE_NAME = 'CustomPetService'
|
||||
PET_VIEWER_METHOD = 'getViewerData'
|
||||
PET_NOT_FOUND_REMOTE_ERROR = 'PHP: Unable to retrieve records from the database.'
|
||||
|
||||
belongs_to :pet_type
|
||||
|
||||
attr_reader :items
|
||||
|
||||
def load!
|
||||
require 'ostruct'
|
||||
begin
|
||||
envelope = Pet.amf_service.fetch(PET_VIEWER_METHOD, name, nil)
|
||||
rescue RocketAMF::RemoteGateway::AMFError => e
|
||||
if e.message == PET_NOT_FOUND_REMOTE_ERROR
|
||||
raise PetNotFound, "Pet #{name.inspect} does not exist"
|
||||
end
|
||||
raise
|
||||
end
|
||||
contents = OpenStruct.new(envelope.messages[0].data.body)
|
||||
pet_data = OpenStruct.new(contents.custom_pet)
|
||||
self.pet_type = PetType.find_or_initialize_by_species_id_and_color_id(
|
||||
pet_data.species_id.to_i,
|
||||
pet_data.color_id.to_i
|
||||
)
|
||||
self.pet_type.body_id = pet_data.body_id
|
||||
@pet_state = self.pet_type.add_pet_state_from_biology! pet_data.biology_by_zone
|
||||
@items = Item.collection_from_pet_type_and_registries(self.pet_type,
|
||||
contents.object_info_registry, contents.object_asset_registry)
|
||||
true
|
||||
end
|
||||
|
||||
def self.load(name)
|
||||
pet = Pet.find_or_initialize_by_name(name)
|
||||
pet.load!
|
||||
pet
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def self.amf_service
|
||||
@amf_service ||= gateway.service AMF_SERVICE_NAME
|
||||
end
|
||||
|
||||
def self.gateway
|
||||
unless @gateway
|
||||
require 'rocketamf/remote_gateway'
|
||||
@gateway = RocketAMF::RemoteGateway.new(GATEWAY_URL)
|
||||
end
|
||||
@gateway
|
||||
end
|
||||
|
||||
class PetNotFound < Exception;end
|
||||
end
|
|
@ -1,4 +1,73 @@
|
|||
class PetState < ActiveRecord::Base
|
||||
include SwfAssetParent
|
||||
SwfAssetType = 'biology'
|
||||
|
||||
has_many :parent_swf_asset_relationships, :foreign_key => 'parent_id',
|
||||
:conditions => {:swf_asset_type => SwfAssetType}
|
||||
has_many :swf_assets, :through => :parent_swf_asset_relationships
|
||||
|
||||
belongs_to :pet_type
|
||||
|
||||
alias_method :swf_asset_ids_from_association, :swf_asset_ids
|
||||
|
||||
def swf_asset_ids
|
||||
self['swf_asset_ids']
|
||||
end
|
||||
|
||||
def swf_asset_ids=(ids)
|
||||
self['swf_asset_ids'] = ids
|
||||
end
|
||||
|
||||
def self.from_pet_type_and_biology_info(pet_type, info)
|
||||
swf_asset_ids = []
|
||||
info.each do |asset_info|
|
||||
if asset_info
|
||||
swf_asset_ids << asset_info[:part_id].to_i
|
||||
end
|
||||
end
|
||||
swf_asset_ids_str = swf_asset_ids.join(',')
|
||||
if pet_type.new_record?
|
||||
pet_state = self.new :swf_asset_ids => swf_asset_ids_str
|
||||
else
|
||||
pet_state = self.find_or_initialize_by_pet_type_id_and_swf_asset_ids(
|
||||
pet_type.id,
|
||||
swf_asset_ids_str
|
||||
)
|
||||
end
|
||||
existing_swf_assets = SwfAsset.find_all_by_id(swf_asset_ids)
|
||||
existing_swf_assets_by_id = {}
|
||||
existing_swf_assets.each do |swf_asset|
|
||||
existing_swf_assets_by_id[swf_asset.id] = swf_asset
|
||||
end
|
||||
existing_relationships_by_swf_asset_id = {}
|
||||
unless pet_state.new_record?
|
||||
pet_state.parent_swf_asset_relationships.each do |relationship|
|
||||
existing_relationships_by_swf_asset_id[relationship.swf_asset_id] = relationship
|
||||
end
|
||||
end
|
||||
pet_state.pet_type = pet_type # save the second case from having to look it up by ID
|
||||
relationships = []
|
||||
info.each do |asset_info|
|
||||
if asset_info
|
||||
swf_asset_id = asset_info[:part_id].to_i
|
||||
swf_asset = existing_swf_assets_by_id[swf_asset_id]
|
||||
unless swf_asset
|
||||
swf_asset = SwfAsset.new
|
||||
swf_asset.id = swf_asset_id
|
||||
end
|
||||
swf_asset.origin_biology_data = asset_info
|
||||
swf_asset.origin_pet_type = pet_type
|
||||
relationship = existing_relationships_by_swf_asset_id[swf_asset_id]
|
||||
unless relationship
|
||||
relationship ||= ParentSwfAssetRelationship.new
|
||||
relationship.parent_id = pet_state.id
|
||||
relationship.swf_asset_type = SwfAssetType
|
||||
relationship.swf_asset_id = swf_asset.id
|
||||
end
|
||||
relationship.swf_asset = swf_asset
|
||||
relationships << relationship
|
||||
end
|
||||
end
|
||||
pet_state.parent_swf_asset_relationships = relationships
|
||||
pet_state
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,7 +3,6 @@ class PetType < ActiveRecord::Base
|
|||
|
||||
BasicHashes = YAML::load_file(Rails.root.join('config', 'basic_type_hashes.yml'))
|
||||
|
||||
|
||||
StandardBodyIds = PetType.select(arel_table[:body_id]).
|
||||
where(arel_table[:color_id].in(Color::BasicIds)).
|
||||
group(arel_table[:species_id]).map(&:body_id)
|
||||
|
@ -55,4 +54,10 @@ class PetType < ActiveRecord::Base
|
|||
def image_hash
|
||||
BasicHashes[species.name][color.name]
|
||||
end
|
||||
|
||||
def add_pet_state_from_biology!(biology)
|
||||
pet_state = PetState.from_pet_type_and_biology_info(self, biology)
|
||||
self.pet_states << pet_state
|
||||
pet_state
|
||||
end
|
||||
end
|
||||
|
|
|
@ -33,4 +33,21 @@ class SwfAsset < ActiveRecord::Base
|
|||
def zone
|
||||
@zone ||= Zone.find(zone_id)
|
||||
end
|
||||
|
||||
def origin_pet_type=(pet_type)
|
||||
self.body_id = pet_type.body_id
|
||||
end
|
||||
|
||||
def origin_biology_data=(data)
|
||||
self.type = 'biology'
|
||||
self.zone_id = data[:zone_id].to_i
|
||||
self.url = data[:asset_url]
|
||||
self.zones_restrict = data[:zones_restrict]
|
||||
end
|
||||
|
||||
def origin_object_data=(data)
|
||||
self.type = 'object'
|
||||
self.zone_id = data[:zone_id].to_i
|
||||
self.url = data[:asset_url]
|
||||
end
|
||||
end
|
||||
|
|
10
lib/deferred_attributes.rb
Normal file
10
lib/deferred_attributes.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
module DeferredAttributes
|
||||
def attr_deferred(name, &block)
|
||||
instance_variable_name = "@#{name}"
|
||||
define_method name do
|
||||
value = instance_variable_get(instance_variable_name)
|
||||
return value if value
|
||||
instance_variable_set(instance_variable_name, self.instance_eval(&block))
|
||||
end
|
||||
end
|
||||
end
|
18
lib/rocketamf/remote_gateway.rb
Normal file
18
lib/rocketamf/remote_gateway.rb
Normal file
|
@ -0,0 +1,18 @@
|
|||
require 'net/http'
|
||||
require 'rocketamf'
|
||||
require_relative 'remote_gateway/service'
|
||||
require_relative 'remote_gateway/request'
|
||||
|
||||
module RocketAMF
|
||||
class RemoteGateway
|
||||
attr_reader :uri
|
||||
|
||||
def initialize(url)
|
||||
@uri = URI.parse url
|
||||
end
|
||||
|
||||
def service(name)
|
||||
Service.new(self, name)
|
||||
end
|
||||
end
|
||||
end
|
74
lib/rocketamf/remote_gateway/request.rb
Normal file
74
lib/rocketamf/remote_gateway/request.rb
Normal file
|
@ -0,0 +1,74 @@
|
|||
module RocketAMF
|
||||
class RemoteGateway
|
||||
class Request
|
||||
ERROR_CODE = 'AMFPHP_RUNTIME_ERROR'
|
||||
|
||||
def initialize(service, method, *params)
|
||||
@service = service
|
||||
@method = method
|
||||
@params = params
|
||||
end
|
||||
|
||||
def fetch
|
||||
uri = @service.gateway.uri
|
||||
data = envelope.serialize
|
||||
|
||||
req = Net::HTTP::Post.new(uri.path)
|
||||
req.body = data
|
||||
res = Net::HTTP.new(uri.host, uri.port).start { |http| http.request(req) }
|
||||
case res
|
||||
when Net::HTTPSuccess, Net::HTTPRedirection
|
||||
result = RocketAMF::Envelope.new.populate_from_stream(res.body)
|
||||
first_message_data = result.messages[0].data
|
||||
if first_message_data.respond_to?(:[]) && first_message_data[:code] == ERROR_CODE
|
||||
raise AMFError.new(first_message_data)
|
||||
end
|
||||
return result
|
||||
else
|
||||
error = nil
|
||||
begin
|
||||
res.error!
|
||||
rescue Exception => scoped_error
|
||||
error = scoped_error
|
||||
end
|
||||
raise ConnectionError, "Error connecting to gateway: #{error}"
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def envelope
|
||||
output = Envelope.new
|
||||
output.messages << wrapper_message
|
||||
output
|
||||
end
|
||||
|
||||
def wrapper_message
|
||||
message = Message.new 'null', '/1', [remoting_message]
|
||||
end
|
||||
|
||||
def remoting_message
|
||||
message = Values::RemotingMessage.new
|
||||
message.source = @service.name
|
||||
message.operation = @method
|
||||
message.body = @params
|
||||
message
|
||||
end
|
||||
end
|
||||
|
||||
class ConnectionError < RuntimeError;end
|
||||
class AMFError < RuntimeError
|
||||
DATA_KEYS = [:details, :line, :code]
|
||||
attr_reader *DATA_KEYS
|
||||
attr_reader :message
|
||||
|
||||
def initialize(data)
|
||||
DATA_KEYS.each do |key|
|
||||
instance_variable_set "@#{key}", data[key]
|
||||
end
|
||||
|
||||
@message = data[:description]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
16
lib/rocketamf/remote_gateway/service.rb
Normal file
16
lib/rocketamf/remote_gateway/service.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
module RocketAMF
|
||||
class RemoteGateway
|
||||
class Service
|
||||
attr_reader :gateway, :name
|
||||
|
||||
def initialize(gateway, name)
|
||||
@gateway = gateway
|
||||
@name = name
|
||||
end
|
||||
|
||||
def fetch(method, *params)
|
||||
Request.new(self, method, *params).fetch
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,4 +1,4 @@
|
|||
Factory.define :pet_state do |ps|
|
||||
ps.pet_type_id 1
|
||||
ps.swf_asset_ids '1,2,3'
|
||||
ps.swf_asset_ids_cache '1,2,3'
|
||||
end
|
||||
|
|
BIN
vendor/cache/RocketAMF-0.2.1.gem
vendored
Normal file
BIN
vendor/cache/RocketAMF-0.2.1.gem
vendored
Normal file
Binary file not shown.
Loading…
Reference in a new issue