1 /* Copyright (C) 2017 Wildfire Games. 2 * This file is part of 0 A.D. 3 * 4 * 0 A.D. is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * 0 A.D. is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 #ifndef INCLUDED_MESSAGETYPES 19 #define INCLUDED_MESSAGETYPES 20 21 #include "simulation2/system/Components.h" 22 #include "simulation2/system/Entity.h" 23 #include "simulation2/system/Message.h" 24 25 #include "simulation2/helpers/Player.h" 26 #include "simulation2/helpers/Position.h" 27 28 #include "simulation2/components/ICmpPathfinder.h" 29 30 #include "maths/Vector3D.h" 31 32 #include "ps/CStr.h" 33 34 #define DEFAULT_MESSAGE_IMPL(name) \ 35 virtual int GetType() const { return MT_##name; } \ 36 virtual const char* GetScriptHandlerName() const { return "On" #name; } \ 37 virtual const char* GetScriptGlobalHandlerName() const { return "OnGlobal" #name; } \ 38 virtual JS::Value ToJSVal(const ScriptInterface& scriptInterface) const; \ 39 static CMessage* FromJSVal(const ScriptInterface&, JS::HandleValue val); 40 41 class SceneCollector; 42 class CFrustum; 43 44 class CMessageTurnStart : public CMessage 45 { 46 public: DEFAULT_MESSAGE_IMPL(TurnStart)47 DEFAULT_MESSAGE_IMPL(TurnStart) 48 49 CMessageTurnStart() 50 { 51 } 52 }; 53 54 // The update process is split into a number of phases, in an attempt 55 // to cope with dependencies between components. Each phase is implemented 56 // as a separate message. Simulation2.cpp sends them in sequence. 57 58 /** 59 * Generic per-turn update message, for things that don't care much about ordering. 60 */ 61 class CMessageUpdate : public CMessage 62 { 63 public: DEFAULT_MESSAGE_IMPL(Update)64 DEFAULT_MESSAGE_IMPL(Update) 65 66 CMessageUpdate(fixed turnLength) : 67 turnLength(turnLength) 68 { 69 } 70 71 fixed turnLength; 72 }; 73 74 /** 75 * Update phase for formation controller movement (must happen before individual 76 * units move to follow their formation). 77 */ 78 class CMessageUpdate_MotionFormation : public CMessage 79 { 80 public: DEFAULT_MESSAGE_IMPL(Update_MotionFormation)81 DEFAULT_MESSAGE_IMPL(Update_MotionFormation) 82 83 CMessageUpdate_MotionFormation(fixed turnLength) : 84 turnLength(turnLength) 85 { 86 } 87 88 fixed turnLength; 89 }; 90 91 /** 92 * Update phase for non-formation-controller unit movement. 93 */ 94 class CMessageUpdate_MotionUnit : public CMessage 95 { 96 public: DEFAULT_MESSAGE_IMPL(Update_MotionUnit)97 DEFAULT_MESSAGE_IMPL(Update_MotionUnit) 98 99 CMessageUpdate_MotionUnit(fixed turnLength) : 100 turnLength(turnLength) 101 { 102 } 103 104 fixed turnLength; 105 }; 106 107 /** 108 * Final update phase, after all other updates. 109 */ 110 class CMessageUpdate_Final : public CMessage 111 { 112 public: DEFAULT_MESSAGE_IMPL(Update_Final)113 DEFAULT_MESSAGE_IMPL(Update_Final) 114 115 CMessageUpdate_Final(fixed turnLength) : 116 turnLength(turnLength) 117 { 118 } 119 120 fixed turnLength; 121 }; 122 123 /** 124 * Prepare for rendering a new frame (set up model positions etc). 125 */ 126 class CMessageInterpolate : public CMessage 127 { 128 public: DEFAULT_MESSAGE_IMPL(Interpolate)129 DEFAULT_MESSAGE_IMPL(Interpolate) 130 131 CMessageInterpolate(float deltaSimTime, float offset, float deltaRealTime) : 132 deltaSimTime(deltaSimTime), offset(offset), deltaRealTime(deltaRealTime) 133 { 134 } 135 136 /// Elapsed simulation time since previous interpolate, in seconds. This is similar to the elapsed real time, except 137 /// it is scaled by the current simulation rate (and might indeed be zero). 138 float deltaSimTime; 139 /// Range [0, 1] (inclusive); fractional time of current frame between previous/next simulation turns. 140 float offset; 141 /// Elapsed real time since previous interpolate, in seconds. 142 float deltaRealTime; 143 }; 144 145 /** 146 * Add renderable objects to the scene collector. 147 * Called after CMessageInterpolate. 148 */ 149 class CMessageRenderSubmit : public CMessage 150 { 151 public: DEFAULT_MESSAGE_IMPL(RenderSubmit)152 DEFAULT_MESSAGE_IMPL(RenderSubmit) 153 154 CMessageRenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling) : 155 collector(collector), frustum(frustum), culling(culling) 156 { 157 } 158 159 SceneCollector& collector; 160 const CFrustum& frustum; 161 bool culling; 162 }; 163 164 /** 165 * Handle progressive loading of resources. 166 * A component that listens to this message must do the following: 167 * - Increase *msg.total by the non-zero number of loading tasks this component can perform. 168 * - If *msg.progressed == true, return and do nothing. 169 * - If you've loaded everything, increase *msg.progress by the value you added to .total 170 * - Otherwise do some loading, set *msg.progressed = true, and increase *msg.progress by a 171 * value indicating how much progress you've made in total (0 <= p <= what you added to .total) 172 * In some situations these messages will never be sent - components must ensure they 173 * load all their data themselves before using it in that case. 174 */ 175 class CMessageProgressiveLoad : public CMessage 176 { 177 public: DEFAULT_MESSAGE_IMPL(ProgressiveLoad)178 DEFAULT_MESSAGE_IMPL(ProgressiveLoad) 179 180 CMessageProgressiveLoad(bool* progressed, int* total, int* progress) : 181 progressed(progressed), total(total), progress(progress) 182 { 183 } 184 185 bool* progressed; 186 int* total; 187 int* progress; 188 }; 189 190 /** 191 * Broadcast after the entire simulation state has been deserialized. 192 * Components should do all their self-contained work in their Deserialize 193 * function when possible. But any reinitialisation that depends on other 194 * components or other entities, that might not be constructed until later 195 * in the deserialization process, may be done in response to this message 196 * instead. 197 */ 198 class CMessageDeserialized : public CMessage 199 { 200 public: DEFAULT_MESSAGE_IMPL(Deserialized)201 DEFAULT_MESSAGE_IMPL(Deserialized) 202 203 CMessageDeserialized() 204 { 205 } 206 }; 207 208 209 /** 210 * This is sent immediately after a new entity's components have all been created 211 * and initialised. 212 */ 213 class CMessageCreate : public CMessage 214 { 215 public: DEFAULT_MESSAGE_IMPL(Create)216 DEFAULT_MESSAGE_IMPL(Create) 217 218 CMessageCreate(entity_id_t entity) : 219 entity(entity) 220 { 221 } 222 223 entity_id_t entity; 224 }; 225 226 /** 227 * This is sent immediately before a destroyed entity is flushed and really destroyed. 228 * (That is, after CComponentManager::DestroyComponentsSoon and inside FlushDestroyedComponents). 229 * The entity will still exist at the time this message is sent. 230 * It's possible for this message to be sent multiple times for one entity, but all its components 231 * will have been deleted after the first time. 232 */ 233 class CMessageDestroy : public CMessage 234 { 235 public: DEFAULT_MESSAGE_IMPL(Destroy)236 DEFAULT_MESSAGE_IMPL(Destroy) 237 238 CMessageDestroy(entity_id_t entity) : 239 entity(entity) 240 { 241 } 242 243 entity_id_t entity; 244 }; 245 246 class CMessageOwnershipChanged : public CMessage 247 { 248 public: DEFAULT_MESSAGE_IMPL(OwnershipChanged)249 DEFAULT_MESSAGE_IMPL(OwnershipChanged) 250 251 CMessageOwnershipChanged(entity_id_t entity, player_id_t from, player_id_t to) : 252 entity(entity), from(from), to(to) 253 { 254 } 255 256 entity_id_t entity; 257 player_id_t from; 258 player_id_t to; 259 }; 260 261 /** 262 * Sent by CCmpPosition whenever anything has changed that will affect the 263 * return value of GetPosition2D() or GetRotation().Y 264 * 265 * If @c inWorld is false, then the other fields are invalid and meaningless. 266 * Otherwise they represent the current position. 267 */ 268 class CMessagePositionChanged : public CMessage 269 { 270 public: DEFAULT_MESSAGE_IMPL(PositionChanged)271 DEFAULT_MESSAGE_IMPL(PositionChanged) 272 273 CMessagePositionChanged(entity_id_t entity, bool inWorld, entity_pos_t x, entity_pos_t z, entity_angle_t a) : 274 entity(entity), inWorld(inWorld), x(x), z(z), a(a) 275 { 276 } 277 278 entity_id_t entity; 279 bool inWorld; 280 entity_pos_t x, z; 281 entity_angle_t a; 282 }; 283 284 /** 285 * Sent by CCmpPosition whenever anything has changed that will affect the 286 * return value of GetInterpolatedTransform() 287 */ 288 class CMessageInterpolatedPositionChanged : public CMessage 289 { 290 public: DEFAULT_MESSAGE_IMPL(InterpolatedPositionChanged)291 DEFAULT_MESSAGE_IMPL(InterpolatedPositionChanged) 292 293 CMessageInterpolatedPositionChanged(entity_id_t entity, bool inWorld, const CVector3D& pos0, const CVector3D& pos1) : 294 entity(entity), inWorld(inWorld), pos0(pos0), pos1(pos1) 295 { 296 } 297 298 entity_id_t entity; 299 bool inWorld; 300 CVector3D pos0; 301 CVector3D pos1; 302 }; 303 304 /*Sent whenever the territory type (neutral,own,enemy) differs from the former type*/ 305 class CMessageTerritoryPositionChanged : public CMessage 306 { 307 public: DEFAULT_MESSAGE_IMPL(TerritoryPositionChanged)308 DEFAULT_MESSAGE_IMPL(TerritoryPositionChanged) 309 310 CMessageTerritoryPositionChanged(entity_id_t entity, player_id_t newTerritory) : 311 entity(entity), newTerritory(newTerritory) 312 { 313 } 314 315 entity_id_t entity; 316 player_id_t newTerritory; 317 }; 318 319 /** 320 * Sent by CCmpUnitMotion during Update, whenever the motion status has changed 321 * since the previous update. 322 */ 323 class CMessageMotionChanged : public CMessage 324 { 325 public: DEFAULT_MESSAGE_IMPL(MotionChanged)326 DEFAULT_MESSAGE_IMPL(MotionChanged) 327 328 CMessageMotionChanged(bool starting, bool error) : 329 starting(starting), error(error) 330 { 331 } 332 333 bool starting; // whether this is a start or end of movement 334 bool error; // whether we failed to start moving (couldn't find any path) 335 }; 336 337 /** 338 * Sent when water height has been changed. 339 */ 340 class CMessageWaterChanged : public CMessage 341 { 342 public: DEFAULT_MESSAGE_IMPL(WaterChanged)343 DEFAULT_MESSAGE_IMPL(WaterChanged) 344 345 CMessageWaterChanged() 346 { 347 } 348 }; 349 350 /** 351 * Sent when terrain (texture or elevation) has been changed. 352 */ 353 class CMessageTerrainChanged : public CMessage 354 { 355 public: DEFAULT_MESSAGE_IMPL(TerrainChanged)356 DEFAULT_MESSAGE_IMPL(TerrainChanged) 357 358 CMessageTerrainChanged(int32_t i0, int32_t j0, int32_t i1, int32_t j1) : 359 i0(i0), j0(j0), i1(i1), j1(j1) 360 { 361 } 362 363 int32_t i0, j0, i1, j1; // inclusive lower bound, exclusive upper bound, in tiles 364 }; 365 366 /** 367 * Sent, at most once per turn, when the visibility of an entity changed 368 */ 369 class CMessageVisibilityChanged : public CMessage 370 { 371 public: DEFAULT_MESSAGE_IMPL(VisibilityChanged)372 DEFAULT_MESSAGE_IMPL(VisibilityChanged) 373 374 CMessageVisibilityChanged(player_id_t player, entity_id_t ent, int oldVisibility, int newVisibility) : 375 player(player), ent(ent), oldVisibility(oldVisibility), newVisibility(newVisibility) 376 { 377 } 378 379 player_id_t player; 380 entity_id_t ent; 381 int oldVisibility; 382 int newVisibility; 383 }; 384 385 /** 386 * Sent when ObstructionManager's view of the shape of the world has changed 387 * (changing the TILE_OUTOFBOUNDS tiles returned by Rasterise). 388 */ 389 class CMessageObstructionMapShapeChanged : public CMessage 390 { 391 public: DEFAULT_MESSAGE_IMPL(ObstructionMapShapeChanged)392 DEFAULT_MESSAGE_IMPL(ObstructionMapShapeChanged) 393 394 CMessageObstructionMapShapeChanged() 395 { 396 } 397 }; 398 399 /** 400 * Sent when territory assignments have changed. 401 */ 402 class CMessageTerritoriesChanged : public CMessage 403 { 404 public: DEFAULT_MESSAGE_IMPL(TerritoriesChanged)405 DEFAULT_MESSAGE_IMPL(TerritoriesChanged) 406 407 CMessageTerritoriesChanged() 408 { 409 } 410 }; 411 412 /** 413 * Sent by CCmpRangeManager at most once per turn, when an active range query 414 * has had matching units enter/leave the range since the last RangeUpdate. 415 */ 416 class CMessageRangeUpdate : public CMessage 417 { 418 public: 419 DEFAULT_MESSAGE_IMPL(RangeUpdate) 420 421 422 423 u32 tag; 424 std::vector<entity_id_t> added; 425 std::vector<entity_id_t> removed; 426 427 // CCmpRangeManager wants to store a vector of messages and wants to 428 // swap vectors instead of copying (to save on memory allocations), 429 // so add some constructors for it: 430 431 // don't init tag in empty ctor CMessageRangeUpdate()432 CMessageRangeUpdate() 433 { 434 } CMessageRangeUpdate(u32 tag)435 CMessageRangeUpdate(u32 tag) : tag(tag) 436 { 437 } CMessageRangeUpdate(u32 tag,const std::vector<entity_id_t> & added,const std::vector<entity_id_t> & removed)438 CMessageRangeUpdate(u32 tag, const std::vector<entity_id_t>& added, const std::vector<entity_id_t>& removed) 439 : tag(tag), added(added), removed(removed) 440 { 441 } CMessageRangeUpdate(const CMessageRangeUpdate & other)442 CMessageRangeUpdate(const CMessageRangeUpdate& other) 443 : CMessage(), tag(other.tag), added(other.added), removed(other.removed) 444 { 445 } 446 CMessageRangeUpdate& operator=(const CMessageRangeUpdate& other) 447 { 448 tag = other.tag; 449 added = other.added; 450 removed = other.removed; 451 return *this; 452 } 453 }; 454 455 /** 456 * Sent by CCmpPathfinder after async path requests. 457 */ 458 class CMessagePathResult : public CMessage 459 { 460 public: DEFAULT_MESSAGE_IMPL(PathResult)461 DEFAULT_MESSAGE_IMPL(PathResult) 462 463 CMessagePathResult(u32 ticket, const WaypointPath& path) : 464 ticket(ticket), path(path) 465 { 466 } 467 468 u32 ticket; 469 WaypointPath path; 470 }; 471 472 /** 473 * Sent by aura manager when a value of a certain entity's component is changed 474 */ 475 class CMessageValueModification : public CMessage 476 { 477 public: DEFAULT_MESSAGE_IMPL(ValueModification)478 DEFAULT_MESSAGE_IMPL(ValueModification) 479 480 CMessageValueModification(const std::vector<entity_id_t>& entities, std::wstring component, const std::vector<std::wstring>& valueNames) : 481 entities(entities), 482 component(component), 483 valueNames(valueNames) 484 { 485 } 486 487 std::vector<entity_id_t> entities; 488 std::wstring component; 489 std::vector<std::wstring> valueNames; 490 }; 491 492 /** 493 * Sent by atlas if the playercolor has been changed. 494 */ 495 class CMessagePlayerColorChanged : public CMessage 496 { 497 public: DEFAULT_MESSAGE_IMPL(PlayerColorChanged)498 DEFAULT_MESSAGE_IMPL(PlayerColorChanged) 499 500 CMessagePlayerColorChanged(player_id_t player) : 501 player(player) 502 { 503 } 504 505 player_id_t player; 506 }; 507 508 /** 509 * Sent by aura and tech managers when a value of a certain template's component is changed 510 */ 511 class CMessageTemplateModification : public CMessage 512 { 513 public: DEFAULT_MESSAGE_IMPL(TemplateModification)514 DEFAULT_MESSAGE_IMPL(TemplateModification) 515 516 CMessageTemplateModification(player_id_t player, std::wstring component, const std::vector<std::wstring>& valueNames) : 517 player(player), 518 component(component), 519 valueNames(valueNames) 520 { 521 } 522 523 player_id_t player; 524 std::wstring component; 525 std::vector<std::wstring> valueNames; 526 }; 527 528 /** 529 * Sent by CCmpVision when an entity's vision range changes. 530 */ 531 class CMessageVisionRangeChanged : public CMessage 532 { 533 public: DEFAULT_MESSAGE_IMPL(VisionRangeChanged)534 DEFAULT_MESSAGE_IMPL(VisionRangeChanged) 535 536 CMessageVisionRangeChanged(entity_id_t entity, entity_pos_t oldRange, entity_pos_t newRange) : 537 entity(entity), oldRange(oldRange), newRange(newRange) 538 { 539 } 540 541 entity_id_t entity; 542 entity_pos_t oldRange; 543 entity_pos_t newRange; 544 }; 545 546 /** 547 * Sent by CCmpVision when an entity's vision sharing changes. 548 */ 549 class CMessageVisionSharingChanged : public CMessage 550 { 551 public: DEFAULT_MESSAGE_IMPL(VisionSharingChanged)552 DEFAULT_MESSAGE_IMPL(VisionSharingChanged) 553 554 CMessageVisionSharingChanged(entity_id_t entity, player_id_t player, bool add) : 555 entity(entity), player(player), add(add) 556 { 557 } 558 559 entity_id_t entity; 560 player_id_t player; 561 bool add; 562 }; 563 564 /** 565 * Sent when an entity pings the minimap 566 */ 567 class CMessageMinimapPing : public CMessage 568 { 569 public: DEFAULT_MESSAGE_IMPL(MinimapPing)570 DEFAULT_MESSAGE_IMPL(MinimapPing) 571 572 CMessageMinimapPing() 573 { 574 } 575 }; 576 577 /** 578 * Cinematics events 579 */ 580 581 class CMessageCinemaPathEnded : public CMessage 582 { 583 public: DEFAULT_MESSAGE_IMPL(CinemaPathEnded)584 DEFAULT_MESSAGE_IMPL(CinemaPathEnded) 585 586 CMessageCinemaPathEnded(CStrW name) : 587 name(name) 588 { 589 } 590 591 CStrW name; 592 }; 593 594 class CMessageCinemaQueueEnded : public CMessage 595 { 596 public: 597 DEFAULT_MESSAGE_IMPL(CinemaQueueEnded) 598 }; 599 600 #endif // INCLUDED_MESSAGETYPES 601