Olib 2.0.0.pre.rc.1 → 2.0.0.pre.rc.6
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/Olib.gemspec +1 -1
- data/lib/Olib/bounty.rb +16 -23
- data/lib/Olib/character/group.rb +238 -225
- data/lib/Olib/combat/attack.rb +60 -0
- data/lib/Olib/combat/creature.rb +77 -59
- data/lib/Olib/combat/creatures.json +1770 -0
- data/lib/Olib/combat/creatures.rb +8 -22
- data/lib/Olib/combat/metadata.rb +13 -0
- data/lib/Olib/core/action.rb +6 -0
- data/lib/Olib/core/container.rb +5 -1
- data/lib/Olib/core/containers.rb +37 -18
- data/lib/Olib/core/exist.rb +14 -15
- data/lib/Olib/core/item.rb +11 -0
- data/lib/Olib/core/scroll.rb +37 -0
- data/lib/Olib/core/transaction.rb +15 -3
- data/lib/Olib/ext/matchdata.rb +1 -1
- data/lib/Olib/go2.rb +1 -2
- data/lib/Olib/log.rb +42 -0
- data/lib/Olib/loot.rb +2 -1
- data/lib/Olib/opts.rb +42 -0
- data/lib/Olib/pattern_matching/any.rb +0 -11
- data/lib/Olib/pattern_matching/result.rb +16 -1
- data/lib/Olib/pattern_matching/rill.rb +13 -5
- data/lib/Olib/version.rb +1 -1
- data/lib/Olib/xml.rb +6 -2
- metadata +8 -4
- data/lib/Olib/objects/scroll.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f7d8e8dfe837282ceb421c8919c9b14385299f9f718493dc74efef8c9863cb4a
|
4
|
+
data.tar.gz: dffc7436f4fc2da600ed00104ca8ca53e9880226d846c12c67987fe36ca9845d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bde4171be06ed24d979ffbc9a49b68a7159af161006607194485502d4e9f8a43d6c9b10b8417b2e915f8e30475670a4c87965ac0d63609302f804ea4c6e15990
|
7
|
+
data.tar.gz: 97ebab201d826e5e483777535ee91d93a9d80110eea2f329c142d3893a0985409957e95f2d4f74e28bedd1832cdf17636c160e14dd580003013a940fa2c4de83
|
data/Olib.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
|
|
11
11
|
s.authors = ["Ondreian Shamsiel"]
|
12
12
|
s.email = "ondreian.shamsiel@gmail.com"
|
13
13
|
s.homepage = "https://github.com/ondreian/Olib"
|
14
|
-
s.files = %w[Olib.gemspec] + Dir["*.md", "lib/**/*.rb"]
|
14
|
+
s.files = %w[Olib.gemspec] + Dir["*.md", "lib/**/*.rb", "lib/**/*.json"]
|
15
15
|
#s.require_paths = %w[lib]
|
16
16
|
# s.add_runtime_dependency "shoes"
|
17
17
|
s.license = "MIT"
|
data/lib/Olib/bounty.rb
CHANGED
@@ -6,7 +6,7 @@ class Bounty
|
|
6
6
|
@@listeners = {}
|
7
7
|
# this should be refactored to use CONST
|
8
8
|
REGEX = OpenStruct.new(
|
9
|
-
creature_problem: /It appears they have a creature problem they\'d like you to solve/,
|
9
|
+
creature_problem: /"Hmm, I've got a task here from (?<town>.*?)\. It appears they have a creature problem they\'d like you to solve/,
|
10
10
|
report_to_guard: /^You succeeded in your task and should report back to/,
|
11
11
|
get_skin_bounty: /The local furrier/,
|
12
12
|
heirloom_found: /^You have located the heirloom and should bring it back to/,
|
@@ -17,16 +17,15 @@ class Bounty
|
|
17
17
|
heirloom: /^You have been tasked to recover (a|an|some) (?<heirloom>.*?) that an unfortunate citizen lost after being attacked by (a|an|some) (?<creature>.*?) (?:in|on|around|near|by) (?<area>.*?)(| near (?<realm>.*?))\./,
|
18
18
|
|
19
19
|
|
20
|
-
get_rescue: /It appears that a local resident urgently needs our help in some matter/,
|
21
|
-
get_bandits: /It appears they have a bandit problem they'd like you to solve./,
|
22
|
-
get_heirloom: /It appears they need your help in tracking down some kind of lost heirloom/,
|
20
|
+
get_rescue: /"Hmm, I've got a task here from (?<town>.*?)\. It appears that a local resident urgently needs our help in some matter/,
|
21
|
+
get_bandits: /"Hmm, I've got a task here from (?<town>.*?)\. It appears they have a bandit problem they'd like you to solve./,
|
22
|
+
get_heirloom: /"Hmm, I've got a task here from (?<town>.*?)\. It appears they need your help in tracking down some kind of lost heirloom/,
|
23
23
|
get_herb_bounty: /local herbalist|local healer|local alchemist/,
|
24
|
-
get_gem_bounty: /The local gem dealer, (?<npc>[a-zA-Z ]+), has an order to fill and wants our help/,
|
24
|
+
get_gem_bounty: /"Hmm, I've got a task here from (?<town>.*?)\. The local gem dealer, (?<npc>[a-zA-Z ]+), has an order to fill and wants our help/,
|
25
25
|
|
26
26
|
herb: /requires (?:a |an |)(?<herb>.*?) found (?:in|on|around|near) (?<area>.*?)(| (near|between) (?<realm>.*?)). These samples must be in pristine condition. You have been tasked to retrieve (?<number>[\d]+)/,
|
27
27
|
escort: /Go to the (.*?) and WAIT for (?:him|her|them) to meet you there. You must guarantee (?:his|her|their) safety to (?<destination>.*?) as soon as/,
|
28
|
-
gem: /has received orders from multiple customers requesting (?:a|an|some) (?<gem>[a-zA-Z '-]+). You have been tasked to retrieve (?<number>[0-9]+)/,
|
29
|
-
|
28
|
+
gem: /The gem dealer in (?<town>.*?), (?<npc>.*?), has received orders from multiple customers requesting (?:a|an|some) (?<gem>[a-zA-Z '-]+). You have been tasked to retrieve (?<number>[0-9]+)/,
|
30
29
|
cull: /^You have been tasked to suppress (?<creature>(?!bandit).*) activity (?:in|on|around) (?<area>.*?)(| (near|between) (?<realm>.*?)). You need to kill (?<number>[0-9]+)/,
|
31
30
|
bandits: /^You have been tasked to suppress bandit activity (?:in|on|around) (?<area>.*?) (?:near|between|under) (?<realm>.*?). You need to kill (?<number>[0-9]+)/,
|
32
31
|
|
@@ -35,7 +34,9 @@ class Bounty
|
|
35
34
|
none: /You are not currently assigned a task/,
|
36
35
|
skin: /^You have been tasked to retrieve (?<number>\d+) (?<skin>.*?) of at least (?<quality>.*?) quality for (?<buyer>.*?) in (?<realm>.*?)\.\s+You can SKIN them off the corpse of (a|an|some) (?<creature>.*?) or/,
|
37
36
|
|
38
|
-
help_bandits: /You have been tasked to help (?<partner>.*?) suppress bandit activity (?:in|on|around) (?<area>.*?) (?:near|between|under) (?<realm>.*?). You need to kill (?<number>[0-9]+)
|
37
|
+
help_bandits: /You have been tasked to help (?<partner>.*?) suppress bandit activity (?:in|on|around) (?<area>.*?) (?:near|between|under) (?<realm>.*?). You need to kill (?<number>[0-9]+)/,
|
38
|
+
help_creatures: /You have been tasked to help (?<partner>.*?) kill a dangerous creature by suppressing (?<creature>.*) activity (?:in|on|around|near) (?<area>.*?) (?:near|between|under) (?<realm>.*?) during the hunt. You need to kill (?<number>[0-9]+)/,
|
39
|
+
help_cull: /You have been tasked to help (?<partner>.*?) suppress (?<creature>.*) activity (?:in|on|around|near) (?<area>.*?) (?:near|between|under) (?<realm>.*?). You need to kill (?<number>[0-9]+)/,
|
39
40
|
)
|
40
41
|
|
41
42
|
# convenience list to get all types of bounties
|
@@ -115,23 +116,15 @@ class Bounty
|
|
115
116
|
Bounty.parse(checkbounty)
|
116
117
|
end
|
117
118
|
|
118
|
-
def Bounty.ask_for_bounty
|
119
|
-
if invisible?
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
fput "unhide"
|
125
|
-
end
|
126
|
-
|
127
|
-
if Bounty.npc
|
128
|
-
fput "ask ##{Bounty.npc.id} for bounty"
|
129
|
-
Bounty
|
119
|
+
def Bounty.ask_for_bounty(expedite: false)
|
120
|
+
fput "unhide" if invisible?
|
121
|
+
fput "unhide" if hidden?
|
122
|
+
raise Exception, "could not find Bounty.npc here" unless Bounty.npc
|
123
|
+
if expedite
|
124
|
+
fput "ask ##{Bounty.npc.id} for expedite"
|
130
125
|
else
|
131
|
-
|
126
|
+
fput "ask ##{Bounty.npc.id} for bounty"
|
132
127
|
end
|
133
|
-
# give the XML parser time to update
|
134
|
-
sleep 0.2
|
135
128
|
end
|
136
129
|
|
137
130
|
def Bounty.herbalist
|
data/lib/Olib/character/group.rb
CHANGED
@@ -1,257 +1,99 @@
|
|
1
1
|
require "ostruct"
|
2
|
+
require "benchmark"
|
2
3
|
require "Olib/character/disk"
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@birth = Time.now
|
10
|
-
@members = []
|
11
|
-
end
|
12
|
-
|
13
|
-
def clear!
|
14
|
-
@members = []
|
15
|
-
@birth = Time.now
|
16
|
-
@leader = nil
|
17
|
-
end
|
18
|
-
|
19
|
-
def size
|
20
|
-
@members.size
|
21
|
-
end
|
22
|
-
|
23
|
-
def empty?
|
24
|
-
@members.empty?
|
25
|
-
end
|
26
|
-
|
27
|
-
def add(pc, leader = false)
|
28
|
-
member = Member.new pc, leader
|
29
|
-
if leader
|
30
|
-
@leader = member
|
31
|
-
end
|
32
|
-
@members << member
|
33
|
-
self
|
34
|
-
end
|
35
|
-
|
36
|
-
def each(&block)
|
37
|
-
@members.each do |char| yield char end
|
38
|
-
self
|
39
|
-
end
|
40
|
-
|
41
|
-
def include?(pc)
|
42
|
-
return true if pc.is_a?(String) and Char.name.eql?(pc)
|
43
|
-
return true if pc.respond_to?(:noun) and Char.name.eql?(pc.noun)
|
44
|
-
return true if pc.respond_to?(:name) and Char.name.eql?(pc.name)
|
45
|
-
!find do |char|
|
46
|
-
if pc.is_a?(String)
|
47
|
-
char.noun.eql?(pc)
|
48
|
-
else
|
49
|
-
char.noun.eql?(pc.noun) || char.noun.eql?(pc.name)
|
50
|
-
end
|
51
|
-
end.nil?
|
52
|
-
end
|
53
|
-
|
54
|
-
def nonmembers
|
55
|
-
((GameObj.pcs || []) + Disk.all()).reject do |pc|
|
56
|
-
include?(pc)
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
def to_s
|
61
|
-
"<Members: [#{@members.join(" ")}]>"
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
class Member
|
66
|
-
attr_reader :id, :leader, :name, :noun
|
67
|
-
def initialize(pc, leader = false)
|
68
|
-
@id = pc.id
|
69
|
-
@leader = leader
|
70
|
-
@name = pc.name
|
71
|
-
@noun = pc.noun
|
72
|
-
end
|
73
|
-
|
74
|
-
def ref
|
75
|
-
GameObj[@id]
|
76
|
-
end
|
77
|
-
|
78
|
-
def leader?
|
79
|
-
@leader
|
80
|
-
end
|
81
|
-
|
82
|
-
def status
|
83
|
-
(ref.status.split(" ") || []).map(&:to_sym)
|
84
|
-
end
|
85
|
-
|
86
|
-
def is(state)
|
87
|
-
status =~ state
|
88
|
-
end
|
89
|
-
|
90
|
-
def ==(other)
|
91
|
-
@id == other.id
|
92
|
-
end
|
5
|
+
class Group
|
6
|
+
@@members ||= []
|
7
|
+
@@leader ||= nil
|
8
|
+
@@checked ||= false
|
9
|
+
@@status ||= :closed
|
93
10
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
98
|
-
MEMBERS = Members.new
|
99
|
-
OPEN = :open
|
100
|
-
CLOSED = :closed
|
101
|
-
CHECK_HOOK = self.name.to_s
|
102
|
-
NO_GROUP = /You are not currently in a group/
|
103
|
-
MEMBER = /<a exist="(?<id>.*?)" noun="(?<name>.*?)">(.*?)<\/a> is (?<type>(the leader|also a member) of your group|following you)\./
|
104
|
-
STATE = /^Your group status is currently (?<state>open|closed)\./
|
105
|
-
END_GROUP = /list of other options\./
|
106
|
-
|
107
|
-
PARSER = Proc.new do |line|
|
108
|
-
if line.strip.empty? || line =~ NO_GROUP
|
109
|
-
nil
|
110
|
-
elsif line =~ STATE
|
111
|
-
nil
|
112
|
-
elsif line =~ END_GROUP
|
113
|
-
Group.checked!
|
114
|
-
DownstreamHook.remove(CHECK_HOOK)
|
115
|
-
nil
|
116
|
-
elsif line =~ MEMBER
|
117
|
-
begin
|
118
|
-
pc = line.match(MEMBER).to_struct
|
119
|
-
Group::MEMBERS.add GameObj[pc.name], (line =~ /leader/ ? true : false)
|
120
|
-
if line =~ /following/
|
121
|
-
Group::MEMBERS.leader = OpenStruct.new(name: Char.name, leader: true)
|
122
|
-
end
|
123
|
-
nil
|
124
|
-
rescue Exception => e
|
125
|
-
respond e
|
126
|
-
respond e.backtrace
|
127
|
-
end
|
128
|
-
else
|
129
|
-
line
|
130
|
-
end
|
11
|
+
def self.clear()
|
12
|
+
@@members = []
|
13
|
+
@@checked = false
|
131
14
|
end
|
132
15
|
|
133
|
-
|
134
|
-
|
135
|
-
def Group.checked?
|
16
|
+
def self.checked?
|
136
17
|
@@checked
|
137
18
|
end
|
138
19
|
|
139
|
-
def
|
140
|
-
|
141
|
-
|
20
|
+
def self.push(*members)
|
21
|
+
members.each do |member|
|
22
|
+
@@members.push(member) unless include?(member)
|
23
|
+
end
|
142
24
|
end
|
143
25
|
|
144
|
-
def
|
145
|
-
|
26
|
+
def self.delete(*members)
|
27
|
+
gone = members.map(&:id)
|
28
|
+
@@members.reject! do |m| gone.include?(m.id) end
|
146
29
|
end
|
147
30
|
|
148
|
-
def
|
149
|
-
|
31
|
+
def self.members
|
32
|
+
maybe_check
|
33
|
+
@@members.dup
|
150
34
|
end
|
151
35
|
|
152
|
-
def
|
153
|
-
|
154
|
-
MEMBERS
|
36
|
+
def self._members
|
37
|
+
@@members
|
155
38
|
end
|
156
39
|
|
157
|
-
def
|
40
|
+
def self.disks
|
158
41
|
return [Disk.find_by_name(Char.name)].compact unless Group.leader?
|
159
|
-
members.map(&:
|
160
|
-
Disk.find_by_name(name)
|
161
|
-
end.compact
|
42
|
+
members.map(&:noun).map do |noun| Disk.find_by_name(noun) end.compact
|
162
43
|
end
|
163
44
|
|
164
|
-
def
|
165
|
-
|
45
|
+
def self.to_s
|
46
|
+
@@members.to_s
|
166
47
|
end
|
167
48
|
|
168
|
-
|
169
|
-
|
170
|
-
Group.unobserve()
|
171
|
-
@@checked = false
|
172
|
-
MEMBERS.clear!
|
173
|
-
DownstreamHook.add(CHECK_HOOK, PARSER)
|
174
|
-
Game._puts "<c>group\r\n"
|
175
|
-
wait_until { Group.checked? }
|
176
|
-
Group.observe()
|
177
|
-
MEMBERS
|
49
|
+
def self.checked=(flag)
|
50
|
+
@@checked = flag
|
178
51
|
end
|
179
52
|
|
180
|
-
def
|
181
|
-
|
53
|
+
def self.status=(state)
|
54
|
+
@@status = state
|
182
55
|
end
|
183
56
|
|
184
|
-
def
|
185
|
-
|
57
|
+
def self.status()
|
58
|
+
@@status
|
186
59
|
end
|
187
60
|
|
188
|
-
def
|
189
|
-
|
61
|
+
def self.open?
|
62
|
+
maybe_check
|
63
|
+
@@status.eql?(:open)
|
190
64
|
end
|
191
65
|
|
192
|
-
def
|
193
|
-
|
66
|
+
def self.closed?
|
67
|
+
not open?
|
194
68
|
end
|
195
69
|
|
70
|
+
# ran at the initialization of a script
|
71
|
+
def self.check
|
72
|
+
Group.clear()
|
73
|
+
ttl = Time.now + 3
|
74
|
+
Game._puts "<c>group\r\n"
|
75
|
+
wait_until { Group.checked? or Time.now > ttl }
|
76
|
+
@@members.dup
|
77
|
+
end
|
196
78
|
|
197
|
-
|
198
|
-
|
199
|
-
# <a exist="-10467645" noun="Oreh">Oreh</a> joins your group.
|
200
|
-
# You add <a exist="-10467645" noun="Oreh">Oreh</a> to your group.
|
201
|
-
# You remove <a exist="-10467645" noun="Oreh">Oreh</a> from the group.
|
202
|
-
JOIN = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> joins your group.$}
|
203
|
-
LEAVE = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> leaves your group.$}
|
204
|
-
ADD = %r{^You add <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> to your group.$}
|
205
|
-
REMOVE = %r{^You remove <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> from the group.$}
|
206
|
-
NOOP = %r{^But <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> is already a member of your group!$}
|
207
|
-
EXIST = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a>}
|
208
|
-
ANY = Regexp.union(JOIN, LEAVE, ADD, REMOVE, NOOP)
|
79
|
+
def self.maybe_check
|
80
|
+
Group.check unless checked?
|
209
81
|
end
|
210
82
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
Group.consume(line.strip)
|
215
|
-
rescue => exception
|
216
|
-
respond exception
|
217
|
-
respond exception.backtrace
|
218
|
-
end
|
219
|
-
line
|
220
|
-
}
|
83
|
+
def self.nonmembers
|
84
|
+
GameObj.pcs.to_a.reject {|pc| ids.include?(pc.id) }
|
85
|
+
end
|
221
86
|
|
222
|
-
def self.
|
223
|
-
|
224
|
-
DownstreamHook.add("__group_observer", GROUP_OBSERVER)
|
87
|
+
def self.leader=(char)
|
88
|
+
@@leader = char
|
225
89
|
end
|
226
90
|
|
227
|
-
def self.
|
228
|
-
|
91
|
+
def self.leader
|
92
|
+
@@leader
|
229
93
|
end
|
230
94
|
|
231
|
-
|
232
|
-
|
233
|
-
def self.consume(line)
|
234
|
-
return unless line.match(Group::Term::ANY)
|
235
|
-
person = GameObj[Term::EXIST.match(line)[:id]]
|
236
|
-
case line
|
237
|
-
when Term::JOIN
|
238
|
-
Group.members.add(person) unless Group.members.include?(person)
|
239
|
-
when Term::ADD
|
240
|
-
Group.members.add(person) unless Group.members.include?(person)
|
241
|
-
when Term::NOOP
|
242
|
-
Group.members.add(person) unless Group.members.include?(person)
|
243
|
-
when Term::LEAVE
|
244
|
-
Group.members.members.delete(Group.members.find do |member|
|
245
|
-
member.id.eql?(person.id)
|
246
|
-
end)
|
247
|
-
when Term::REMOVE
|
248
|
-
Group.members.members.delete(Group.members.find do |member|
|
249
|
-
member.id.eql?(person.id)
|
250
|
-
end)
|
251
|
-
else
|
252
|
-
# silence is golden
|
253
|
-
end
|
254
|
-
Group.persist()
|
95
|
+
def self.leader?
|
96
|
+
@@leader.eql?(:self)
|
255
97
|
end
|
256
98
|
|
257
99
|
def self.add(*members)
|
@@ -259,30 +101,201 @@ module Group
|
|
259
101
|
if member.is_a?(Array)
|
260
102
|
Group.add(*member)
|
261
103
|
else
|
104
|
+
member = GameObj.pcs.find {|pc| pc.noun.eql?(member)} if member.is_a?(String)
|
105
|
+
|
106
|
+
return if member.nil?
|
107
|
+
|
262
108
|
result = dothistimeout("group ##{member.id}", 3, Regexp.union(
|
263
109
|
%r{You add #{member.noun} to your group},
|
264
110
|
%r{#{member.noun}'s group status is closed},
|
265
111
|
%r{But #{member.noun} is already a member of your group}))
|
266
112
|
|
267
113
|
case result
|
268
|
-
when %r{You add}
|
269
|
-
Group.
|
270
|
-
|
271
|
-
when %r{already a member}
|
272
|
-
[:noop, member]
|
114
|
+
when %r{You add}, %r{already a member}
|
115
|
+
Group.push(member)
|
116
|
+
{ok: member}
|
273
117
|
when %r{closed}
|
274
|
-
|
118
|
+
Group.delete(member)
|
119
|
+
{err: member}
|
275
120
|
else
|
276
121
|
end
|
277
122
|
end
|
278
123
|
end
|
279
124
|
end
|
280
125
|
|
281
|
-
def self.
|
282
|
-
|
126
|
+
def self.ids
|
127
|
+
@@members.map(&:id)
|
128
|
+
end
|
129
|
+
|
130
|
+
def self.include?(*members)
|
131
|
+
members.all? { |m| ids.include?(m.id) }
|
283
132
|
end
|
284
133
|
|
285
134
|
def self.broken?
|
286
|
-
|
287
|
-
|
288
|
-
|
135
|
+
if Group.leader?
|
136
|
+
(GameObj.pcs.map(&:noun) & @@members.map(&:noun)).size < @@members.size
|
137
|
+
else
|
138
|
+
GameObj.pcs.find do |pc| pc.noun.eql?(Group.leader.noun) end.nil?
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.method_missing(method, *args, &block)
|
143
|
+
@@members.send(method, *args, &block)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
class Group
|
148
|
+
module Observer
|
149
|
+
module Term
|
150
|
+
##
|
151
|
+
## passive messages
|
152
|
+
##
|
153
|
+
# <a exist="-10467645" noun="Oreh">Oreh</a> joins your group.
|
154
|
+
JOIN = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> joins your group.$}
|
155
|
+
# <a exist="-10467645" noun="Oreh">Oreh</a> leaves your group
|
156
|
+
LEAVE = %r{^<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> leaves your group.$}
|
157
|
+
# You add <a exist="-10467645" noun="Oreh">Oreh</a> to your group.
|
158
|
+
ADD = %r{^You add <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> to your group.$}
|
159
|
+
# You remove <a exist="-10467645" noun="Oreh">Oreh</a> from the group.
|
160
|
+
REMOVE = %r{^You remove <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> from the group.$}
|
161
|
+
NOOP = %r{^But <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> is already a member of your group!$}
|
162
|
+
# <a exist="-10488845" noun="Etanamir">Etanamir</a> designates you as the new leader of the group.
|
163
|
+
HAS_LEADER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> designates you as the new leader of the group\.$}
|
164
|
+
SWAP_LEADER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> designates <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> as the new leader of the group.}
|
165
|
+
|
166
|
+
# You designate <a exist="-10778599" noun="Ondreian">Ondreian</a> as the new leader of the group.
|
167
|
+
GAVE_LEADER_AWAY = %r{You designate <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> as the new leader of the group\.$}
|
168
|
+
# You disband your group.
|
169
|
+
DISBAND = %r{^You disband your group}
|
170
|
+
# <a exist="-10488845" noun="Etanamir">Etanamir</a> adds you to <a exist="-10488845" noun="Etanamir">his</a> group.
|
171
|
+
ADDED_TO_NEW_GROUP = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> adds you to <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> group.}
|
172
|
+
# You join <a exist="-10488845" noun="Etanamir">Etanamir</a>.
|
173
|
+
JOINED_NEW_GROUP = %r{You join <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a>\.$}
|
174
|
+
# <a exist="-10488845" noun="Etanamir">Etanamir</a> adds <a exist="-10974229" noun="Szan">Szan</a> to <a exist="-10488845" noun="Etanamir">his</a> group.
|
175
|
+
LEADER_ADDED_MEMBER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> adds <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> to <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> group\.$}
|
176
|
+
# <a exist="-10488845" noun="Etanamir">Etanamir</a> removes <a exist="-10974229" noun="Szan">Szan</a> from the group.
|
177
|
+
LEADER_REMOVED_MEMBER = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> removes <a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a> from the group\.$}
|
178
|
+
##
|
179
|
+
## active messages
|
180
|
+
##
|
181
|
+
NO_GROUP = /You are not currently in a group/
|
182
|
+
MEMBER = /<a exist="(?<id>.*?)" noun="(?<name>.*?)">(.*?)<\/a> is (?<type>(the leader|also a member) of your group|following you)\./
|
183
|
+
STATUS = /^Your group status is currently (?<status>open|closed)\./
|
184
|
+
|
185
|
+
GROUP_EMPTIED = %[<indicator id='IconJOINED' visible='n'/>]
|
186
|
+
GROUP_EXISTS = %[<indicator id='IconJOINED' visible='y'/>]
|
187
|
+
GIVEN_LEADERSHIP = %[designates you as the new leader of the group.]
|
188
|
+
|
189
|
+
ANY = Regexp.union(
|
190
|
+
JOIN,
|
191
|
+
LEAVE,
|
192
|
+
ADD,
|
193
|
+
REMOVE,
|
194
|
+
DISBAND,
|
195
|
+
NOOP,
|
196
|
+
STATUS,
|
197
|
+
NO_GROUP,
|
198
|
+
MEMBER,
|
199
|
+
|
200
|
+
HAS_LEADER,
|
201
|
+
SWAP_LEADER,
|
202
|
+
|
203
|
+
LEADER_ADDED_MEMBER,
|
204
|
+
LEADER_REMOVED_MEMBER,
|
205
|
+
|
206
|
+
ADDED_TO_NEW_GROUP,
|
207
|
+
JOINED_NEW_GROUP,
|
208
|
+
GAVE_LEADER_AWAY,
|
209
|
+
)
|
210
|
+
|
211
|
+
EXIST = %r{<a exist="(?<id>[\d-]+)" noun="(?<noun>[A-Za-z]+)">(?<name>\w+?)</a>}
|
212
|
+
end
|
213
|
+
|
214
|
+
CALLBACK = -> line {
|
215
|
+
begin
|
216
|
+
# fast first-pass
|
217
|
+
if line.include?("group") or line.include?("following you") or line.include?("IconJOINED")
|
218
|
+
# more detailed pass
|
219
|
+
if match_data = Observer.wants?(line)
|
220
|
+
Observer.consume(line.strip, match_data)
|
221
|
+
end
|
222
|
+
end
|
223
|
+
rescue => exception
|
224
|
+
respond(exception)
|
225
|
+
respond(exception.backtrace)
|
226
|
+
ensure
|
227
|
+
return line
|
228
|
+
end
|
229
|
+
}
|
230
|
+
|
231
|
+
def self.exist(xml)
|
232
|
+
xml.scan(Group::Observer::Term::EXIST).map { |id, noun, name| GameObj[id] }
|
233
|
+
end
|
234
|
+
|
235
|
+
def self.wants?(line)
|
236
|
+
line.strip.match(Term::ANY) or
|
237
|
+
line.include?(Term::GROUP_EMPTIED)
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.consume(line, match_data)
|
241
|
+
if line.include?(Term::GIVEN_LEADERSHIP)
|
242
|
+
return Group.leader = :self
|
243
|
+
end
|
244
|
+
|
245
|
+
## Group indicator changed!
|
246
|
+
if line.include?(Term::GROUP_EMPTIED)
|
247
|
+
Group.leader = :self
|
248
|
+
return Group._members.clear
|
249
|
+
end
|
250
|
+
|
251
|
+
people = exist(line)
|
252
|
+
|
253
|
+
if line.include?("is following you")
|
254
|
+
Group.leader = :self
|
255
|
+
elsif line.include?("is the leader of your group")
|
256
|
+
Group.leader = people.first
|
257
|
+
end
|
258
|
+
|
259
|
+
case line
|
260
|
+
when Term::NO_GROUP, Term::DISBAND
|
261
|
+
Group.leader = :self
|
262
|
+
return Group._members.clear
|
263
|
+
when Term::STATUS
|
264
|
+
Group.status = match_data[:status].to_sym
|
265
|
+
return Group.checked = true
|
266
|
+
when Term::GAVE_LEADER_AWAY
|
267
|
+
Group.push(people.first)
|
268
|
+
return Group.leader = people.first
|
269
|
+
when Term::ADDED_TO_NEW_GROUP, Term::JOINED_NEW_GROUP
|
270
|
+
Group.push(people.first)
|
271
|
+
return Group.leader = people.first
|
272
|
+
when Term::SWAP_LEADER
|
273
|
+
(old_leader, new_leader) = people
|
274
|
+
Group.push(*people) if Group.include?(old_leader) or Group.include?(new_leader)
|
275
|
+
return Group.leader = new_leader
|
276
|
+
when Term::LEADER_ADDED_MEMBER
|
277
|
+
(leader, added) = people
|
278
|
+
Group.push(added) if Group.include?(leader)
|
279
|
+
when Term::LEADER_REMOVED_MEMBER
|
280
|
+
(leader, removed) = people
|
281
|
+
return Group.delete(removed) if Group.include?(leader)
|
282
|
+
when Term::JOIN, Term::ADD, Term::NOOP, Term::MEMBER
|
283
|
+
return Group.push(*people)
|
284
|
+
when Term::LEAVE, Term::REMOVE
|
285
|
+
return Group.delete(*people)
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
|
290
|
+
def self.attach()
|
291
|
+
remove() if DownstreamHook.list.include?(self.name)
|
292
|
+
DownstreamHook.add(self.name, CALLBACK)
|
293
|
+
end
|
294
|
+
|
295
|
+
def self.remove()
|
296
|
+
DownstreamHook.remove(self.name)
|
297
|
+
end
|
298
|
+
end
|
299
|
+
|
300
|
+
Observer.attach()
|
301
|
+
end
|