Class: Demiurge::ActionItem
- Defined in:
- lib/demiurge/action_item.rb
Overview
A Demiurge::ActionItem keeps track of actions from Ruby code blocks and implements the Demiurge DSL for action code, including inside World Files.
Constant Summary
- ACTION_LEGAL_KEYS =
Legal keys to pass to ActionItem#register_actions' hash
[ "name", "block", "busy", "engine_code", "tags" ]
Instance Attribute Summary
Attributes inherited from StateItem
Instance Method Summary collapse
-
#__state_internal ⇒ Hash
private
An internal function that provides the object's internal state to an action block via a Runner class.
-
#finished_init ⇒ void
Callback to be called from the Engine when all items are loaded.
-
#get_action(action_name) ⇒ Hash?
Get the action hash structure for a given action name.
-
#get_actions_with_tags(tags) ⇒ Array<Hash>
Return all actions which have the given String tags specified for them.
-
#initialize(name, engine, state) ⇒ void
constructor
Constructor.
-
#intentions_for_next_step ⇒ Array<Demiurge::Intention>
Get this item's intentions for the next tick.
-
#location ⇒ Demiurge::StateItem?
Get the location StateItem where this item is located.
-
#location_name ⇒ String?
Get the name of this item's location.
-
#position ⇒ String?
A Position can be simply a location ("here's a room-type object and you're in it") or something more specific, such as a specific coordinate within a room.
-
#register_actions(action_hash) ⇒ Object
This method is called by (among other things) define_action to specify things about an action.
-
#run_action(action_name, *args, current_intention: nil) ⇒ void
This is a raw, low-level way to execute an action of an ActionItem.
-
#zone ⇒ StateItem?
Get the StateItem of the Zone where this item is located.
-
#zone_name ⇒ String?
Get the Zone name for this StateItem's current location, which may be different from its "home" Zone.
Methods inherited from StateItem
#agent?, from_name_type, #get_structure, #state, #state_type, #zone?
Constructor Details
#initialize(name, engine, state) ⇒ void
Constructor. Set up ActionItem-specific things like EveryXTicks actions.
15 16 17 18 19 |
# File 'lib/demiurge/action_item.rb', line 15 def initialize(name, engine, state) super # Set @name and @engine and @state @every_x_ticks_intention = ActionItemInternal::EveryXTicksIntention.new(engine, name) nil end |
Instance Method Details
#__state_internal ⇒ Hash
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
An internal function that provides the object's internal state to an action block via a Runner class.
88 89 90 |
# File 'lib/demiurge/action_item.rb', line 88 def __state_internal @state end |
#finished_init ⇒ void
This method returns an undefined value.
Callback to be called from the Engine when all items are loaded.
25 26 27 28 29 |
# File 'lib/demiurge/action_item.rb', line 25 def finished_init loc = self.location loc.move_item_inside(self) unless loc.nil? nil end |
#get_action(action_name) ⇒ Hash?
Get the action hash structure for a given action name. This is normally done to verify that a specific action name exists at all.
181 182 183 184 185 186 187 188 |
# File 'lib/demiurge/action_item.rb', line 181 def get_action(action_name) action = @engine.action_for_item(@name, action_name) if !action && state["parent"] # Do we have a parent and no action definition yet? If so, defer to the parent. action = @engine.item_by_name(state["parent"]).get_action(action_name) end action end |
#get_actions_with_tags(tags) ⇒ Array<Hash>
Return all actions which have the given String tags specified for them.
195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/demiurge/action_item.rb', line 195 def () = [].flatten # Allow calling with a single tag string @actions = [] @engine.actions_for_item(@name).each do |action_name, action_struct| # I'm sure there's some more clever way to check if the action contains all these tags... if ( - (action_struct["tags"] || [])).empty? @actions.push action_struct end end @actions end |
#intentions_for_next_step ⇒ Array<Demiurge::Intention>
Get this item's intentions for the next tick.
96 97 98 99 100 |
# File 'lib/demiurge/action_item.rb', line 96 def intentions_for_next_step everies = @state["everies"] return [] if everies.nil? || everies.empty? [@every_x_ticks_intention] end |
#location ⇒ Demiurge::StateItem?
Get the location StateItem where this item is located.
46 47 48 49 50 |
# File 'lib/demiurge/action_item.rb', line 46 def location ln = location_name return nil if ln == "" || ln == nil @engine.item_by_name(location_name) end |
#location_name ⇒ String?
Get the name of this item's location. This is compatible with complex positions, and removes any sub-location suffix, if there is one.
37 38 39 40 |
# File 'lib/demiurge/action_item.rb', line 37 def location_name pos = @state["position"] pos ? pos.split("#",2)[0] : nil end |
#position ⇒ String?
A Position can be simply a location ("here's a room-type object and you're in it") or something more specific, such as a specific coordinate within a room. In general, a Position consists of a location's unique item name, optionally followed by an optional pound sign ("#") and zone-specific additional coordinates.
60 61 62 |
# File 'lib/demiurge/action_item.rb', line 60 def position @state["position"] end |
#register_actions(action_hash) ⇒ Object
This method is called by (among other things) define_action to specify things about an action. It's how to specify the action's code, how busy it makes an agent when it occurs, what Runner to use with it, and any appropriate String tags. While it can be called multiple times to specify different things about a single action, it must not be called with the same information. So the block can only be specified once, "busy" can only be specified once and so on.
This means that if an action's block is given implicitly by something like an every_X_ticks declaration, it can use define_action to set "busy" or "engine_code". But it can't define a different block of code to run with define_action.
125 126 127 |
# File 'lib/demiurge/action_item.rb', line 125 def register_actions(action_hash) @engine.register_actions_by_item_and_action_name(@name => action_hash) end |
#run_action(action_name, *args, current_intention: nil) ⇒ void
This method returns an undefined value.
This is a raw, low-level way to execute an action of an ActionItem. It doesn't wait for Intentions. It doesn't send extra notifications. It doesn't offer or give a chance to cancel the action. It just runs.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/demiurge/action_item.rb', line 139 def run_action(action_name, *args, current_intention: nil) action = get_action(action_name) raise ::Demiurge::Errors::NoSuchActionError.new("No such action as #{action_name.inspect} for #{@name.inspect}!", "item" => self.name, "action" => action_name, execution_context: @engine.execution_context) unless action block = action["block"] raise ::Demiurge::Errors::NoSuchActionError.new("Action was never defined for #{action_name.inspect} of object #{@name.inspect}!", "item" => self.name, "action" => action_name, execution_context: @engine.execution_context) unless block runner_constructor_args = {} if action["engine_code"] block_runner_type = ActionItemInternal::EngineBlockRunner elsif self.agent? block_runner_type = ActionItemInternal::AgentBlockRunner runner_constructor_args[:current_intention] = current_intention else block_runner_type = ActionItemInternal::ActionItemBlockRunner runner_constructor_args[:current_intention] = current_intention end # TODO: can we save block runners between actions? block_runner = block_runner_type.new(self, **runner_constructor_args) begin @engine.push_context("running_action" => action_name, "running_action_item" => @name) do block_runner.instance_exec(*args, &block) end rescue #STDERR.puts "#{$!.message}\n#{$!.backtrace.join("\n")}" raise ::Demiurge::Errors::BadScriptError.new("Script error of type #{$!.class} with message: #{$!.}", { "runner type": block_runner_type.to_s, "action" => action_name, }, execution_context: @engine.execution_context); end nil end |
#zone ⇒ StateItem?
Get the StateItem of the Zone where this item is located. This may be different from its "home" Zone.
68 69 70 71 |
# File 'lib/demiurge/action_item.rb', line 68 def zone zn = zone_name zn ? @engine.item_by_name(zn) : nil end |
#zone_name ⇒ String?
Get the Zone name for this StateItem's current location, which may be different from its "home" Zone.
77 78 79 80 |
# File 'lib/demiurge/action_item.rb', line 77 def zone_name l = location l ? l.zone_name : state["zone"] end |