module FelFlame module Components @component_map = [] class <] def addition_triggers @addition_triggers ||= [] end # Stores references to systems that should be triggered when a # component from this manager is removed. # Do not edit this array as it is managed by FelFlame automatically. # @return [Array] def removal_triggers @removal_triggers ||= [] end # Stores references to systems that should be triggered when an # attribute from this manager is changed. # Do not edit this hash as it is managed by FelFlame automatically. # @return [Hash>] def attr_triggers @attr_triggers ||= {} end # Creates a new component and sets the values of the attributes given to it. If an attritbute is not passed then it will remain as the default. # @param attrs [Keyword: Value] You can pass any number of Keyword-Value pairs # @return [Component] def initialize(**attrs) # Prepare the object # (this is a function created with metaprogramming # in FelFlame::Components) set_defaults # Fill params attrs.each do |key, value| send "#{key}=", value end # Save Component self.class.push self end class <] def addition_triggers @addition_triggers ||= [] end # Stores references to systems that should be triggered when this # component is removed from an enitity. # Do not edit this array as it is managed by FelFlame automatically. # @return [Array] def removal_triggers @removal_triggers ||= [] end # Stores references to systems that should be triggered when an # attribute from this component changed. # Do not edit this hash as it is managed by FelFlame automatically. # @return [Hash] def attr_triggers @attr_triggers ||= {} end # @return [Array] Array of all Components that belong to a given component manager # @!visibility private def _data @data ||= [] end end # Entities that have this component # @return [Array] def entities @entities ||= [] end # A single entity. Use this if you expect the component to only belong to one entity and you want to access it. # @return [Component] def entity if entities.empty? Warning.warn("This component belongs to NO entities but you called the method that is intended for components belonging to a single entity.\nYou may have a bug in your logic.") elsif entities.length > 1 Warning.warn("This component belongs to MANY entities but you called the method that is intended for components belonging to a single entity.\nYou may have a bug in your logic.") end entities.first end # Update attribute values using a hash or keywords. # @return [Hash] Hash of updated attributes def update_attrs(**opts) opts.each do |key, value| send "#{key}=", value end end # Execute systems that have been added to execute on variable change # @return [Boolean] +true+ def attr_changed_trigger_systems(attr) systems_to_execute = self.class.attr_triggers[attr] systems_to_execute = [] if systems_to_execute.nil? systems_to_execute |= attr_triggers[attr] unless attr_triggers[attr].nil? systems_to_execute.sort_by(&:priority).reverse_each(&:call) true end # Removes this component from the list and purges all references to this Component from other Entities, as well as its data. # @return [Boolean] +true+. def delete addition_triggers.each do |system| system.clear_triggers component_or_manager: self end entities.reverse_each do |entity| entity.remove self end self.class._data.delete self instance_variables.each do |var| instance_variable_set(var, nil) end true end # @return [Hash] A hash, where all the keys are attributes linked to their respective values. def to_h return_hash = instance_variables.each_with_object({}) do |key, final| final[key.to_s.delete_prefix('@').to_sym] = instance_variable_get(key) end return_hash.delete(:attr_triggers) return_hash end # Export all data into a JSON String, which could then later be loaded or saved to a file # TODO: This function is not yet complete # @return [String] a JSON formatted String #def to_json # # should return a json or hash of all data in this component #end end end