Skip to content

Instantly share code, notes, and snippets.

@litvil
Created January 13, 2016 17:06
Show Gist options
  • Save litvil/6190e9c4ca73499b7eb4 to your computer and use it in GitHub Desktop.
Save litvil/6190e9c4ca73499b7eb4 to your computer and use it in GitHub Desktop.
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