gamefic 1.6.0 → 1.7.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/lib/gamefic.rb +4 -1
- data/lib/gamefic/action.rb +4 -0
- data/lib/gamefic/{character.rb → active.rb} +280 -232
- data/lib/gamefic/actor.rb +5 -0
- data/lib/gamefic/core_ext/string.rb +12 -12
- data/lib/gamefic/describable.rb +18 -1
- data/lib/gamefic/element.rb +31 -0
- data/lib/gamefic/engine/base.rb +17 -24
- data/lib/gamefic/entity.rb +18 -36
- data/lib/gamefic/grammar/gender.rb +1 -1
- data/lib/gamefic/grammar/pronouns.rb +3 -2
- data/lib/gamefic/messaging.rb +0 -1
- data/lib/gamefic/plot.rb +14 -4
- data/lib/gamefic/plot/callbacks.rb +1 -2
- data/lib/gamefic/plot/commands.rb +3 -4
- data/lib/gamefic/plot/darkroom.rb +264 -0
- data/lib/gamefic/plot/entities.rb +13 -1
- data/lib/gamefic/plot/host.rb +10 -8
- data/lib/gamefic/plot/playbook.rb +17 -13
- data/lib/gamefic/plot/scenes.rb +50 -12
- data/lib/gamefic/plot/snapshot.rb +15 -210
- data/lib/gamefic/query.rb +1 -0
- data/lib/gamefic/query/base.rb +15 -19
- data/lib/gamefic/query/external.rb +14 -0
- data/lib/gamefic/scene.rb +2 -4
- data/lib/gamefic/scene/{active.rb → activity.rb} +26 -26
- data/lib/gamefic/scene/base.rb +12 -7
- data/lib/gamefic/scene/multiple_choice.rb +0 -13
- data/lib/gamefic/scene/multiple_scene.rb +1 -1
- data/lib/gamefic/subplot.rb +16 -23
- data/lib/gamefic/user.rb +0 -1
- data/lib/gamefic/user/base.rb +15 -1
- data/lib/gamefic/user/tty.rb +15 -31
- data/lib/gamefic/version.rb +1 -1
- metadata +8 -26
- data/lib/gamefic/character/state.rb +0 -12
- data/lib/gamefic/user/buffer.rb +0 -32
@@ -1,16 +1,16 @@
|
|
1
1
|
class String
|
2
|
-
|
2
|
+
include Gamefic::Matchable
|
3
3
|
# Capitalize the first letter without changing the rest of the string.
|
4
4
|
# (String#capitalize makes the rest of the string lower-case.)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
5
|
+
def capitalize_first
|
6
|
+
"#{self[0,1].upcase}#{self[1,self.length]}"
|
7
|
+
end
|
8
|
+
# @return [String]
|
9
|
+
def cap_first
|
10
|
+
self.capitalize_first
|
11
|
+
end
|
12
|
+
# @return [Array]
|
13
|
+
def split_words
|
14
|
+
self.gsub(/ +/, ' ').strip.split
|
15
|
+
end
|
16
16
|
end
|
data/lib/gamefic/describable.rb
CHANGED
@@ -9,15 +9,24 @@ module Gamefic
|
|
9
9
|
include Grammar::Person, Grammar::Plural
|
10
10
|
include Matchable
|
11
11
|
|
12
|
+
# Get the name of the object.
|
13
|
+
# The name is usually presented without articles (e.g., "object" instead
|
14
|
+
# of "an object" or "the object" unless the article is part of a proper
|
15
|
+
# name (e.g., "The Ohio State University").
|
16
|
+
#
|
12
17
|
# @return [String]
|
13
18
|
attr_reader :name
|
14
19
|
|
15
20
|
# @return [String]
|
16
21
|
attr_reader :synonyms
|
17
22
|
|
23
|
+
# Get the object's indefinite article (usually "a" or "an").
|
24
|
+
#
|
18
25
|
# @return [String]
|
19
26
|
attr_reader :indefinite_article
|
20
27
|
|
28
|
+
# Get the object's definite article (usually "the").
|
29
|
+
#
|
21
30
|
# @return [String]
|
22
31
|
attr_reader :definite_article
|
23
32
|
|
@@ -41,22 +50,30 @@ module Gamefic
|
|
41
50
|
# Get the name of the object with a definite article.
|
42
51
|
# Note: proper-named objects never append an article, though an article
|
43
52
|
# may be included in its proper name.
|
53
|
+
#
|
54
|
+
# @return [String]
|
44
55
|
def definitely
|
45
56
|
((proper_named? or definite_article == '') ? '' : "#{definite_article} ") + name.to_s
|
46
57
|
end
|
47
58
|
|
48
|
-
# Get the definite article for this object.
|
59
|
+
# Get the definite article for this object (usually "the").
|
49
60
|
#
|
50
61
|
# @return [String]
|
51
62
|
def definite_article
|
52
63
|
@definite_article || "the"
|
53
64
|
end
|
54
65
|
|
66
|
+
# Set the definite article.
|
67
|
+
#
|
68
|
+
# @param [String] article
|
55
69
|
def definite_article= article
|
56
70
|
@keywords = nil
|
57
71
|
@definite_article = article
|
58
72
|
end
|
59
73
|
|
74
|
+
# Set the indefinite article.
|
75
|
+
#
|
76
|
+
# @param [String] article
|
60
77
|
def indefinite_article= article
|
61
78
|
@keywords = nil
|
62
79
|
@indefinite_article = article
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Gamefic
|
2
|
+
class Element
|
3
|
+
include Gamefic::Describable
|
4
|
+
|
5
|
+
def initialize(args = {})
|
6
|
+
self.class.default_attributes.merge(args).each { |key, value|
|
7
|
+
send "#{key}=", value
|
8
|
+
}
|
9
|
+
post_initialize
|
10
|
+
yield self if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def post_initialize
|
14
|
+
# raise NotImplementedError, "#{self.class} must implement post_initialize"
|
15
|
+
end
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def set_default attrs = {}
|
19
|
+
default_attributes.merge! attrs
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_attributes
|
23
|
+
@default_attributes ||= {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def inherited subclass
|
27
|
+
subclass.set_default default_attributes
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/gamefic/engine/base.rb
CHANGED
@@ -3,7 +3,10 @@ module Gamefic
|
|
3
3
|
# Basic functionality for running a single-player game from a console.
|
4
4
|
#
|
5
5
|
class Engine::Base
|
6
|
+
# @return [Class]
|
6
7
|
attr_writer :user_class
|
8
|
+
|
9
|
+
# @return [Gamefic::Plot]
|
7
10
|
attr_reader :plot
|
8
11
|
|
9
12
|
def initialize(plot)
|
@@ -20,46 +23,36 @@ module Gamefic
|
|
20
23
|
end
|
21
24
|
|
22
25
|
def connect
|
23
|
-
|
24
|
-
@
|
25
|
-
@
|
26
|
-
@
|
26
|
+
raise 'Plot did not specify a player class' if @plot.player_class.nil?
|
27
|
+
# @todo The plot itself can define name, etc.
|
28
|
+
character = @plot.make @plot.player_class, name: 'yourself', synonyms: 'self myself you me', proper_named: true
|
29
|
+
@user = user_class.new(self)
|
30
|
+
@user.connect character
|
31
|
+
character.connect @user
|
27
32
|
end
|
28
33
|
|
29
34
|
def run
|
30
35
|
connect
|
31
|
-
@plot.introduce @character
|
32
|
-
|
33
|
-
turn until @character.concluded?
|
36
|
+
@plot.introduce @user.character
|
37
|
+
#@user.update @character.state
|
38
|
+
turn until @user.character.concluded?
|
39
|
+
@user.update
|
34
40
|
#print @user.flush
|
35
41
|
end
|
36
42
|
|
37
43
|
def turn
|
38
44
|
@plot.ready
|
39
|
-
|
40
|
-
|
41
|
-
@character.state[:options].each { |o|
|
42
|
-
list += "<li><a href=\"#\" rel=\"gamefic\" data-command=\"#{o}\">#{o}</a></li>"
|
43
|
-
}
|
44
|
-
list += "</ol>"
|
45
|
-
@character.tell list
|
46
|
-
end
|
47
|
-
#print @user.flush
|
48
|
-
@user.update @character.state
|
49
|
-
#@character.flush
|
50
|
-
if @character.queue.empty?
|
45
|
+
@user.update
|
46
|
+
if @user.character.queue.empty?
|
51
47
|
receive
|
52
48
|
end
|
53
49
|
@plot.update
|
54
|
-
#print @user.flush
|
55
|
-
@user.update @character.state
|
56
|
-
#@character.flush
|
57
50
|
end
|
58
51
|
|
59
52
|
def receive
|
60
|
-
print @character.scene.prompt + ' '
|
53
|
+
print @user.character.scene.prompt + ' '
|
61
54
|
input = STDIN.gets
|
62
|
-
@character.queue.push input unless input.nil?
|
55
|
+
@user.character.queue.push input unless input.nil?
|
63
56
|
end
|
64
57
|
end
|
65
58
|
|
data/lib/gamefic/entity.rb
CHANGED
@@ -4,39 +4,11 @@ require 'gamefic/messaging'
|
|
4
4
|
|
5
5
|
module Gamefic
|
6
6
|
|
7
|
-
class Entity
|
7
|
+
class Entity < Element
|
8
8
|
include Node
|
9
|
-
include Describable
|
10
9
|
include Messaging
|
11
10
|
include Grammar::WordAdapter
|
12
11
|
|
13
|
-
attr_reader :session
|
14
|
-
|
15
|
-
def initialize(args = {})
|
16
|
-
pre_initialize
|
17
|
-
args.each { |key, value|
|
18
|
-
send "#{key}=", value
|
19
|
-
}
|
20
|
-
@session = Hash.new
|
21
|
-
yield self if block_given?
|
22
|
-
post_initialize
|
23
|
-
end
|
24
|
-
|
25
|
-
def uid
|
26
|
-
if @uid == nil
|
27
|
-
@uid = self.object_id.to_s
|
28
|
-
end
|
29
|
-
@uid
|
30
|
-
end
|
31
|
-
|
32
|
-
def pre_initialize
|
33
|
-
# raise NotImplementedError, "#{self.class} must implement post_initialize"
|
34
|
-
end
|
35
|
-
|
36
|
-
def post_initialize
|
37
|
-
# raise NotImplementedError, "#{self.class} must implement post_initialize"
|
38
|
-
end
|
39
|
-
|
40
12
|
# Execute the entity's on_update blocks.
|
41
13
|
# This method is typically called by the Engine that manages game execution.
|
42
14
|
# The base method does nothing. Subclasses can override it.
|
@@ -53,22 +25,32 @@ module Gamefic
|
|
53
25
|
end
|
54
26
|
super
|
55
27
|
end
|
56
|
-
|
57
|
-
#
|
28
|
+
|
29
|
+
# A freeform property dictionary.
|
30
|
+
# Authors can use the session hash to assign custom properties to the
|
31
|
+
# entity. It can also be referenced directly using [] without the method
|
32
|
+
# name, e.g., entity.session[:my_value] or entity[:my_value].
|
58
33
|
#
|
59
|
-
# @
|
34
|
+
# @return [Hash]
|
35
|
+
def session
|
36
|
+
@session ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Get a custom property.
|
40
|
+
#
|
41
|
+
# @param key [Symbol] The property's name
|
42
|
+
# @return The value of the property
|
60
43
|
def [](key)
|
61
44
|
session[key]
|
62
45
|
end
|
63
46
|
|
64
|
-
# Set
|
47
|
+
# Set a custom property.
|
65
48
|
#
|
66
|
-
# @param key [Symbol] The property's name
|
67
|
-
# @param value The value to set
|
49
|
+
# @param key [Symbol] The property's name
|
50
|
+
# @param value The value to set
|
68
51
|
def []=(key, value)
|
69
52
|
session[key] = value
|
70
53
|
end
|
71
|
-
|
72
54
|
end
|
73
55
|
|
74
56
|
end
|
@@ -53,7 +53,7 @@ module Gamefic::Grammar
|
|
53
53
|
#
|
54
54
|
# @return [String]
|
55
55
|
def Poss
|
56
|
-
|
56
|
+
poss.cap_first
|
57
57
|
end
|
58
58
|
|
59
59
|
# Get the capitalized reflexive pronoun
|
@@ -88,7 +88,7 @@ module Gamefic::Grammar
|
|
88
88
|
if @sets.nil?
|
89
89
|
@sets = {}
|
90
90
|
@sets["1:singular"] = ["I", "me", "my", "myself"]
|
91
|
-
@sets["2"] = ["you", "you", "your", "yourself"]
|
91
|
+
@sets["2:singular"] = ["you", "you", "your", "yourself"]
|
92
92
|
@sets["3:singular:male"] = ["he", "him", "his", "himself"]
|
93
93
|
@sets["3:singular:female"] = ["she", "her", "her", "herself"]
|
94
94
|
# "other" refers to a person or living being that is neither
|
@@ -97,6 +97,7 @@ module Gamefic::Grammar
|
|
97
97
|
@sets["3:singular:other"] = ["they", "them", "their", "themselves"]
|
98
98
|
@sets["3:singular:neutral"] = ["it", "it", "its", "itself"]
|
99
99
|
@sets["1:plural"] = ["we", "us", "our", "ourselves"]
|
100
|
+
@sets["2:plural"] = ["you", "you", "your", "yourselves"]
|
100
101
|
@sets["3:plural"] = ["they", "them", "their", "themselves"]
|
101
102
|
end
|
102
103
|
@sets
|
data/lib/gamefic/messaging.rb
CHANGED
data/lib/gamefic/plot.rb
CHANGED
@@ -1,5 +1,3 @@
|
|
1
|
-
# TODO: JSON support is currently experimental.
|
2
|
-
#require 'gamefic/entityloader'
|
3
1
|
require 'gamefic/tester'
|
4
2
|
require 'gamefic/source'
|
5
3
|
require 'gamefic/script'
|
@@ -14,6 +12,7 @@ module Gamefic
|
|
14
12
|
autoload :Articles, 'gamefic/plot/articles'
|
15
13
|
autoload :YouMount, 'gamefic/plot/you_mount'
|
16
14
|
autoload :Snapshot, 'gamefic/plot/snapshot'
|
15
|
+
autoload :Darkroom, 'gamefic/plot/darkroom'
|
17
16
|
autoload :Host, 'gamefic/plot/host'
|
18
17
|
autoload :Players, 'gamefic/plot/players'
|
19
18
|
autoload :Playbook, 'gamefic/plot/playbook'
|
@@ -21,6 +20,7 @@ module Gamefic
|
|
21
20
|
autoload :Theater, 'gamefic/plot/theater'
|
22
21
|
|
23
22
|
attr_reader :commands, :imported_scripts, :source
|
23
|
+
|
24
24
|
# TODO: Metadata could use better protection
|
25
25
|
attr_accessor :metadata
|
26
26
|
include Theater
|
@@ -36,6 +36,11 @@ module Gamefic
|
|
36
36
|
post_initialize
|
37
37
|
end
|
38
38
|
|
39
|
+
def player_class cls = nil
|
40
|
+
@player_class = cls unless cls.nil?
|
41
|
+
@player_class
|
42
|
+
end
|
43
|
+
|
39
44
|
# @return [Gamefic::Plot::Playbook]
|
40
45
|
def playbook
|
41
46
|
@playbook ||= Gamefic::Plot::Playbook.new
|
@@ -68,6 +73,8 @@ module Gamefic
|
|
68
73
|
def ready
|
69
74
|
playbook.freeze
|
70
75
|
@running = true
|
76
|
+
# Call the initial state to make sure it's set
|
77
|
+
initial_state
|
71
78
|
call_ready
|
72
79
|
call_player_ready
|
73
80
|
p_subplots.each { |s| s.ready }
|
@@ -78,7 +85,10 @@ module Gamefic
|
|
78
85
|
def update
|
79
86
|
entities.each { |e| e.flush }
|
80
87
|
call_before_player_update
|
81
|
-
p_players.each { |p|
|
88
|
+
p_players.each { |p|
|
89
|
+
p.performed nil
|
90
|
+
p.scene.update
|
91
|
+
}
|
82
92
|
p_entities.each { |e| e.update }
|
83
93
|
call_player_update
|
84
94
|
call_update
|
@@ -117,7 +127,7 @@ module Gamefic
|
|
117
127
|
else
|
118
128
|
false
|
119
129
|
end
|
120
|
-
end
|
130
|
+
end
|
121
131
|
end
|
122
132
|
|
123
133
|
end
|
@@ -30,7 +30,7 @@ module Gamefic
|
|
30
30
|
# player[:turns] += 1
|
31
31
|
# end
|
32
32
|
#
|
33
|
-
# @yieldparam [
|
33
|
+
# @yieldparam [Gamefic::Performance]
|
34
34
|
def on_player_ready &block
|
35
35
|
p_player_ready_procs.push block
|
36
36
|
end
|
@@ -98,7 +98,6 @@ module Gamefic
|
|
98
98
|
#
|
99
99
|
def call_player_update
|
100
100
|
p_players.each { |player|
|
101
|
-
#player.performed nil
|
102
101
|
p_player_update_procs.each { |block| block.call player }
|
103
102
|
}
|
104
103
|
end
|
@@ -103,11 +103,10 @@ module Gamefic
|
|
103
103
|
end
|
104
104
|
|
105
105
|
# Get an Array of available verbs.
|
106
|
-
# If the to_s parameter is true, convert Symbols to Strings.
|
107
106
|
#
|
108
|
-
# @return [Array<
|
109
|
-
def verbs
|
110
|
-
|
107
|
+
# @return [Array<String>]
|
108
|
+
def verbs
|
109
|
+
playbook.verbs.map { |v| v.to_s }.reject{ |v| v.start_with?('_') }
|
111
110
|
end
|
112
111
|
|
113
112
|
# Get an Array of all Actions defined in the Plot.
|
@@ -0,0 +1,264 @@
|
|
1
|
+
module Gamefic
|
2
|
+
# Create and restore plot snapshots.
|
3
|
+
#
|
4
|
+
class Plot::Darkroom
|
5
|
+
attr_reader :plot
|
6
|
+
|
7
|
+
def initialize plot
|
8
|
+
@plot = plot
|
9
|
+
end
|
10
|
+
|
11
|
+
# Create a snapshot of the plot.
|
12
|
+
#
|
13
|
+
# @return [Hash]
|
14
|
+
def save
|
15
|
+
result = { entities: [], players: [], subplots: [], instance_variables: {} }
|
16
|
+
entity_store.clear
|
17
|
+
player_store.clear
|
18
|
+
entity_store.concat plot.entities
|
19
|
+
player_store.concat plot.players
|
20
|
+
plot.subplots.each { |s| entity_store.concat s.entities }
|
21
|
+
entity_store.uniq!
|
22
|
+
entity_store.each do |e|
|
23
|
+
result[:entities].push hash_entity(e)
|
24
|
+
end
|
25
|
+
player_store.each do |p|
|
26
|
+
result[:players].push hash_entity(p)
|
27
|
+
end
|
28
|
+
plot.theater.instance_variables.each { |i|
|
29
|
+
v = plot.theater.instance_variable_get(i)
|
30
|
+
result[:instance_variables][i] = serialize(v) if can_serialize?(v)
|
31
|
+
}
|
32
|
+
plot.subplots.each { |s|
|
33
|
+
result[:subplots].push hash_subplot(s)
|
34
|
+
}
|
35
|
+
result
|
36
|
+
end
|
37
|
+
|
38
|
+
# Restore a snapshot.
|
39
|
+
#
|
40
|
+
def restore snapshot
|
41
|
+
entity_store.clear
|
42
|
+
player_store.clear
|
43
|
+
plot.subplots.each { |s| s.conclude }
|
44
|
+
plot.entities[plot.initial_state[:entities].length..-1].each { |e| plot.destroy e }
|
45
|
+
entity_store.concat plot.entities[0..plot.initial_state[:entities].length-1]
|
46
|
+
entity_store.uniq!
|
47
|
+
player_store.concat plot.players
|
48
|
+
i = 0
|
49
|
+
snapshot[:entities].each { |h|
|
50
|
+
if entity_store[i].nil?
|
51
|
+
e = plot.stage do
|
52
|
+
cls = self.const_get(h[:class])
|
53
|
+
make cls
|
54
|
+
end
|
55
|
+
entity_store.push e
|
56
|
+
end
|
57
|
+
i += 1
|
58
|
+
}
|
59
|
+
snapshot[:subplots].each { |s|
|
60
|
+
sp = plot.stage do
|
61
|
+
cls = const_get(s[:class])
|
62
|
+
branch cls
|
63
|
+
end
|
64
|
+
# @todo Assuming one player
|
65
|
+
sp.introduce player_store[0] unless player_store.empty?
|
66
|
+
rebuild_subplot sp, s
|
67
|
+
}
|
68
|
+
i = 0
|
69
|
+
snapshot[:entities].each { |h|
|
70
|
+
rebuild1 entity_store[i], h
|
71
|
+
i += 1
|
72
|
+
}
|
73
|
+
i = 0
|
74
|
+
snapshot[:players].each { |p|
|
75
|
+
rebuild1 player_store[i], p
|
76
|
+
i += 1
|
77
|
+
}
|
78
|
+
i = 0
|
79
|
+
snapshot[:entities].each { |h|
|
80
|
+
rebuild2 entity_store[i], h
|
81
|
+
i += 1
|
82
|
+
}
|
83
|
+
i = 0
|
84
|
+
snapshot[:players].each { |h|
|
85
|
+
rebuild2 player_store[i], h
|
86
|
+
i += 1
|
87
|
+
}
|
88
|
+
snapshot[:instance_variables].each_pair { |k, v|
|
89
|
+
plot.theater.instance_variable_set(k, unserialize(v))
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def hash_blacklist
|
96
|
+
[:@parent, :@children, :@last_action, :@scene, :@next_scene, :@playbook, :@performance_stack, :@buffer_stack, :@messages, :@state]
|
97
|
+
end
|
98
|
+
|
99
|
+
def can_serialize? v
|
100
|
+
return true if v.kind_of?(String) or v.kind_of?(Numeric) or v.kind_of?(Symbol) or v.kind_of?(Gamefic::Entity) or is_scene_class?(v) or v == true or v == false or v.nil?
|
101
|
+
if v.kind_of?(Array)
|
102
|
+
v.each do |e|
|
103
|
+
result = can_serialize?(e)
|
104
|
+
return false if result == false
|
105
|
+
end
|
106
|
+
true
|
107
|
+
elsif v.kind_of?(Hash)
|
108
|
+
v.each_pair do |k, v|
|
109
|
+
result = can_serialize?(k)
|
110
|
+
return false if result == false
|
111
|
+
result = can_serialize?(v)
|
112
|
+
return false if result == false
|
113
|
+
end
|
114
|
+
true
|
115
|
+
else
|
116
|
+
false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def is_scene_class?(v)
|
121
|
+
if v.kind_of?(Class)
|
122
|
+
s = v
|
123
|
+
until s.nil?
|
124
|
+
return true if s == Gamefic::Scene::Base
|
125
|
+
s = s.superclass
|
126
|
+
end
|
127
|
+
false
|
128
|
+
else
|
129
|
+
false
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def serialize v
|
134
|
+
if v.kind_of?(Array)
|
135
|
+
result = []
|
136
|
+
v.each do |e|
|
137
|
+
result.push serialize(e)
|
138
|
+
end
|
139
|
+
result
|
140
|
+
elsif v.kind_of?(Hash)
|
141
|
+
result = {}
|
142
|
+
v.each_pair do |k, v|
|
143
|
+
result[serialize(k)] = serialize(v)
|
144
|
+
end
|
145
|
+
result
|
146
|
+
elsif is_scene_class?(v)
|
147
|
+
i = plot.scene_classes.index(v)
|
148
|
+
"#<SIN_#{i}>"
|
149
|
+
elsif v.kind_of?(Gamefic::Entity)
|
150
|
+
i = entity_store.index(v)
|
151
|
+
if i.nil?
|
152
|
+
i = player_store.index(v)
|
153
|
+
if i.nil?
|
154
|
+
raise "#{v} not found in plot"
|
155
|
+
nil
|
156
|
+
else
|
157
|
+
"#<PIN_#{i}>"
|
158
|
+
end
|
159
|
+
else
|
160
|
+
"#<EIN_#{i}>"
|
161
|
+
end
|
162
|
+
else
|
163
|
+
v
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def unserialize v
|
168
|
+
if v.kind_of?(Array)
|
169
|
+
result = []
|
170
|
+
v.each do |e|
|
171
|
+
result.push unserialize(e)
|
172
|
+
end
|
173
|
+
result
|
174
|
+
elsif v.kind_of?(Hash)
|
175
|
+
result = {}
|
176
|
+
v.each_pair do |k, v|
|
177
|
+
result[unserialize(k)] = unserialize(v)
|
178
|
+
end
|
179
|
+
result
|
180
|
+
elsif v.kind_of?(String)
|
181
|
+
if m = v.match(/#<SIN_([0-9]+)>/)
|
182
|
+
plot.scene_classes[m[1].to_i]
|
183
|
+
elsif m = v.match(/#<EIN_([0-9]+)>/)
|
184
|
+
entity_store[m[1].to_i]
|
185
|
+
elsif m = v.match(/#<PIN_([0-9]+)>/)
|
186
|
+
player_store[m[1].to_i]
|
187
|
+
else
|
188
|
+
v
|
189
|
+
end
|
190
|
+
else
|
191
|
+
v
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def rebuild1 e, h
|
196
|
+
h.each_pair do |k, v|
|
197
|
+
if k.to_s.start_with?('@')
|
198
|
+
e.instance_variable_set(k, unserialize(v))
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def rebuild2 e, h
|
204
|
+
h.each_pair do |k, v|
|
205
|
+
if k.to_s != 'class' and !k.to_s.start_with?('@')
|
206
|
+
e.send("#{k}=", unserialize(v))
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def hash_subplot s
|
212
|
+
result = { entities: [], instance_variables: {}, theater_instance_variables: {} }
|
213
|
+
s.instance_variables.each { |i|
|
214
|
+
v = s.instance_variable_get(i)
|
215
|
+
result[:instance_variables][i] = serialize(v) if can_serialize?(v)
|
216
|
+
}
|
217
|
+
s.theater.instance_variables.each { |i|
|
218
|
+
v = s.theater.instance_variable_get(i)
|
219
|
+
result[:theater_instance_variables][i] = serialize(v) if can_serialize?(v)
|
220
|
+
}
|
221
|
+
s.entities.each { |s|
|
222
|
+
result[:entities].push serialize(s)
|
223
|
+
}
|
224
|
+
result[:class] = s.class.to_s.split('::').last
|
225
|
+
result
|
226
|
+
end
|
227
|
+
|
228
|
+
def rebuild_subplot s, h
|
229
|
+
s.entities.each { |e|
|
230
|
+
s.destroy e
|
231
|
+
}
|
232
|
+
h[:instance_variables].each_pair { |k, v|
|
233
|
+
s.instance_variable_set(k, unserialize(v))
|
234
|
+
}
|
235
|
+
h[:theater_instance_variables].each_pair { |k, v|
|
236
|
+
s.theater.instance_variable_set(k, unserialize(v))
|
237
|
+
}
|
238
|
+
i = 0
|
239
|
+
h[:entities].each { |e|
|
240
|
+
s.add_entity unserialize(e)
|
241
|
+
i += 1
|
242
|
+
}
|
243
|
+
end
|
244
|
+
|
245
|
+
def entity_store
|
246
|
+
@entity_store ||= []
|
247
|
+
end
|
248
|
+
|
249
|
+
def player_store
|
250
|
+
@player_store ||= []
|
251
|
+
end
|
252
|
+
|
253
|
+
def hash_entity e
|
254
|
+
h = {}
|
255
|
+
e.instance_variables.each { |i|
|
256
|
+
v = e.instance_variable_get(i)
|
257
|
+
h[i] = serialize(v) unless hash_blacklist.include?(i) or !can_serialize?(v)
|
258
|
+
}
|
259
|
+
h[:class] = e.class.to_s.split('::').last
|
260
|
+
h[:parent] = serialize(e.parent)
|
261
|
+
h
|
262
|
+
end
|
263
|
+
end
|
264
|
+
end
|