Package horizons :: Package messaging :: Module message
[hide private]
[frames] | no frames]

Source Code for Module horizons.messaging.message

  1  # ################################################### 
  2  # Copyright (C) 2008-2017 The Unknown Horizons Team 
  3  # team@unknown-horizons.org 
  4  # This file is part of Unknown Horizons. 
  5   
  6  # Unknown Horizons is free software; you can redistribute it and/or modify 
  7  # it under the terms of the GNU General Public License as published by 
  8  # the Free Software Foundation; either version 2 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # This program is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU General Public License 
 17  # along with this program; if not, write to the 
 18  # Free Software Foundation, Inc., 
 19  # 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA 
 20  # ################################################### 
 21   
 22  from typing import Tuple 
 23   
 24  from horizons.messaging.messagebus import MessageBus 
 25  from horizons.messaging.queuingmessagebus import QueuingMessageBus 
26 27 28 -class Message:
29 """Message class for the MessageBus. Every Message that is supposed to be 30 sent through the MessageBus has to subclass this base class, to ensure proper 31 setting of base attributes and inheriting the interface. 32 33 The first argument in each message is always a reference to the sender, 34 additional expected arguments are defined on the class-level attribute `arguments`, 35 these will be stored on the instance. 36 """ 37 arguments = tuple() # type: Tuple[str, ...] 38 bus = MessageBus 39
40 - def __init__(self, sender, *args):
41 self.sender = sender 42 if len(self.arguments) != len(args): 43 raise Exception('Unexpected number of arguments. Expected {:d}, received {:d}'.format( 44 len(self.arguments), len(args))) 45 46 for arg, value in zip(self.arguments, args): 47 setattr(self, arg, value)
48 49 @classmethod
50 - def subscribe(cls, callback, sender=None):
51 """Register a callback to be called whenever a message of this type is send. 52 53 callback - Callable that receives an instance of a message as only argument. 54 55 sender - If specified, the callback receives only messages that originated 56 from sender. By default, all messages are received. 57 58 Example: 59 60 >>> def cb(msg): 61 ... print 'Received', msg 62 63 >>> MessageClass.subscribe(cb) # Global 64 >>> MessageClass.subscribe(cb, sender=foo) # Specific sender 65 """ 66 if sender: 67 cls.bus().subscribe_locally(cls, sender, callback) 68 else: 69 cls.bus().subscribe_globally(cls, callback)
70 71 @classmethod
72 - def unsubscribe(cls, callback, sender=None):
73 """Stop your subscription of this message type for the specified callback. 74 75 callback - Callable that receives an instance of a message as only argument. 76 The same you've been using with `Message.subscribe`. 77 78 sender - If specified, the subscription will only be stopped for messages 79 from this sender. By default, all subscriptions are ended. 80 81 Note: There has to be a subscription, otherwise an error will be raised. 82 83 Example: 84 85 >>> MessageClass.subscribe(cb) 86 >>> MessageClass.broadcast('sender') 87 message received 88 >>> MessageClass.unsubscribe(cb) 89 >>> MessageClass.broadcast('sender') 90 """ 91 if sender: 92 cls.bus().unsubscribe_locally(cls, sender, callback) 93 else: 94 cls.bus().unsubscribe_globally(cls, callback)
95 96 @classmethod
97 - def discard(cls, callback, sender=None):
98 """Similar to `Message.unsubscribe`, but does not raise an error if the 99 callback has not been registered before. 100 """ 101 if sender: 102 cls.bus().discard_locally(cls, sender, callback) 103 else: 104 cls.bus().discard_globally(cls, callback)
105 106 @classmethod
107 - def broadcast(cls, *args):
108 """Send a message that is initialized with `args`. 109 110 The first argument is always a sender, the number of arguments has to be 111 N + 1, with N being the number of arguments defined on the message class. 112 113 Example: 114 115 >>> class Foo(Message): 116 ... arguments = ('a', 'b', ) 117 118 >>> Foo.broadcast('sender', 1, 2) 119 """ 120 cls.bus().broadcast(cls(*args))
121
122 123 -class QueuingMessage(Message):
124 """QueuingMessage class for the QueuingMessageBus. Every Message that is supposed to be 125 sent through the QueuingMessageBus has to subclass this subclass. 126 """ 127 bus = QueuingMessageBus 128 129 @classmethod
130 - def clear(cls, *args):
131 """Empty the message queue for this Message class 132 """ 133 cls.bus().clear(cls)
134 135 @classmethod
136 - def queue_len(cls, *args):
137 """Get the length the message queue for this Message class 138 """ 139 return cls.bus().queue_len(cls)
140
141 142 -class AddStatusIcon(QueuingMessage):
143 arguments = ('icon', )
144
145 146 -class RemoveStatusIcon(Message):
147 arguments = ( 148 'instance', # the instance from which to remove the icon 149 'icon_class' # class object of the icon that is to be removed 150 )
151
152 153 -class SettlerUpdate(Message):
154 """Sent when the level of a settler building changes. Message includes the new 155 level and the change (+1/-1). 156 """ 157 arguments = ('level', 'change', )
158
159 160 -class PlayerLevelUpgrade(Message):
161 """Sent when the settler level of a player increases.""" 162 arguments = ('level', 'building', )
163
164 165 -class SettlerInhabitantsChanged(Message):
166 """Class to signal that the number of inhabitants in a settler building 167 have changed.""" 168 arguments = ('change', )
169
170 171 -class ResourceBarResize(Message):
172 """Signals a change in resource bar size (not slot changes, but number of slot changes).""" 173 pass
174
175 176 -class UpgradePermissionsChanged(Message):
177 """In a settlement.""" 178 pass
179
180 181 -class SettlementRangeChanged(Message):
182 """Called on grow and perhaps shrink once that's implemented. Used by buildingtool. 183 Sent by a Settlement.""" 184 arguments = ( 185 'changed_tiles', # Actual tile objects 186 )
187
188 189 -class WorldObjectDeleted(Message):
190 """Called when a world object is being deleted. 191 Currently emitted in the process of destruction, i.e. you aren't guaranteed 192 to be able to access any attributes. 193 (Feel free to change the implementation if you need this). 194 """ 195 arguments = ('worldobject', 'worldid', )
196
197 198 -class ShipDestroyed(Message):
199 """Sent just when a ship is destroyed.""" 200 pass
201
202 203 -class NewPlayerSettlementHovered(Message):
204 """Sent when the mouse hovers over a different settlement than before, 205 and it belongs to the local player or is None.""" 206 arguments = ('settlement', )
207
208 209 -class HoverSettlementChanged(Message):
210 """Sent when hovering over any different settlement, or no settlement.""" 211 arguments = ('settlement', )
212
213 214 -class NewSettlement(Message):
215 """Sent when a new settlement is created.""" 216 arguments = ('settlement', 'warehouse_position', )
217
218 219 -class HoverInstancesChanged(Message):
220 """Sent when hovering over a different set of instances. 221 Not sent on every mouse move but with a bit of delay to be able to do more extensive 222 computation without risk of delays.""" 223 arguments = ('instances', )
224
225 226 -class NewDisaster(Message):
227 """Sent when a building is affected by a disaster.""" 228 arguments = ('building', 'disaster_class', 'disaster')
229
230 231 -class TabWidgetChanged(Message):
232 """Sent when the ingamegui displays a different set of tabs, i.e. the tabwidget is exchanged. 233 The tabs are not necessarily different from the old ones.""" 234 pass
235
236 237 -class GuiAction(Message):
238 """Sent on events pychan classifies as "action".""" 239 pass
240
241 242 -class GuiCancelAction(Message):
243 """Sent on events that originate from the cancelButton.""" 244 pass
245
246 247 -class GuiHover(Message):
248 """Sent on mouseEntered events""" 249 pass
250
251 252 -class ResourceProduced(Message):
253 """Sent when a production building finished the production of a resource.""" 254 arguments = ('caller', 'produced_resources', )
255
256 257 -class InstanceInventoryUpdated(Message):
258 """Message sent whenever an inventory of any instance is updated. 259 260 This message is sent by StorageComponent but sender is the instance! 261 """ 262 arguments = ('inventory', )
263
264 265 -class SettlementInventoryUpdated(Message):
266 """Message sent whenever a settlement's inventory is updated.""" 267 pass
268
269 270 -class PlayerInventoryUpdated(Message):
271 """Message sent whenever a player's inventory is updated.""" 272 pass
273
274 275 -class LanguageChanged(Message):
276 """Sent when the language has changed.""" 277 pass
278
279 280 -class SpeedChanged(Message):
281 """Sent when the ingame speed has changed.""" 282 arguments = ('old', 'new', )
283
284 285 -class SettingChanged(Message):
286 """Sent when a setting is changed in the dialog.""" 287 arguments = ('setting_name', 'old_value', 'new_value', )
288
289 290 -class MineEmpty(Message):
291 """Sent when there are no more resources left in a mine.""" 292 arguments = ('mine', )
293
294 295 -class LoadingProgress(Message):
296 """Sent when loading screen is updated with a new progress hint.""" 297 arguments = ('stage', )
298
299 300 -class ZoomChanged(Message):
301 """Sent when map zoom has changed.""" 302 arguments = ('zoom', )
303
304 305 -class ActionChanged(Message):
306 """Sent when a ConcreteObject changed its action""" 307 arguments = ('action', )
308