Class: GameMachine::GameSystems::Chat

Inherits:
Actor::Base
  • Object
show all
Includes:
Commands
Defined in:
lib/game_machine/game_systems/chat.rb

Constant Summary

Constants inherited from Actor::Base

Actor::Base::ON_RECEIVE_HOOKS

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Commands

#commands

Methods inherited from Actor::Base

aspect, aspects, find, find_by_address, find_distributed, find_distributed_local, find_remote, hashring, local_path, model_filter, #onReceive, player_controller, #receive_message, #schedule_message, #sender, set_player_controller

Instance Attribute Details

#chat_idObject (readonly)

Returns the value of attribute chat_id.



16
17
18
# File 'lib/game_machine/game_systems/chat.rb', line 16

def chat_id
  @chat_id
end

#registered_asObject (readonly)

Returns the value of attribute registered_as.



16
17
18
# File 'lib/game_machine/game_systems/chat.rb', line 16

def registered_as
  @registered_as
end

Class Method Details

.subscribers_for_topic(topic) ⇒ Object



7
8
9
10
11
12
13
14
# File 'lib/game_machine/game_systems/chat.rb', line 7

def self.subscribers_for_topic(topic)
  datastore = GameMachine::Commands::DatastoreCommands.new
  if entity = datastore.get("chat_topic_#{topic}")
    entity.subscribers || MessageLib::Subscribers.new
  else
    MessageLib::Subscribers.new
  end
end

Instance Method Details

#add_subscriber(subscriber_id, topic) ⇒ Object



114
115
116
117
118
# File 'lib/game_machine/game_systems/chat.rb', line 114

def add_subscriber(subscriber_id,topic)
  stored_entity_id = "chat_topic_#{topic}"
  entity = MessageLib::Entity.new.set_id(subscriber_id)
  commands.datastore.call_dbproc(:chat_add_subscriber,stored_entity_id,entity,false)
end

#channel_flags_id(name) ⇒ Object



148
149
150
# File 'lib/game_machine/game_systems/chat.rb', line 148

def channel_flags_id(name)
  "channel_flags#{@chat_id}#{name}"
end

#create_topic_handler(topic) ⇒ Object



99
100
101
102
103
104
105
106
# File 'lib/game_machine/game_systems/chat.rb', line 99

def create_topic_handler(topic)
  name = "topic#{chat_id}#{topic}"
  builder = Actor::Builder.new(GameSystems::ChatTopic,chat_id,registered_as)
  actor_name = Digest::MD5.hexdigest(name)
  ref = builder.with_parent(context).with_name(actor_name).start
  actor_ref = Actor::Ref.new(ref,GameSystems::ChatTopic.name)
  @topic_handlers[topic] = actor_ref
end

#delete_channel_flags(channel_name) ⇒ Object



174
175
176
177
# File 'lib/game_machine/game_systems/chat.rb', line 174

def delete_channel_flags(channel_name)
  flags_id = channel_flags_id(channel_name)
  commands.datastore.delete(flags_id)
end

#flags_for_channel(channel_name) ⇒ Object



152
153
154
# File 'lib/game_machine/game_systems/chat.rb', line 152

def flags_for_channel(channel_name)
  @channel_flags.fetch(channel_name,[])
end

#get_flagsObject



156
157
158
159
160
161
162
163
164
# File 'lib/game_machine/game_systems/chat.rb', line 156

def get_flags
  {}.tap do |flags|
    @subscriptions.each do |name|
      if entity = commands.datastore.get(channel_flags_id(name))
        flags[name] = parse_channel_flags(entity.params)
      end
    end
  end
end

#get_subscriptionsObject



131
132
133
134
135
136
137
138
139
140
141
142
# File 'lib/game_machine/game_systems/chat.rb', line 131

def get_subscriptions
  subscriptions = Set.new
  entity_id = "subscriptions_#{chat_id}"
  if entity = commands.datastore.get(entity_id)
    if chat_channels = entity.chat_channels.get_chat_channel_list
      chat_channels.each do |channel|
        subscriptions.add(channel.name)
      end
    end
  end
  subscriptions
end

#invite_exists?(channel_name, invite_id) ⇒ Boolean

Returns:

  • (Boolean)


179
180
181
182
# File 'lib/game_machine/game_systems/chat.rb', line 179

def invite_exists?(channel_name,invite_id)
  key = "invite_#{channel_name}_#{invite_id}"
  commands.datastore.get(key)
end

#join_channel(name, flags) ⇒ Object



211
212
213
214
215
216
217
218
219
220
# File 'lib/game_machine/game_systems/chat.rb', line 211

def join_channel(name,flags)
  create_topic_handler(name)
  message = MessageLib::Subscribe.new.set_topic(name)
  message_queue.tell(message,topic_handler_for(name).actor)
  @subscriptions.add(name)
  save_subscriptions
  add_subscriber(chat_id,name)
  set_channel_flags(name,flags)
  GameMachine.logger.info "Player #{chat_id} Joined channel #{name} with flags #{flags}"
end

#join_channels(chat_channels) ⇒ Object



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
# File 'lib/game_machine/game_systems/chat.rb', line 184

def join_channels(chat_channels)
  chat_channels.each do |channel|
    if @topic_handlers[channel.name]
      GameMachine.logger.info "Topic handler exists for #{channel.name}, not creating"
      next
    end

    GameMachine.logger.info "Join request #{channel.name}"
    # Private channels.  format priv_[chat_id]_[channel name]
    # Players can create private channels with their player id, other
    # players must have an invite to join someone elses private channel
    if channel.name.match(/^priv/)
      if channel.name.match(/^priv_#{chat_id}/)
        join_channel(channel.name,channel.flags)
      elsif channel.invite_id
        if invite_exists?(channel.name,channel.invite_id)
          join_channel(channel.name,channel.flags)
        else
          GameMachine.logger.info "Invite id #{channel.invite_id} not found"
        end
      end
    else
      join_channel(channel.name,channel.flags)
    end
  end
end

#leave_all_channelsObject



82
83
84
85
86
87
88
89
# File 'lib/game_machine/game_systems/chat.rb', line 82

def leave_all_channels
  channels = MessageLib::ChatChannels.new
  @subscriptions.each do |name|
    channel = MessageLib::ChatChannel.new.set_name(name)
    leave_channel(channel)
  end
  get_sender.tell('complete',get_self)
end

#leave_channel(channel) ⇒ Object



228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/game_machine/game_systems/chat.rb', line 228

def leave_channel(channel)
  if topic_handler = topic_handler_for(channel.name)
    message = MessageLib::Unsubscribe.new.set_topic(channel.name)
    message_queue.tell(message,topic_handler_for(channel.name).actor)
    @subscriptions.delete_if {|sub| sub == channel.name}
    save_subscriptions
    remove_subscriber(chat_id,channel.name)
    topic_handler.tell(JavaLib::PoisonPill.get_instance)
    @topic_handlers.delete(channel.name)
    delete_channel_flags(channel.name)
  else
    GameMachine.logger.info "leave_channel: no topic handler found for #{channel.name}"
  end
end

#leave_channels(chat_channels) ⇒ Object



222
223
224
225
226
# File 'lib/game_machine/game_systems/chat.rb', line 222

def leave_channels(chat_channels)
  chat_channels.each do |channel|
    leave_channel(channel)
  end
end

#load_stateObject



31
32
33
34
35
36
# File 'lib/game_machine/game_systems/chat.rb', line 31

def load_state
  @subscriptions.each do |name|
    flags = flags_for_channel(name).join('|')
    join_channel(name,flags)
  end
end

#message_queueObject



91
92
93
# File 'lib/game_machine/game_systems/chat.rb', line 91

def message_queue
  MessageQueue.find
end

#on_receive(entity) ⇒ Object



38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/game_machine/game_systems/chat.rb', line 38

def on_receive(entity)
  if entity.is_a?(MessageLib::ChatDestroy)
    leave_all_channels
    return
  end

  if entity.has_join_chat
    join_channels(entity.join_chat.get_chat_channel_list)
    send_status
  end

  if entity.has_chat_message
    send_message(entity.chat_message)
  end

  if entity.has_leave_chat
    leave_channels(entity.leave_chat.get_chat_channel_list)
    send_status
  end

  if entity.has_chat_status
    send_status
  end
end

#parse_channel_flags(flags) ⇒ Object



144
145
146
# File 'lib/game_machine/game_systems/chat.rb', line 144

def parse_channel_flags(flags)
  flags.split('|')
end

#post_init(*args) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/game_machine/game_systems/chat.rb', line 17

def post_init(*args)
  @chat_id = args.first
  @registered_as = args.last
  @topic_handlers = {}

  # Update these values from the datastore, as this state needs to
  # persist between restarts
  @subscriptions = get_subscriptions
  @channel_flags = get_flags

  # Make sure we re-create our state from the persisted state if we died
  load_state
end

#remove_subscriber(subscriber_id, topic) ⇒ Object



108
109
110
111
112
# File 'lib/game_machine/game_systems/chat.rb', line 108

def remove_subscriber(subscriber_id,topic)
  stored_entity_id = "chat_topic_#{topic}"
  entity = MessageLib::Entity.new.set_id(subscriber_id)
  commands.datastore.call_dbproc(:chat_remove_subscriber,stored_entity_id,entity,false)
end

#save_subscriptionsObject



120
121
122
123
124
125
126
127
128
129
# File 'lib/game_machine/game_systems/chat.rb', line 120

def save_subscriptions
  entity_id = "subscriptions_#{chat_id}"
  channels = MessageLib::ChatChannels.new
  @subscriptions.each do |name|
    channel = MessageLib::ChatChannel.new.set_name(name)
    channels.add_chat_channel(channel)
  end
  entity = MessageLib::Entity.new.set_id(entity_id).set_chat_channels(channels)
  commands.datastore.put(entity)
end

#send_group_message(chat_message) ⇒ Object



254
255
256
257
258
259
260
261
262
263
264
# File 'lib/game_machine/game_systems/chat.rb', line 254

def send_group_message(chat_message)
  topic = chat_message.chat_channel.name
  if topic_handler = topic_handler_for(topic)
    entity = MessageLib::Entity.new.set_id('0').set_chat_message(chat_message)
    publish = MessageLib::Publish.new
    publish.set_topic(topic).set_message(entity)
    message_queue.tell(publish,topic_handler_for(topic).actor)
  else
    GameMachine.logger.info "send_message: no topic handler found for #{topic}"
  end
end

#send_message(chat_message) ⇒ Object



266
267
268
269
270
271
272
# File 'lib/game_machine/game_systems/chat.rb', line 266

def send_message(chat_message)
  if chat_message.type == 'group'
    send_group_message(chat_message)
  elsif chat_message.type == 'private'
    send_private_message(chat_message)
  end
end

#send_private_message(chat_message) ⇒ Object



243
244
245
246
247
248
249
250
251
252
# File 'lib/game_machine/game_systems/chat.rb', line 243

def send_private_message(chat_message)
  GameMachine.logger.info "Sending private chat message #{chat_message.message} to #{chat_message.chat_channel.name}"
  entity = MessageLib::Entity.new
  player = MessageLib::Player.new.set_id(chat_message.chat_channel.name)
  entity.set_id(player.id)
  entity.set_player(player)
  entity.set_chat_message(chat_message)
  entity.set_send_to_player(true)
  commands.player.send_message(entity)
end

#send_statusObject

flags = subscribers



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/game_machine/game_systems/chat.rb', line 64

def send_status
  channels = MessageLib::ChatChannels.new
  @subscriptions.each do |name|
    flags = @channel_flags.fetch(name,[])
    channel = MessageLib::ChatChannel.new.set_name(name)
    if flags.include?('subscribers')
      channel.set_subscribers(self.class.subscribers_for_topic(name))
    end
    channels.add_chat_channel(channel)
  end
  if registered_as == 'player'
    commands.player.send_message(channels,chat_id)
  else
    message = MessageLib::Entity.new.set_id(chat_id).set_chat_channels(channels)
    Actor::Base.find(registered_as).tell(message,get_self)
  end
end

#set_channel_flags(name, flags) ⇒ Object



166
167
168
169
170
171
172
# File 'lib/game_machine/game_systems/chat.rb', line 166

def set_channel_flags(name,flags)
  return if flags.nil?
  @channel_flags[name] = parse_channel_flags(flags)
  flags_id = channel_flags_id(name)
  entity = MessageLib::Entity.new.set_id(flags_id).set_params(flags)
  commands.datastore.put(entity)
end

#topic_handler_for(name) ⇒ Object



95
96
97
# File 'lib/game_machine/game_systems/chat.rb', line 95

def topic_handler_for(name)
  @topic_handlers.fetch(name,nil)
end