summaryrefslogtreecommitdiffhomepage
path: root/lib/felflame/component_manager.rb
diff options
context:
space:
mode:
author_Tradam <[email protected]>2021-12-30 07:33:12 -0500
committerGitHub <[email protected]>2021-12-30 07:33:12 -0500
commit5ef652300e71b572ca58b061610d606840ce19a9 (patch)
treeb82c99051b378c18ad4a8af98292681869dfa5a7 /lib/felflame/component_manager.rb
parentac8888f6682c68d74bfb362789fb43044e1c0961 (diff)
downloadFelECS-5ef652300e71b572ca58b061610d606840ce19a9.tar.gz
FelECS-5ef652300e71b572ca58b061610d606840ce19a9.zip
Major 4.0 update (#12)
Check the changelog
Diffstat (limited to 'lib/felflame/component_manager.rb')
-rw-r--r--lib/felflame/component_manager.rb128
1 files changed, 66 insertions, 62 deletions
diff --git a/lib/felflame/component_manager.rb b/lib/felflame/component_manager.rb
index 43932d2..ca5be89 100644
--- a/lib/felflame/component_manager.rb
+++ b/lib/felflame/component_manager.rb
@@ -1,8 +1,7 @@
-class FelFlame
- class Components
+module FelFlame
+ module Components
@component_map = []
class <<self
- include Enumerable
# Creates a new {FelFlame::ComponentManager component manager}.
#
# @example
@@ -46,10 +45,26 @@ class FelFlame
FelFlame::Components.const_get(component_name)
end
- # Iterate over all existing component managers. You also call other enumerable methods instead of each, such as +each_with_index+ or +select+
- # @return [Enumerator]
- def each(&block)
- constants.each(&block)
+ # Makes component module behave like an array of component
+ # managers with additional methods for managing the array
+ # @!visibility private
+ def respond_to_missing?(method, *)
+ if constants.respond_to? method
+ true
+ else
+ super
+ end
+ end
+
+ # Makes component module behave like arrays with additional
+ # methods for managing the array
+ # @!visibility private
+ def method_missing(method, *args, **kwargs, &block)
+ if constants.respond_to? method
+ constants.send(method, *args, **kwargs, &block)
+ else
+ super
+ end
end
end
end
@@ -58,16 +73,6 @@ class FelFlame
# When a Component is created from a Component Manager that has accessors given to it, you can set or get the values of those accessors using standard ruby message sending (e.g [email protected] = 5+), or by using the {#attrs} and {#update_attrs} methods instead.
class ComponentManager
- # Holds the {id unique ID} of a component. The {id ID} is only unique within the scope of the component manager it was created from.
- # @return [Integer]
- attr_reader :id
-
- # A seperate attr_writer was made for documentation readability reasons.
- # Yard will list attr_reader is readonly which is my intention.
- # This value needs to be changable as it is set by other functions.
- # @!visibility private
- attr_writer :id
-
# Allows overwriting the storage of triggers, such as for clearing.
# This method should generally only need to be used internally and
# not by a game developer.
@@ -104,25 +109,43 @@ class FelFlame
def initialize(**attrs)
# Prepare the object
# (this is a function created with metaprogramming
- # in FelFlame::Components
+ # in FelFlame::Components)
set_defaults
- # Generate ID
- new_id = self.class.data.find_index { |i| i.nil? }
- new_id = self.class.data.size if new_id.nil?
- @id = new_id
-
# Fill params
attrs.each do |key, value|
send "#{key}=", value
end
# Save Component
- self.class.data[new_id] = self
+ self.class.push self
end
class <<self
+ # Makes component managers behave like arrays with additional
+ # methods for managing the array
+ # @!visibility private
+ def respond_to_missing?(method, *)
+ if self._data.respond_to? method
+ true
+ else
+ super
+ end
+ end
+
+ # Makes component managers behave like arrays with additional
+ # methods for managing the array
+ # @!visibility private
+ def method_missing(method, *args, **kwargs, &block)
+ if self._data.respond_to? method
+ self._data.send(method, *args, **kwargs, &block)
+ else
+ super
+ end
+ end
+
+
# Allows overwriting the storage of triggers, such as for clearing.
# This method should generally only need to be used internally and
# not by a game developer.
@@ -155,41 +178,28 @@ class FelFlame
# @return [Array<Component>] Array of all Components that belong to a given component manager
# @!visibility private
- def data
+ def _data
@data ||= []
end
-
- # Gets a Component from the given {id unique ID}. Usage is simular to how an Array lookup works.
- #
- # @example
- # # this gets the 'Health' Component with ID 7
- # FelFlame::Components::Health[7]
- # @param component_id [Integer]
- # @return [Component] Returns the Component that uses the given unique {id ID}, nil if there is no Component associated with the given {id ID}
- def [](component_id)
- data[component_id]
- end
-
- # Iterates over all components within the component manager.
- # Special Enumerable methods like +map+ or +each_with_index+ are not implemented
- # @return [Enumerator]
- def each(&block)
- data.compact.each(&block)
- end
- end
-
- # An alias for the {id ID Reader}
- # @return [Integer]
- def to_i
- id
end
- # A list of entity ids that are linked to the component
- # @return [Array<Integer>]
+ # Entities that have this component
+ # @return [Array<Component>]
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<Symbol, Value>] Hash of updated attributes
def update_attrs(**opts)
@@ -206,25 +216,19 @@ class FelFlame
systems_to_execute |= attr_triggers[attr] unless attr_triggers[attr].nil?
- systems_to_execute.sort_by(&:priority).reverse.each(&:call)
+ 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 {id ID} and data.
+ # 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
- # This needs to be cloned because indices get deleted as
- # the remove command is called, breaking the loop if it
- # wasn't referencing a clone(will get Nil errors)
- iter = entities.map(&:clone)
- iter.each do |entity|
- #FelFlame::Entities[entity_id].remove self #unless FelFlame::Entities[entity_id].nil?
+ entities.reverse_each do |entity|
entity.remove self
end
- self.class.data[id] = nil
+ self.class._data.delete self
instance_variables.each do |var|
instance_variable_set(var, nil)
end
@@ -232,7 +236,7 @@ class FelFlame
end
# @return [Hash<Symbol, Value>] A hash, where all the keys are attributes linked to their respective values.
- def attrs
+ 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