inform-runtime 1.0.4 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +10 -12
- data/Rakefile +26 -16
- data/lib/{runtime → story_teller}/articles.rb +14 -10
- data/lib/{runtime → story_teller}/builtins.rb +50 -22
- data/lib/{runtime → story_teller}/color.rb +8 -8
- data/lib/{runtime → story_teller}/command.rb +26 -28
- data/lib/{runtime → story_teller}/context.rb +23 -24
- data/lib/story_teller/core.rb +38 -0
- data/lib/{runtime → story_teller}/daemon.rb +35 -36
- data/lib/story_teller/engine.rb +151 -0
- data/lib/story_teller/ephemeral_adapter.rb +42 -0
- data/lib/{runtime → story_teller}/events.rb +8 -9
- data/lib/{runtime → story_teller}/experimental/handler_dsl.rb +7 -18
- data/lib/story_teller/experimental/reverse_engineer_class.rb +37 -0
- data/lib/{runtime → story_teller}/grammar_parser.rb +24 -40
- data/lib/{runtime → story_teller}/helpers.rb +21 -7
- data/lib/{runtime → story_teller}/history.rb +5 -5
- data/lib/{runtime → story_teller}/inflector.rb +4 -5
- data/lib/story_teller/inform/base.rb +160 -0
- data/lib/{runtime → story_teller/inform/ephemeral}/link.rb +27 -45
- data/lib/{runtime → story_teller/inform/ephemeral}/module.rb +17 -58
- data/lib/story_teller/inform/ephemeral/object.rb +329 -0
- data/lib/{runtime → story_teller/inform/ephemeral}/tag.rb +54 -81
- data/lib/story_teller/inform/models.rb +25 -0
- data/lib/{runtime → story_teller}/io.rb +10 -10
- data/lib/{runtime → story_teller}/kernel.rb +21 -31
- data/lib/story_teller/library/bootstrap.rb +66 -0
- data/lib/story_teller/library/declarations.rb +53 -0
- data/lib/story_teller/library/directives.rb +91 -0
- data/lib/story_teller/library/loader.rb +104 -0
- data/lib/story_teller/library/location.rb +73 -0
- data/lib/{runtime → story_teller}/library.rb +27 -12
- data/lib/{runtime → story_teller}/logging.rb +47 -24
- data/lib/{runtime → story_teller}/mixins.rb +6 -6
- data/lib/story_teller/model_adapter.rb +132 -0
- data/lib/{runtime → story_teller}/plurals.rb +11 -11
- data/lib/{runtime → story_teller}/prototype.rb +11 -10
- data/lib/{runtime → story_teller}/publication.rb +9 -9
- data/lib/{runtime → story_teller}/session.rb +6 -8
- data/lib/{runtime → story_teller}/stdlib.rb +13 -11
- data/lib/{runtime → story_teller}/subscription.rb +8 -8
- data/lib/{runtime → story_teller}/tree.rb +6 -6
- data/lib/{runtime → story_teller}/version.rb +16 -6
- data/lib/story_teller/world_tree.rb +54 -0
- data/lib/story_teller.rb +26 -0
- metadata +59 -99
- data/config/database.yml +0 -37
- data/exe/inform.rb +0 -6
- data/game/config.yml +0 -5
- data/game/example.inf +0 -76
- data/game/example.rb +0 -90
- data/game/forms/example_form.rb +0 -2
- data/game/grammar/game_grammar.inf.rb +0 -11
- data/game/languages/english.rb +0 -2
- data/game/models/example_model.rb +0 -2
- data/game/modules/example_module.rb +0 -9
- data/game/rules/example_state.rb +0 -2
- data/game/scripts/example_script.rb +0 -2
- data/game/topics/example_topic.rb +0 -2
- data/game/verbs/game_verbs.rb +0 -15
- data/game/verbs/metaverbs.rb +0 -2028
- data/lib/runtime/config.rb +0 -48
- data/lib/runtime/database.rb +0 -500
- data/lib/runtime/game.rb +0 -74
- data/lib/runtime/game_loader.rb +0 -132
- data/lib/runtime/library_loader.rb +0 -135
- data/lib/runtime/object.rb +0 -761
- data/lib/runtime/options.rb +0 -104
- data/lib/runtime/persistence.rb +0 -292
- data/lib/runtime/runtime.rb +0 -321
- data/lib/runtime/world_tree.rb +0 -69
- data/lib/runtime.rb +0 -35
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# lib/story_teller/core.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
require_relative 'builtins'
|
|
23
|
+
require_relative 'stdlib'
|
|
24
|
+
require_relative 'logging'
|
|
25
|
+
require_relative 'prototype'
|
|
26
|
+
require_relative 'command'
|
|
27
|
+
require_relative 'history'
|
|
28
|
+
require_relative 'events'
|
|
29
|
+
require_relative 'grammar_parser'
|
|
30
|
+
require_relative 'kernel'
|
|
31
|
+
require_relative 'mixins'
|
|
32
|
+
require_relative 'helpers'
|
|
33
|
+
require_relative 'io'
|
|
34
|
+
require_relative 'publication'
|
|
35
|
+
require_relative 'context'
|
|
36
|
+
require_relative 'world_tree'
|
|
37
|
+
require_relative 'library'
|
|
38
|
+
require_relative 'engine'
|
|
@@ -1,24 +1,23 @@
|
|
|
1
|
+
# src/lib/daemon.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
5
6
|
#
|
|
6
|
-
# This file is part of the
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
7
8
|
#
|
|
8
|
-
# The
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
9
10
|
# modify it under the terms of the GNU General Public License as published
|
|
10
11
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
11
12
|
# (at your option) any later version.
|
|
12
13
|
#
|
|
13
|
-
# The
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
14
15
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
16
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
17
|
# GNU General Public License for more details.
|
|
17
18
|
#
|
|
18
19
|
# You should have received a copy of the GNU General Public License
|
|
19
|
-
# along with the
|
|
20
|
-
|
|
21
|
-
require 'set'
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
22
21
|
|
|
23
22
|
# In order to support atmospheric messages and NPC automation
|
|
24
23
|
# based on timers, I'm trying to come up with an approach for
|
|
@@ -75,14 +74,14 @@ require 'set'
|
|
|
75
74
|
# has switchable ~on;
|
|
76
75
|
#
|
|
77
76
|
|
|
78
|
-
# The
|
|
79
|
-
module
|
|
77
|
+
# The StoryTeller module
|
|
78
|
+
module StoryTeller
|
|
80
79
|
def run_daemons
|
|
81
80
|
return if defined?(TURN_BASED)
|
|
82
|
-
|
|
81
|
+
StoryTeller::Daemons.start
|
|
83
82
|
end
|
|
84
83
|
|
|
85
|
-
# The
|
|
84
|
+
# The StoryTeller::Daemons module
|
|
86
85
|
module Daemons
|
|
87
86
|
def spawn
|
|
88
87
|
@spawn ||= defined?(Java) ? java.util.concurrent.ConcurrentSkipListSet.new : Set.new
|
|
@@ -98,10 +97,10 @@ module Inform
|
|
|
98
97
|
java.util.concurrent.Executors.newSingleThreadScheduledExecutor()
|
|
99
98
|
end
|
|
100
99
|
|
|
101
|
-
# The
|
|
100
|
+
# The StoryTeller::Daemons::Entheogen class encapsulates a heartbeat which
|
|
102
101
|
# is a ScheduledFuture created by the Heart executor and instantiated
|
|
103
|
-
# when
|
|
104
|
-
class Entheogen < Inform::
|
|
102
|
+
# when StoryTeller::Daemons.start is executed.
|
|
103
|
+
class Entheogen < Inform::Ephemeral::Object
|
|
105
104
|
attr_accessor :heartbeat
|
|
106
105
|
end
|
|
107
106
|
|
|
@@ -114,13 +113,13 @@ module Inform
|
|
|
114
113
|
end
|
|
115
114
|
|
|
116
115
|
def on?
|
|
117
|
-
return false if
|
|
118
|
-
|
|
116
|
+
return false if StoryTeller::Daemons.ghost.heartbeat.nil?
|
|
117
|
+
StoryTeller::Daemons.ghost.heartbeat.isCancelled() == false
|
|
119
118
|
end
|
|
120
119
|
|
|
121
120
|
def rescan
|
|
122
|
-
|
|
123
|
-
|
|
121
|
+
StoryTeller::Daemons.spawn.clear
|
|
122
|
+
StoryTeller::Daemons.scan_objects
|
|
124
123
|
end
|
|
125
124
|
|
|
126
125
|
DaemonScanElapsedMessage = "Scanned %<daemons>s daemons in %<elapsed>0.2f milliseconds".freeze
|
|
@@ -138,32 +137,32 @@ module Inform
|
|
|
138
137
|
|
|
139
138
|
# rubocop: disable Metrics/AbcSize
|
|
140
139
|
def self.start
|
|
141
|
-
initial_delay =
|
|
142
|
-
period =
|
|
140
|
+
initial_delay = StoryTeller::Game.config[:daemon_initial_delay]
|
|
141
|
+
period = StoryTeller::Game.config[:daemons_period]
|
|
143
142
|
unit = defined?(Java) ? java.util.concurrent.TimeUnit::MILLISECONDS : 'milliseconds'
|
|
144
143
|
Thread.new do
|
|
145
|
-
|
|
144
|
+
StoryTeller::Daemons.rescan
|
|
146
145
|
log.debug "Starting daemons..."
|
|
147
|
-
daemons =
|
|
148
|
-
|
|
146
|
+
daemons = StoryTeller::Daemons.method(:daemons).to_proc
|
|
147
|
+
StoryTeller::Daemons.ghost.heartbeat = StoryTeller::Daemons.heart.scheduleAtFixedRate(
|
|
149
148
|
daemons, initial_delay, period, unit)
|
|
150
149
|
end
|
|
151
150
|
end
|
|
152
151
|
# rubocop: enable Metrics/AbcSize
|
|
153
152
|
|
|
154
153
|
def self.stop
|
|
155
|
-
|
|
156
|
-
|
|
154
|
+
StoryTeller::Daemons.ghost.heartbeat.cancel(false)
|
|
155
|
+
StoryTeller::Daemons.spawn.clear
|
|
157
156
|
end
|
|
158
157
|
|
|
159
158
|
DaemonExecutionElapsedMessage = "\e[1m\e[33mExecuted daemons in %<elapsed>0.2f milliseconds\e[39m\e[22m".freeze
|
|
160
159
|
|
|
161
160
|
def self.daemons
|
|
162
161
|
start = Time.ms
|
|
163
|
-
|
|
162
|
+
StoryTeller::Daemons.spawn.each do |daemon|
|
|
164
163
|
# In realtime games, each_turn is a synonym for daemon
|
|
165
164
|
next unless daemon.respond_to?(:daemon) || daemon.respond_to?(:each_turn)
|
|
166
|
-
|
|
165
|
+
StoryTeller::Daemons.execute daemon
|
|
167
166
|
end
|
|
168
167
|
ensure
|
|
169
168
|
finish = Time.ms
|
|
@@ -185,7 +184,7 @@ module Inform
|
|
|
185
184
|
# TODO: Use a pool of InformLibraries until
|
|
186
185
|
# comprehensive event contexts can be implemented
|
|
187
186
|
log.warn "Using singleton Ghost InformLibrary for #{obj} daemon"
|
|
188
|
-
obj.inflib =
|
|
187
|
+
obj.inflib = StoryTeller::Engine.libraries[StoryTeller::Daemons.ghost]
|
|
189
188
|
end
|
|
190
189
|
|
|
191
190
|
# TODO: Potentially go ahead and print any string results
|
|
@@ -216,14 +215,14 @@ module Inform
|
|
|
216
215
|
end
|
|
217
216
|
|
|
218
217
|
def StartDaemon(obj)
|
|
219
|
-
|
|
218
|
+
StoryTeller::Daemons.spawn.add obj if obj.respond_to?(:daemon) || obj.respond_to?(:each_turn)
|
|
220
219
|
end
|
|
221
220
|
|
|
222
221
|
def StopDaemon(obj)
|
|
223
222
|
return if obj.nil?
|
|
224
223
|
log.warn "Stopping daemon: #{obj}"
|
|
225
224
|
obj.undef_method(:daemon) # TODO: Maybe don't do this
|
|
226
|
-
|
|
225
|
+
StoryTeller::Daemons.spawn.remove obj
|
|
227
226
|
end
|
|
228
227
|
|
|
229
228
|
def StartTimer(obj, interval)
|
|
@@ -235,11 +234,11 @@ module Inform
|
|
|
235
234
|
end
|
|
236
235
|
|
|
237
236
|
def daemonize(event)
|
|
238
|
-
|
|
237
|
+
StoryTeller::Daemons.schedules[self] = event
|
|
239
238
|
end
|
|
240
239
|
|
|
241
240
|
def daemonic?
|
|
242
|
-
|
|
241
|
+
StoryTeller::Daemons.schedules.include? self
|
|
243
242
|
end
|
|
244
243
|
|
|
245
244
|
def before_destroy
|
|
@@ -250,17 +249,17 @@ module Inform
|
|
|
250
249
|
|
|
251
250
|
# rubocop: disable Metrics/AbcSize
|
|
252
251
|
def occasionally(time = nil, &block)
|
|
253
|
-
time =
|
|
252
|
+
time = StoryTeller::Game.config[:daemons_frequency_default] if time.nil?
|
|
254
253
|
return if active? || daemonic?
|
|
255
254
|
frequency = ((self.&:frequency) || time).to_i
|
|
256
255
|
occasion = rand(frequency) + 1
|
|
257
256
|
log.trace "Scheduling occasional daemonic event for #{self} in #{occasion} seconds"
|
|
258
|
-
(
|
|
259
|
-
|
|
257
|
+
(StoryTeller::Daemons.schedules[self] = delay(occasion, &block)).finally do
|
|
258
|
+
StoryTeller::Daemons.schedules.delete self
|
|
260
259
|
end
|
|
261
260
|
end
|
|
262
261
|
end
|
|
263
262
|
# rubocop: enable Metrics/AbcSize
|
|
264
263
|
# module Daemons
|
|
265
264
|
end
|
|
266
|
-
# module
|
|
265
|
+
# module StoryTeller
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# lib/story_teller/engine.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
require_relative 'session'
|
|
23
|
+
require_relative 'io'
|
|
24
|
+
require_relative 'context'
|
|
25
|
+
require_relative 'library'
|
|
26
|
+
require_relative 'publication'
|
|
27
|
+
|
|
28
|
+
# The StoryTeller module
|
|
29
|
+
module StoryTeller
|
|
30
|
+
# The Engine module
|
|
31
|
+
module Engine
|
|
32
|
+
# The Library module
|
|
33
|
+
module Library
|
|
34
|
+
def play
|
|
35
|
+
log.debug "Using engine-managed InformLibrary play method override"
|
|
36
|
+
inform_library = StoryTeller::Engine.libraries[StoryTeller::Engine]
|
|
37
|
+
inform_library.play
|
|
38
|
+
inform_library
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# The Config class
|
|
43
|
+
module Config
|
|
44
|
+
DEFAULTS = {
|
|
45
|
+
environment: 'default',
|
|
46
|
+
inform6lib_gem_code_prefix: 'inform',
|
|
47
|
+
language: 'English',
|
|
48
|
+
properties: 'player actor action action_to_be ' \
|
|
49
|
+
'results parameters pattern ' \
|
|
50
|
+
'noun second inp1 inp2 ' \
|
|
51
|
+
'special_word special_number special_number1 special_number2 ' \
|
|
52
|
+
'consult_words match_from wn verb_wordnum words ' \
|
|
53
|
+
'parser_action parser_one parser_two scope_reason',
|
|
54
|
+
log_level: Logger::INFO
|
|
55
|
+
}.freeze
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
module_function
|
|
59
|
+
|
|
60
|
+
def libraries
|
|
61
|
+
@libraries ||= {}
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def main_object=(obj)
|
|
65
|
+
@main_object = obj
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def main_object
|
|
69
|
+
@main_object
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def default_config
|
|
73
|
+
@default_config ||= StoryTeller::Engine::Config::DEFAULTS
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def inform_code_prefix
|
|
77
|
+
StoryTeller::Engine.default_config[:inform6lib_gem_code_prefix]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def project_dir_path
|
|
81
|
+
@project_dir_path ||= begin
|
|
82
|
+
story_dir_path = File.expand_path(__dir__)
|
|
83
|
+
lib_dir_path = File.expand_path(File.dirname(story_dir_path))
|
|
84
|
+
File.expand_path(File.dirname(lib_dir_path))
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def executable=(executable)
|
|
89
|
+
@executable = executable
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def executable
|
|
93
|
+
@executable
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def default_environment
|
|
97
|
+
StoryTeller::Engine.default_config[:environment]
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def default_invocation_properties
|
|
101
|
+
StoryTeller::Engine.default_config.fetch(:properties, '').split.map(&:to_sym).freeze
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def invocation_properties
|
|
105
|
+
@invocation_properties ||= default_invocation_properties
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def invocation_properties=(properties)
|
|
109
|
+
@invocation_properties = properties
|
|
110
|
+
@invocation_context = nil
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def invocation_context
|
|
114
|
+
@invocation_context ||= Struct.new(*invocation_properties)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def language_name
|
|
118
|
+
StoryTeller::Engine.default_config[:language]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def player?(obj)
|
|
122
|
+
return false unless defined?(StoryTeller::IO::Session) && StoryTeller::IO::Session.respond_to?(:players)
|
|
123
|
+
StoryTeller::IO::Session.players.include?(obj)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def prime_dictionary
|
|
127
|
+
Inform::Object.select_map(:name).compact.each do |n|
|
|
128
|
+
StoryTeller::Dictionary.merge(n.split(/[,\s]+/).grep_v(/[^a-z]/i).map(&:downcase).map(&:to_sym))
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
# module Engine
|
|
133
|
+
|
|
134
|
+
# The StoryTeller::Privileges module to implement privilege
|
|
135
|
+
module Privileges
|
|
136
|
+
def admin?
|
|
137
|
+
self.has?(:admin)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def builder?
|
|
141
|
+
admin? || self.has?(:builder)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
end
|
|
145
|
+
# module StoryTeller
|
|
146
|
+
|
|
147
|
+
if defined?(ZCODE_ONLY)
|
|
148
|
+
# Simulate compiling with Z-code only compiler
|
|
149
|
+
WORDSIZE = (2**((0.size * 8) - 2) - 1)
|
|
150
|
+
end
|
|
151
|
+
# defined?(ZCODE_ONLY)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# lib/story_teller/ephemeral_adapter.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# module StoryTeller
|
|
23
|
+
module StoryTeller
|
|
24
|
+
# module EphemeralAdapter
|
|
25
|
+
module EphemeralAdapter
|
|
26
|
+
Adapter = {
|
|
27
|
+
name: :ephemeral,
|
|
28
|
+
object_class: Inform::Ephemeral::Object,
|
|
29
|
+
tag_class: Inform::Ephemeral::Tag,
|
|
30
|
+
link_class: Inform::Ephemeral::Link,
|
|
31
|
+
module_class: Inform::Ephemeral::Module
|
|
32
|
+
}.freeze
|
|
33
|
+
|
|
34
|
+
module_function
|
|
35
|
+
|
|
36
|
+
def register!
|
|
37
|
+
StoryTeller::ModelAdapter.register!(Adapter)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
StoryTeller::EphemeralAdapter.register!
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
+
# lib/story_teller/events.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
5
6
|
#
|
|
6
|
-
# This file is part of
|
|
7
|
+
# This file is part of StoryTeller.
|
|
7
8
|
#
|
|
8
|
-
#
|
|
9
|
+
# StoryTeller is free software: you can redistribute it and/or
|
|
9
10
|
# modify it under the terms of the GNU General Public License as published
|
|
10
11
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
11
12
|
# (at your option) any later version.
|
|
12
13
|
#
|
|
13
|
-
#
|
|
14
|
+
# StoryTeller is distributed in the hope that it will be useful,
|
|
14
15
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
16
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
17
|
# GNU General Public License for more details.
|
|
17
18
|
#
|
|
18
19
|
# You should have received a copy of the GNU General Public License
|
|
19
|
-
# along with
|
|
20
|
+
# along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
20
21
|
|
|
21
22
|
# The Time class
|
|
22
23
|
class Time
|
|
@@ -480,13 +481,13 @@ module EventInitializationMethods
|
|
|
480
481
|
def generate_identity
|
|
481
482
|
s = format(EventCauseIdentityTemplate, identity: @cause.identity, name: @cause.name)
|
|
482
483
|
if !@callstack.empty?
|
|
483
|
-
trace = @callstack.first.gsub(
|
|
484
|
+
trace = @callstack.first.gsub(StoryTeller::Engine.project_dir_path, '')
|
|
484
485
|
location, line_number, method_name = CallerPattern.match(trace)&.captures
|
|
485
486
|
s << format(EventSourceFullTemplate,
|
|
486
487
|
method_name: method_name, source_location: location, source_line_number: line_number)
|
|
487
488
|
elsif @activity.respond_to?(:source_location) || @activity.is_a?(Proc)
|
|
488
489
|
activity_source_location_enumerator = @activity.source_location.each
|
|
489
|
-
source_location = activity_source_location_enumerator.next.gsub(
|
|
490
|
+
source_location = activity_source_location_enumerator.next.gsub(StoryTeller::Engine.project_dir_path, '')
|
|
490
491
|
source_line_number = activity_source_location_enumerator.next
|
|
491
492
|
s << format(
|
|
492
493
|
EventSourceTemplate, source_location: source_location, source_line_number: source_line_number)
|
|
@@ -536,8 +537,6 @@ module Inform
|
|
|
536
537
|
invoke(self)
|
|
537
538
|
end
|
|
538
539
|
|
|
539
|
-
private
|
|
540
|
-
|
|
541
540
|
include EventInitializationMethods
|
|
542
541
|
end
|
|
543
542
|
|
|
@@ -1,22 +1,23 @@
|
|
|
1
|
+
# lib/story_teller/experimental/handler_dsl.rb
|
|
1
2
|
# encoding: utf-8
|
|
2
3
|
# frozen_string_literal: false
|
|
3
4
|
|
|
4
|
-
# Copyright Nels Nelson 2008-
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
5
6
|
#
|
|
6
|
-
# This file is part of the
|
|
7
|
+
# This file is part of the StoryTeller.
|
|
7
8
|
#
|
|
8
|
-
# The
|
|
9
|
+
# The StoryTeller is free software: you can redistribute it and/or
|
|
9
10
|
# modify it under the terms of the GNU General Public License as published
|
|
10
11
|
# by the Free Software Foundation, either version 3 of the License, or
|
|
11
12
|
# (at your option) any later version.
|
|
12
13
|
#
|
|
13
|
-
# The
|
|
14
|
+
# The StoryTeller is distributed in the hope that it will be useful,
|
|
14
15
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
15
16
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
16
17
|
# GNU General Public License for more details.
|
|
17
18
|
#
|
|
18
19
|
# You should have received a copy of the GNU General Public License
|
|
19
|
-
# along with the
|
|
20
|
+
# along with the StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
20
21
|
|
|
21
22
|
# The Inform module
|
|
22
23
|
module Inform
|
|
@@ -37,7 +38,7 @@ module Inform
|
|
|
37
38
|
|
|
38
39
|
# The Inform::Behavior module
|
|
39
40
|
module Behavior
|
|
40
|
-
Registry
|
|
41
|
+
class Registry < Hash; end
|
|
41
42
|
REGISTRY = Registry.new
|
|
42
43
|
|
|
43
44
|
def self.key_for(obj)
|
|
@@ -126,18 +127,6 @@ module Inform
|
|
|
126
127
|
|
|
127
128
|
# The BuilderInstanceMethods module
|
|
128
129
|
module BuilderInstanceMethods
|
|
129
|
-
# Unknown method with a block => define it on behavior.
|
|
130
|
-
# def method_missing(method_name, *args, &block)
|
|
131
|
-
# return @target.public_send(method_name, *args) if block.nil?
|
|
132
|
-
# local_context = @context
|
|
133
|
-
# @behavior.send(:define_method, method_name) do |*call_args, &_block|
|
|
134
|
-
# instance_exec(local_context, *call_args, &block)
|
|
135
|
-
# end
|
|
136
|
-
# method_name
|
|
137
|
-
# rescue NoMethodError
|
|
138
|
-
# super
|
|
139
|
-
# end
|
|
140
|
-
|
|
141
130
|
def method_missing(method_name, *args, &block)
|
|
142
131
|
# 1) Try the real receiver first (even when a block is present)
|
|
143
132
|
log.debug "@target: #{@target.inspect}"
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# lib/story_teller/experimental/reverse_engineer_class.rb
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
# frozen_string_literal: false
|
|
4
|
+
|
|
5
|
+
# Copyright Nels Nelson 2008-2025 but freely usable (see license)
|
|
6
|
+
#
|
|
7
|
+
# This file is part of StoryTeller.
|
|
8
|
+
#
|
|
9
|
+
# StoryTeller is free software: you can redistribute it and/or
|
|
10
|
+
# modify it under the terms of the GNU General Public License as published
|
|
11
|
+
# by the Free Software Foundation, either version 3 of the License, or
|
|
12
|
+
# (at your option) any later version.
|
|
13
|
+
#
|
|
14
|
+
# StoryTeller is distributed in the hope that it will be useful,
|
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17
|
+
# GNU General Public License for more details.
|
|
18
|
+
#
|
|
19
|
+
# You should have received a copy of the GNU General Public License
|
|
20
|
+
# along with StoryTeller. If not, see <http://www.gnu.org/licenses/>.
|
|
21
|
+
|
|
22
|
+
# The ReverseEngineerClass module
|
|
23
|
+
module ReverseEngineerClass
|
|
24
|
+
def singleton_object_to_class(object, superclass = Object)
|
|
25
|
+
source = object.singleton_class
|
|
26
|
+
|
|
27
|
+
Class.new(superclass) do
|
|
28
|
+
source.instance_methods(false).each do |method_name|
|
|
29
|
+
define_method(method_name, source.instance_method(method_name))
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
old_library = InformLibrary
|
|
35
|
+
Object.send(:remove_const, :InformLibrary)
|
|
36
|
+
InformLibrary = singleton_object_to_class(old_library, Inform::Ephemeral::Object)
|
|
37
|
+
end
|