Created
January 13, 2016 17:06
-
-
Save litvil/6190e9c4ca73499b7eb4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Rooms | |
HOME = 0 | |
RANCH = 1 | |
end | |
class RoomController < UserController | |
CONTROLLER_MANIFEST = { | |
:common_methods => { # common methods, that controller responds to | |
:to_xml => :to_xml, | |
:to_friend_xml => :to_friend_xml, | |
:save => {:name => :save!, :need_init => true} | |
}, | |
:commands => { #commands, that controller can perform | |
:upgrade_room_cluster => :upgrade_cluster, | |
:change_room => :on_change_room, | |
:accelerate_room_cluster => :accelerate | |
}, | |
:config_section => :rooms | |
} | |
attr_accessor :data | |
DEFAULT_ROOM_INFO = "{\"rooms\":{\"0\":{\"clusters\":{\"0\":{\"state:\"1, \"end_stage:\"0}}}}}" | |
def initialize(user) | |
super | |
refresh | |
unlock_room(Rooms::HOME) if rooms_data.empty? | |
end | |
def to_xml | |
@data.present? ? " room_information='#{@data.to_json}' " : '' | |
end | |
def to_friend_xml(friend) | |
data = friend.room_information | |
data.present? ? " friend_room_information='#{data}' " : '' | |
end | |
def upgrade_cluster(data) | |
room = (data[:in_room] || current_room).to_i | |
cluster = data[:cluster_id].to_i | |
res = check_and_upgrade_cluster(room, cluster) | |
res | |
end | |
def accelerate(data) | |
room = (data[:in_room] || current_room).to_i | |
cluster = data[:cluster_id].to_i | |
cluster_data = get_cluster_data(room,cluster) | |
raise DZError.new('Nothing to accelerate', "Room: #{room}; Cluster: #{cluster}") unless cluster_data.present? | |
raise DZError.new('Not need to accelerate cluster', "Room: #{room}; Cluster: #{cluster}") if cluster_data['end_state'] <= @user.current_time.to_i | |
time_remain = cluster_data['end_state'] - @user.current_time.to_i | |
@user.with_acceleration(time_remain, data, nil, 'accelerate_unlock_room'){|need_gold| | |
cluster_data['end_state'] = @user.current_time.to_i | |
} | |
end | |
def refresh | |
@data = JSON.parse(@user.room_information || '{}') | |
self | |
end | |
def save! | |
@user.room_information = @data.to_json | |
end | |
def check_and_upgrade_cluster(room, cluster, force = false) | |
cluster = get_leader_cluster(room, cluster) | |
config = RoomController.get_cluster_config(room, cluster) | |
next_state = get_cluster_state(room, cluster) + 1 | |
check_and_give_rewards(room, cluster, next_state) unless force | |
upgrade_cluster_state(room, cluster) | |
current_state = get_cluster_state(room, cluster) | |
if config['linked_to'].is_a?(Array) | |
config['linked_to'].each{|cluster_id| | |
states_diff = current_state - get_cluster_state(room, cluster_id) | |
next if states_diff <= 0 | |
states_diff.times{ | |
upgrade_cluster_state(room, cluster_id) | |
} | |
} | |
end | |
return true if force | |
if current_state == RoomController.get_final_state(room, cluster) | |
place_stage_items(room, cluster) | |
end | |
true | |
end | |
def check_and_give_rewards(room, cluster = 0, state = nil) | |
Application.logger.info('Check and give reward') | |
config = RoomController.get_cluster_config(room, cluster) | |
raise DZError.new('Cannot upgrade cluster', "Room: #{room}; Cluster: #{cluster}") unless can_upgrade_cluster?(room, cluster) | |
cluster_data = get_cluster_data(room, cluster) | |
state ||= cluster_data['state'].present? ? cluster_data['state'] : 0 | |
state_config = config['object_states'][state] | |
Application.logger.info("Upgrade cluster #{cluster} state #{state}") | |
raise DZError.new('Cannot find state for cluster', "Room: #{room}; Cluster: #{cluster}; State: #{state}") unless state_config | |
ABTestController.with_patched_config(:rooms, @user){ | |
Application.logger.info("Give user items room #{room} and cluster #{cluster}") | |
@user.inventory_controller.without_storage_check {@user.reward_controller.with_reward({}, state_config['drop'], 'upgrade') {}} | |
} | |
end | |
def can_upgrade_cluster?(room, cluster) | |
cluster_config = RoomController.get_cluster_config(room, cluster) | |
raise DZError.new('Cannot find config for cluster', "Room: #{room}; Cluster: #{cluster}") unless cluster_config | |
cluster_data = get_cluster_data(room, cluster) | |
return false if cluster_data.present? && cluster_data['end_state'] > @user.current_time.to_i | |
neighbours = cluster_config['neighbours'] | |
return true unless neighbours | |
neighbours.each{|id| return true if is_cluster_unlocked(room,id.to_s)} | |
false | |
end | |
def place_stage_items(room, cluster = nil) | |
Application.logger.info('Placing stage items on room ' << room.to_s) | |
cluster ||= RoomController.get_room_config(room)['default_cluster'] | |
clear_room(room.to_i) if cluster == RoomController.get_room_config(room)['default_cluster'] | |
@user.cached_stage_items.without_retry do | |
place_items_by_yaml(room.to_i, cluster) | |
end | |
end | |
def upgrade_cluster_state(room, cluster) | |
cluster_data = get_cluster_data(room, cluster, true) | |
cluster_data['state'] = cluster_data['state'].present? ? cluster_data['state'] + 1 : 0 | |
stage_config = RoomController.get_cluster_config(room, cluster)['object_states'][cluster_data['state']] | |
raise DZError.new('Cannot find state for cluster', "Room: #{room}; Cluster: #{cluster}; State: #{cluster_data['state']}") unless stage_config | |
end_time = (StageItem.parse_stage_length(stage_config['stage_length']) || 0).to_i | |
cluster_data['end_state'] = @user.current_time.to_i + end_time | |
end | |
def unlock_room(room) | |
default_cluster = RoomController.get_room_config(room)['default_cluster'] | |
(RoomController.get_final_state(room, default_cluster) + 1).times{ | |
check_and_upgrade_cluster(room, default_cluster, true) | |
} | |
end | |
def lock_room(room) | |
return unless is_room_available?(room) | |
@data.delete(room) | |
end | |
def get_leader_cluster(room, cluster) | |
config = RoomController.get_cluster_config(room, cluster) | |
return cluster if config['leader'] || !config['linked_to'].is_a?(Array) | |
config['linked_to'].each{|cluster_id| | |
return cluster_id if RoomController.get_cluster_config(room, cluster_id)['leader'] | |
} | |
cluster | |
end | |
def get_unlocked_clusters(room) | |
get_clusters_data(room).select{|id, data| data['state'] == RoomController.get_final_state(room, id)} | |
end | |
def get_cluster_state(room, cluster) | |
cluster_data = get_cluster_data(room, cluster) | |
cluster_data.present? && cluster_data['state'].present? ? cluster_data['state'].to_i : -1 | |
end | |
def get_cluster_data(room, cluster, initialize = false) | |
cluster = cluster.to_s | |
get_clusters_data(room)[cluster] ||= {} if initialize | |
get_clusters_data(room)[cluster] | |
end | |
def get_clusters_data(room) | |
get_room_data(room)['clusters'] ||= {} | |
end | |
def get_room_data(room) | |
room = room.to_s | |
rooms_data[room] ||= {} | |
rooms_data[room] | |
end | |
def rooms_data | |
@data['rooms'] ||= {} | |
end | |
def current_room | |
@user.cached_stage_items.room | |
end | |
def is_room_available?(room) | |
room_data = get_room_data(room) | |
return false unless room_data.present? | |
default_cluster = RoomController.get_room_config(room)['default_cluster'] | |
is_cluster_unlocked(room, default_cluster) | |
end | |
def is_cluster_unlocked(room, cluster) | |
get_cluster_state(room, cluster) == RoomController.get_final_state(room, cluster) | |
end | |
def get_room_rectangle(room) | |
room_size_config = RoomController.get_room_config(room)['field'] | |
if room_size_config.present? | |
SQRect.new(room_size_config['position']['x'], room_size_config['position']['y'], room_size_config['size']['x'], room_size_config['size']['y']) | |
else | |
room_rectangle = SQRect.new | |
get_unlocked_clusters(room).each{|id, data| | |
cluster_rectangle = RoomController.get_cluster_rect(room, id) | |
room_rectangle.left = cluster_rectangle.left if cluster_rectangle.left < room_rectangle.left | |
room_rectangle.right = cluster_rectangle.right if cluster_rectangle.right > room_rectangle.right | |
room_rectangle.top = cluster_rectangle.top if cluster_rectangle.top > room_rectangle.top | |
room_rectangle.bottom = cluster_rectangle.bottom if cluster_rectangle.bottom < room_rectangle.bottom | |
} | |
room_rectangle | |
end | |
end | |
def check_coordinates(item_rect, room = nil) | |
room ||= current_room | |
room_config = RoomController.get_room_config(room) | |
if room_config['field'].present? && room_config['field']['full_check'] | |
get_unlocked_clusters(room).each{|id, data| | |
return true if SQRect.include_coords?(RoomController.get_cluster_rect(room, id), item_rect.x, item_rect.y) | |
} | |
else | |
return SQRect.include_coords?(get_room_rectangle(room), item_rect.x, item_rect.y) | |
end | |
false | |
end | |
def to_room(room = Rooms::HOME, check_availability = true) | |
return if room.to_i == current_room | |
raise DZError.new('Room is not available', "Room: #{room}") if check_availability && !is_room_available?(room) | |
@user.cached_stage_items.set_room(room) | |
end | |
def change_room_by_request_params(params) | |
return if params.nil? | |
to_room(params[:room_id].to_i) | |
end | |
def with_room(room, stay_in_room = false, check_availability = true) | |
room = room.to_i | |
last_room = current_room | |
to_room(room, check_availability) | |
yield | |
to_room(last_room, check_availability) unless stay_in_room | |
end | |
def with_all_rooms(check_availability = true) | |
last_room = current_room || Rooms::HOME | |
rooms_data.each_key{|room| | |
room = room.to_i | |
next if check_availability && !is_room_available?(room) | |
with_room(room, true, check_availability) { | |
yield(room) | |
} | |
} | |
to_room(last_room) | |
end | |
def on_change_room(data) | |
raise DZNilValueError.new('room_id') if data[:room_id].blank? | |
raise DZNilValueError.new('old_room_id') if data[:old_room_id].blank? | |
raise DZValidationError.new('Room locked', "Room: #{data[:room_id]}") unless is_room_available?(data[:room_id]) | |
Application.logger.info "Changing room from #{data[:old_room_id]} to #{data[:room_id]}" | |
end | |
def self.get_cluster_rect(room, cluster) | |
cluster_config = RoomController.get_cluster_config(room, cluster) | |
SQRect.new(cluster_config['position']['x'], cluster_config['position']['y'], cluster_config['size']['x'], cluster_config['size']['y']) | |
end | |
def self.get_final_state(room, cluster) | |
get_cluster_config(room, cluster)['object_states'].size - 1 | |
end | |
def self.get_cluster_config(room, cluster) | |
clusters_config = self.get_room_config(room)['clusters'] | |
return nil unless clusters_config | |
clusters_config[cluster.to_i] | |
end | |
def self.get_room_config(room) | |
self.config[room.to_i] | |
end | |
def get_field_config(room) | |
ABTestController.with_patched_config(:rooms, @user){ | |
RoomController.get_room_config(room)['field_config'].each{|field_config| | |
next unless @user.check_require_config(field_config['require']).blank? | |
return field_config | |
} | |
} | |
end | |
def self.load_fields_config | |
config.each do |_, room| | |
field_keys = room.keys.select{|field| field.start_with?('field_config')} | |
field_keys.each do |field_key| | |
room[field_key].each{|preset_config| | |
path = preset_config['file'] | |
preset_config.merge!(RoomController.load_yml_field(File.join(Application.config_path, path))) | |
} | |
end | |
end | |
end | |
def self.load_yml_field(filename) | |
DZError.new('Can\'t find field config', "Field config file name: #{filename}") unless File.file?(filename) | |
YAML.load(Tfp.load(filename)) | |
end | |
def clear_room(room=nil) | |
Application.logger.info('Clear room ' << room.to_s) | |
with_room(room, false, false){ | |
items = @user.cached_stage_items.select_all | |
need_flush =false | |
items.each { |item| | |
@user.cached_stage_items.delete(item.id) | |
item.destroy_without_transactions | |
need_flush = true | |
} | |
Application.logger.info("Deleted #{items.count} stage items") | |
@user.cached_stage_items.flush if need_flush | |
} | |
end | |
def place_items_by_yaml(room=nil, cluster = nil) | |
Application.logger.info('Place items by yaml in room ' << room.to_s) | |
cluster ||= RoomController.get_room_config(room)['default_cluster'] | |
cluster = cluster.to_i | |
room ||= Rooms::HOME | |
with_room(room, false, false){ | |
exist = @user.cached_stage_items.map_with_primitives{|k, v| v} | |
field_xml = @user.room_controller.get_field_config(room) | |
return unless field_xml['field'][cluster].present? | |
items_count = 0 | |
field_xml['field'][cluster].each { |field_item| | |
items_count += create_item_with_params(field_item, exist).nil? ? 0 : 1 | |
} | |
Application.logger.info("Created #{items_count} stage items" ) | |
} | |
end | |
def create_item_with_params(params, exist) | |
return nil if params == nil | |
return nil if exist.any?{|v| v.x_coord == params['x'] && v.y_coord == params['y']} # && v.type == field_item["type"]} | |
options = params.symbolize_keys!.clone | |
options.delete(:data) if options[:data].blank? | |
extra_params = options.delete(:extra_params) | |
obj = StageItem.check_klass_and_give(params[:item_class]) | |
contained_items = params[:contained_items] | |
options[:contained_items] = {} if options[:contained_items] | |
params = { | |
:user_id => @user.id, | |
:user=>@user, | |
:dont_drop_user_cache=>true, | |
:to_create => options, | |
:room => @user.cached_stage_items.room | |
} | |
begin | |
obj = obj.new(params) | |
extra_params.each do |param, value| | |
obj.send((param+'=').to_sym, value) | |
end unless extra_params.nil? | |
obj.save_without_transactions! | |
@user.item_id_controller.apply_object_on_field(obj) | |
if contained_items.present? | |
contained_items.each{|contained_params| | |
contained_obj = create_item_with_params(contained_params, exist) | |
obj.register_contained_object(contained_obj) | |
} | |
end | |
return obj | |
rescue | |
raise DZError.new('Can\'t create object', "Class: #{params[:item_class]}") | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment