Skip to content
This repository has been archived by the owner on Jan 4, 2023. It is now read-only.

Commit

Permalink
Merge pull request #33 from dmlary/issue/29-scripting
Browse files Browse the repository at this point in the history
Implemented scripting, enter/exit hooks, for teleporter rooms
  • Loading branch information
dmlary authored Dec 31, 2019
2 parents 9617b96 + 4c0f0a9 commit 389abcd
Show file tree
Hide file tree
Showing 20 changed files with 1,415 additions and 311 deletions.
24 changes: 15 additions & 9 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ source 'https://rubygems.org'

gem 'eventmachine'
gem 'colorize'
gem 'rspec'
gem 'rspec-mocks'
gem 'facets'
gem 'pry'
gem 'pry-remote'
gem 'pry-rescue'
gem 'pry-stack_explorer'
gem 'malloc_trim'
gem 'memory_profiler'
gem 'get_process_mem'
gem 'parser' # needed for lib/script.rb

group :test do
gem 'rspec'
gem 'rspec-mocks'
end

group :test, :development do
gem 'pry'
gem 'pry-remote'
gem 'pry-rescue'
gem 'pry-stack_explorer'
gem 'memory_profiler'
gem 'get_process_mem'
end
14 changes: 8 additions & 6 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
GEM
remote: https://rubygems.org/
specs:
ast (2.4.0)
binding_of_caller (0.8.0)
debug_inspector (>= 0.0.1)
coderay (1.1.2)
Expand All @@ -13,18 +14,19 @@ GEM
get_process_mem (0.2.5)
ffi (~> 1.0)
interception (0.5)
malloc_trim (0.1.0)
memory_profiler (0.9.14)
method_source (0.9.0)
pry (0.11.3)
method_source (0.9.2)
parser (2.7.0.0)
ast (~> 2.4.0)
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
pry-remote (0.1.8)
pry (~> 0.9)
slop (~> 3.0)
pry-rescue (1.4.5)
pry-rescue (1.5.0)
interception (>= 0.5)
pry
pry (>= 0.12.0)
pry-stack_explorer (0.4.9.3)
binding_of_caller (>= 0.7)
pry (>= 0.9.11)
Expand All @@ -51,8 +53,8 @@ DEPENDENCIES
eventmachine
facets
get_process_mem
malloc_trim
memory_profiler
parser
pry
pry-remote
pry-rescue
Expand Down
28 changes: 28 additions & 0 deletions data/world/base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -113,3 +113,31 @@
- viewable:
short: a red rubber ball
long: a red rubber ball is on the floor

- id: base:act/teleporter
components:
- hook:
event: :on_enter
script: base:script/teleporter/enter
- hook:
event: :on_exit
script: base:script/teleporter/exit
- teleporter

- id: base:script/teleporter/enter
components:
- script: !script |
here = args[:here]
unless porter = get_component(here, :teleporter)
error "#{here} missing teleporter component"
return
end
entity = args[:entity]
port = get_component!(entity, :teleport)
port[:dest] = porter[:dest]
port[:time] = now + porter[:delay]
- id: base:script/teleporter/exit
components:
- script: !script |
remove_component(args[:entity], :teleport)
11 changes: 11 additions & 0 deletions data/world/limbo/rooms.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
list:
- limbo:spawn/mob/puff
- limbo:spawn/obj/limbo-chest
- hook:
event: :on_enter
script: limbo:script/balls

- base: base:exit
link: base:room/void.exits.up
Expand Down Expand Up @@ -73,3 +76,11 @@
components:
- spawn:
entity: limbo:mob/puff

- id: limbo:script/balls
components:
- script: !script |
actor = args[:entity]
send_to_char(char: actor,
buf: "A small &Rred&0 ball appears in your hand!\n")
spawn_at(dest: actor, base: 'base:obj/junk/ball')
3 changes: 1 addition & 2 deletions lib/command/movement.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ def traverse_passage(actor, name)
else
dest = get_component(passage, :destination) or
fault "passage #{passage} has no destination!"
move_entity(entity: actor, dest: dest.entity)
Command::Look.show_room(actor, dest.entity)
move_entity(entity: actor, dest: dest.entity, look: true)
end
end
end
Expand Down
21 changes: 21 additions & 0 deletions lib/component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -257,4 +257,25 @@ def ==(other)
self.class == other.class && to_h == other.to_h
end
alias eql? ==

# []
#
# Get the value for a field. Slower method created to support Script.
def [](key)
key = key.to_sym unless key.is_a?(Symbol)
raise KeyError, "key not found: #{key}" unless
self.class.fields.include?(key)
send(key)
end

# []=
#
# Set the value for a field. Slower than calling the setter directly.
# Implemented to support Script.
def []=(key, value)
key = key.to_sym unless key.is_a?(Symbol)
raise KeyError, "key not found: #{key}" unless
self.class.fields.include?(key)
send("#{key}=", value)
end
end
74 changes: 74 additions & 0 deletions lib/components.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,80 @@ class ConnectionComponent < Component
field :buf, default: '' # String of pending output
end

# Used to run scripts when specific events occur in the world.
#
class HookComponent < Component
# due to compositing architecture, we're going to permit multiple hooks
not_unique

# Event when this script should be run
#
# will_enter: Entity (entity) will be added to (dest) entity's
# ContainerComponent. May be blocked by returning :deny.
# This hook will be called before the character performs 'look'
# in the dest room.
#
# Script arguments:
# entity: Entity being moved
# src: entity's current location; may be nil
# dest: destination entity
#
# on_enter: Entity (entity) has been added to (here) entity's
# ContainerComponent.
# This hook will be caled after the character performs 'look' in
# here.
#
# Script arguments:
# entity: Entity that was added
# here: entity's current location
#
# will_exit: Entity (entity) will removed from (src) entity's
# ContainerComponent. May be blocked by returning :deny.
# Script arguments:
#
# entity: Entity being moved
# src: entity's current location; may be nil
# dest: destination entity
#
# on_exit: Entity (entity) has been removed from (here) entity's
# ContainerComponent.
#
# Script arguments:
# entity: Entity that was removed
# here: entity's current location
field :event, valid: %i{ will_enter on_enter will_exit on_exit }

# This points at the entity id for the script that should be run
field :script
end

# This component holds configuration for a teleporter. It is used by the
# teleporter script.
class TeleporterComponent < Component

# destination entity
field :dest

# delay before entity should be moved
field :delay, valid: proc { |v| v.is_a?(Integer) }, default: 10
end

# This component is added to an entity that will be teleported at a later time.
# It is added by the teleporter script
class TeleportComponent < Component
# destination entity
field :dest, valid: proc { |v| v.nil? or World.entity_exists?(v) }

# Time at which they should be teleported
field :time
end

# Component that holds a script
class ScriptComponent < Component
# Script instance
field :script, clone: false
end

### QUESTIONABLE COMPONENTS ###
class AffectComponent < Component
not_unique
Expand Down
Loading

0 comments on commit 389abcd

Please sign in to comment.