Ticket #4046: messageChangesV0.patch

File messageChangesV0.patch, 52.0 KB (added by wraitii, 8 years ago)
  • binaries/data/mods/public/simulation/components/Formation.js

     
    334334        var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
    335335        cmpUnitAI.UpdateWorkOrders();
    336336        cmpUnitAI.SetFormationController(INVALID_ENTITY);
     337        Engine.UnsubscribeFromEntity(IID_Formation, this.entity, ent);
    337338    }
    338339
    339340    for each (var ent in this.formationMembersWithAura)
     
    379380            cmpAuras.RemoveFormationBonus(this.members);
    380381    }
    381382
     383    for (let ent of ents)
     384    {
     385        Engine.SubscribeToEntity(IID_Formation, this.entity, ent);
     386    }
     387
    382388    this.members = this.members.concat(ents);
    383389
    384390    for each (var ent in this.members)
     
    924930    }
    925931};
    926932
    927 Formation.prototype.OnGlobalOwnershipChanged = function(msg)
     933Formation.prototype.OnSubscribedOwnershipChanged = function(msg)
    928934{
    929935    // When an entity is captured or destroyed, it should no longer be
    930936    // controlled by this formation
     
    933939        this.RemoveMembers([msg.entity]);
    934940};
    935941
    936 Formation.prototype.OnGlobalEntityRenamed = function(msg)
     942Formation.prototype.OnSubscribedOwnershipChanged = function(msg)
    937943{
    938944    if (this.members.indexOf(msg.entity) != -1)
    939945    {
     946        this.UnsubscribeFromEntity(IID_Formation, this.entity, msg.entity)
     947        this.SubscribeToEntity(IID_Formation, this.entity, msg.newentity)
     948
    940949        this.offsets = undefined;
    941950        var cmpNewUnitAI = Engine.QueryInterface(msg.newentity, IID_UnitAI);
    942951        if (cmpNewUnitAI)
  • binaries/data/mods/public/simulation/components/GarrisonHolder.js

     
    278278    if (cmpAura && cmpAura.HasGarrisonAura())
    279279        cmpAura.ApplyGarrisonBonus(this.entity);
    280280
     281    Engine.SubscribeToEntity(IID_GarrisonHolder, this.entity, entity);
     282
    281283    Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [entity], "removed": [] });
    282284
    283285    var cmpUnitAI = Engine.QueryInterface(entity, IID_UnitAI);
     
    411413
    412414        if (this.Eject(entity, forced))
    413415        {
     416            Engine.UnsubscribeFromEntity(IID_GarrisonHolder, this.entity, entity);
    414417            var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
    415418            var cmpEntOwnership = Engine.QueryInterface(entity, IID_Ownership);
    416419            if (cmpOwnership && cmpEntOwnership && cmpOwnership.GetOwner() == cmpEntOwnership.GetOwner())
     
    585588    }
    586589};
    587590
     591
     592GarrisonHolder.prototype.OnOwnershipChanged = function(msg)
     593{
     594    var entities = [];
     595    for each (var entity in this.entities)
     596    {
     597        if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, entity))
     598            entities.push(entity);
     599    }
     600    if (entities.length)
     601        this.EjectOrKill(entities);
     602    return;
     603}
    588604/**
    589605 * If a garrisoned entity is captured, or about to be killed (so its owner
    590606 * changes to '-1'), remove it from the building so we only ever contain valid
    591607 * entities
    592608 */
    593 GarrisonHolder.prototype.OnGlobalOwnershipChanged = function(msg)
     609GarrisonHolder.prototype.OnSubscribedOwnershipChanged = function(msg)
    594610{
    595     // the ownership change may be on the garrisonholder
    596     if (this.entity == msg.entity)
    597     {
    598         var entities = [];
    599         for each (var entity in this.entities)
    600         {
    601             if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, entity))
    602                 entities.push(entity);
    603         }
    604         if (entities.length)
    605             this.EjectOrKill(entities);
    606         return;
    607     }
    608 
    609611    // or on some of its garrisoned units
    610612    var entityIndex = this.entities.indexOf(msg.entity);
    611613    if (entityIndex != -1)
     614        warn("no sanity check");
     615
     616    // If the entity is dead, remove it directly instead of ejecting the corpse
     617    var cmpHealth = Engine.QueryInterface(msg.entity, IID_Health);
     618    if (cmpHealth && cmpHealth.GetHitpoints() == 0)
    612619    {
    613         // If the entity is dead, remove it directly instead of ejecting the corpse
    614         var cmpHealth = Engine.QueryInterface(msg.entity, IID_Health);
    615         if (cmpHealth && cmpHealth.GetHitpoints() == 0)
    616         {
    617             this.entities.splice(entityIndex, 1);
    618             Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
    619             this.UpdateGarrisonFlag();
     620        this.entities.splice(entityIndex, 1);
     621        Engine.PostMessage(this.entity, MT_GarrisonedUnitsChanged, { "added" : [], "removed": [msg.entity] });
     622        this.UpdateGarrisonFlag();
    620623
    621             for (var pt of this.visibleGarrisonPoints)
    622                 if (pt.entity == msg.entity)
    623                     pt.entity = null;
    624         }
    625         else if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, msg.entity))
    626             this.EjectOrKill([msg.entity]);
     624        Engine.UnsubscribeFromEntity(IID_GarrisonHolder, this.entity, entity);
     625
     626        for (var pt of this.visibleGarrisonPoints)
     627            if (pt.entity == msg.entity)
     628                pt.entity = null;
    627629    }
     630    else if (msg.to == -1 || !IsOwnedByMutualAllyOfEntity(this.entity, msg.entity))
     631        this.EjectOrKill([msg.entity]);
    628632};
    629633
    630 /**
    631  * Update list of garrisoned entities if one gets renamed (e.g. by promotion)
    632  */
    633 GarrisonHolder.prototype.OnGlobalEntityRenamed = function(msg)
     634GarrisonHolder.prototype.OnEntityRenamed = function(msg)
    634635{
    635636    var entityIndex = this.entities.indexOf(msg.entity);
    636637    if (entityIndex != -1)
     
    646647        this.Eject(msg.entity);
    647648        this.Garrison(msg.newentity, vgpRenamed);
    648649    }
    649 
     650}
     651/**
     652 * Update list of garrisoned entities if one gets renamed (e.g. by promotion)
     653 */
     654GarrisonHolder.prototype.OnSubscribedEntityRenamed = function(msg)
     655{
    650656    if (!this.initGarrison)
    651657        return;
    652658
     
    659665    }
    660666    else
    661667    {
     668        Engine.UnsubscriptionFromEntity(IID_GarrisonHolder, this.entity, msg.entity);
     669        Engine.SubscriptionToEntity(IID_GarrisonHolder, this.entity, msg.newentity);
     670       
    662671        let entityIndex = this.initGarrison.indexOf(msg.entity);
    663672        if (entityIndex != -1)
    664673            this.initGarrison[entityIndex] = msg.newentity;
     
    681690 */
    682691GarrisonHolder.prototype.EjectOrKill = function(entities)
    683692{
     693    for (let entity of entities)
     694    {
     695        Engine.UnsubscribeFromEntity(IID_GarrisonHolder, this.entity, entity);
     696    }
    684697    var cmpPosition = Engine.QueryInterface(this.entity, IID_Position);
    685698    // Eject the units which can be ejected (if not in world, it generally means this holder
    686699    // is inside a holder which kills its entities, so do not eject)
  • binaries/data/mods/public/simulation/components/Guard.js

     
    3737{
    3838    if (this.entities.indexOf(ent) != -1)
    3939        return;
     40    Engine.SubscribeToEntity(IID_Guard, this.entity, ent);
    4041    this.entities.push(ent);
    4142};
    4243
     
    4344Guard.prototype.RemoveGuard = function(ent)
    4445{
    4546    var index = this.entities.indexOf(ent);
    46     if (index != -1)
    47         this.entities.splice(index, 1);
     47    if (index == -1)
     48        return;
     49    this.entities.splice(index, 1);
     50    Engine.UnsubscribeFromEntity(IID_Guard, this.entity, ent);
    4851};
    4952
    5053Guard.prototype.OnAttacked = function(msg)
     
    5659/**
    5760 * Update list of guarding/escorting entities if one gets renamed (e.g. by promotion)
    5861 */
    59 Guard.prototype.OnGlobalEntityRenamed = function(msg)
     62Guard.prototype.OnSubscribedEntityRenamed = function(msg)
    6063{
    6164    var entityIndex = this.entities.indexOf(msg.entity);
    62     if (entityIndex != -1)
    63         this.entities[entityIndex] = msg.newentity;
     65    if (entityIndex == -1)
     66        return;
     67   
     68    Engine.UnsubscribeFromEntity(IID_Guard, this.entity, msg.entity);
     69    Engine.SubscribeToEntity(IID_Guard, this.entity, msg.newentity);
     70    this.entities[entityIndex] = msg.newentity;
    6471};
    6572
    66 /**
    67  * If an entity is captured, or about to be killed (so its owner
    68  * changes to '-1'), update the guards list
    69  */
    70 Guard.prototype.OnGlobalOwnershipChanged = function(msg)
     73Guard.prototype.OnOwnershipChanged = function(msg)
    7174{
    7275    // the ownership change may be on the guarded
    7376    if (this.entity == msg.entity)
     
    8790        this.entities = entities;
    8891        return;
    8992    }
    90 
     93}
     94/**
     95 * If an entity is captured, or about to be killed (so its owner
     96 * changes to '-1'), update the guards list
     97 */
     98Guard.prototype.OnSubscribedOwnershipChanged = function(msg)
     99{
    91100    // or on some of its guards
    92101    if (this.entities.indexOf(msg.entity) != -1)
    93102    {
  • source/simulation2/components/CCmpAIManager.cpp

     
    939939        m_JustDeserialized = true;
    940940    }
    941941
    942     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     942    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    943943    {
    944944        switch (msg.GetType())
    945945        {
  • source/simulation2/components/CCmpCinemaManager.cpp

     
    174174        g_Game->GetView()->GetCinema()->SetEnabled(p_CinematicSimulationData->m_Enabled);
    175175    }
    176176
    177     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     177    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    178178    {
    179179        if (!g_Game || !g_Game->GetView())
    180180            return;
  • source/simulation2/components/CCmpDecay.cpp

     
    125125        Init(paramNode);
    126126    }
    127127
    128     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     128    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    129129    {
    130130        switch (msg.GetType())
    131131        {
  • source/simulation2/components/CCmpMinimap.cpp

     
    145145        SerializeCommon(deserialize);
    146146    }
    147147
    148     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     148    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    149149    {
    150150        switch (msg.GetType())
    151151        {
  • source/simulation2/components/CCmpMotionBall.cpp

     
    6666        deserialize.NumberFloat_Unbounded("speed z", m_SpeedZ);
    6767    }
    6868
    69     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     69    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    7070    {
    7171        switch (msg.GetType())
    7272        {
  • source/simulation2/components/CCmpObstruction.cpp

     
    297297        SerializeCommon(deserialize);
    298298    }
    299299
    300     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     300    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    301301    {
    302302        switch (msg.GetType())
    303303        {
  • source/simulation2/components/CCmpObstructionManager.cpp

     
    215215        m_UpdateInformations.dirtinessGrid = Grid<u8>(m_TerrainTiles*Pathfinding::NAVCELLS_PER_TILE, m_TerrainTiles*Pathfinding::NAVCELLS_PER_TILE);
    216216    }
    217217
    218     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     218    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    219219    {
    220220        switch (msg.GetType())
    221221        {
  • source/simulation2/components/CCmpOverlayRenderer.cpp

     
    7474        Init(paramNode);
    7575    }
    7676
    77     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     77    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    7878    {
    7979        switch (msg.GetType())
    8080        {
  • source/simulation2/components/CCmpOwnership.cpp

     
    6464        deserialize.NumberI32_Unbounded("owner", m_Owner);
    6565    }
    6666
    67     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     67    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    6868    {
    6969        switch (msg.GetType())
    7070        {
  • source/simulation2/components/CCmpParticleManager.cpp

     
    6060        Init(paramNode);
    6161    }
    6262
    63     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     63    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberTypelobal))
    6464    {
    6565        switch (msg.GetType())
    6666        {
  • source/simulation2/components/CCmpPathfinder.cpp

     
    153153    deserialize.NumberU16_Unbounded("same turn moves count", m_SameTurnMovesCount);
    154154}
    155155
    156 void CCmpPathfinder::HandleMessage(const CMessage& msg, bool UNUSED(global))
     156void CCmpPathfinder::HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    157157{
    158158    switch (msg.GetType())
    159159    {
  • source/simulation2/components/CCmpPathfinder_Common.h

     
    197197
    198198    virtual void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize);
    199199
    200     virtual void HandleMessage(const CMessage& msg, bool global);
     200    virtual void HandleMessage(const CMessage& msg, SubscriptionType subscriberType);
    201201
    202202    virtual pass_class_t GetPassabilityClass(const std::string& name);
    203203
  • source/simulation2/components/CCmpPosition.cpp

     
    753753        pos1.Y += GetConstructionProgressOffset(pos1);
    754754    }
    755755
    756     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     756    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    757757    {
    758758        switch (msg.GetType())
    759759        {
  • source/simulation2/components/CCmpProjectileManager.cpp

     
    8888        deserialize.NumberU32_Unbounded("next id", m_NextId);
    8989    }
    9090
    91     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     91    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    9292    {
    9393        switch (msg.GetType())
    9494        {
  • source/simulation2/components/CCmpRallyPointRenderer.cpp

     
    212212        Init(paramNode);
    213213    }
    214214
    215     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     215    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    216216    {
    217217        switch (msg.GetType())
    218218        {
  • source/simulation2/components/CCmpRangeManager.cpp

     
    447447        m_Deserializing = false;
    448448    }
    449449
    450     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     450    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    451451    {
    452452        switch (msg.GetType())
    453453        {
  • source/simulation2/components/CCmpSelectable.cpp

     
    165165        Init(paramNode);
    166166    }
    167167
    168     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global));
     168    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType));
    169169
    170170    virtual void SetSelectionHighlight(const CColor& color, bool selected)
    171171    {
     
    283283
    284284const double CCmpSelectable::FADE_DURATION = 0.3;
    285285
    286 void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
     286void CCmpSelectable::HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    287287{
    288288    switch (msg.GetType())
    289289    {
  • source/simulation2/components/CCmpTemplateManager.cpp

     
    7979                m_LatestTemplates[id] = mapEl.first;   
    8080    }
    8181
    82     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     82    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    8383    {
    8484        switch (msg.GetType())
    8585        {
  • source/simulation2/components/CCmpTerritoryManager.cpp

     
    162162        deserialize.Bool("trigger event", m_TriggerEvent);
    163163    }
    164164
    165     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     165    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    166166    {
    167167        switch (msg.GetType())
    168168        {
  • source/simulation2/components/CCmpTest.cpp

     
    7070        return m_x;
    7171    }
    7272
    73     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     73    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    7474    {
    7575        switch (msg.GetType())
    7676        {
     
    8484            m_x = 0;
    8585            break;
    8686        }
     87        debug_printf("x is  %i\n", m_x);
    8788    }
    8889};
    8990
     
    131132        return m_x;
    132133    }
    133134
    134     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     135    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    135136    {
    136137        switch (msg.GetType())
    137138        {
     
    192193        return m_x;
    193194    }
    194195
    195     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     196    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    196197    {
    197198        switch (msg.GetType())
    198199        {
  • source/simulation2/components/CCmpUnitMotion.cpp

     
    371371            m_PassClass = cmpPathfinder->GetPassabilityClass(m_PassClassName);
    372372    }
    373373
    374     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     374    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    375375    {
    376376        switch (msg.GetType())
    377377        {
  • source/simulation2/components/CCmpUnitRenderer.cpp

     
    156156        Init(paramNode);
    157157    }
    158158
    159     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     159    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    160160    {
    161161        switch (msg.GetType())
    162162        {
  • source/simulation2/components/CCmpVision.cpp

     
    7979        Init(paramNode);
    8080    }
    8181
    82     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     82    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    8383    {
    8484        switch (msg.GetType())
    8585        {
  • source/simulation2/components/CCmpVisualActor.cpp

     
    284284        }
    285285    }
    286286
    287     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     287    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    288288    {
    289289        // Quick exit for running in non-graphical mode
    290290        if (m_Unit == NULL)
  • source/simulation2/components/CCmpWaterManager.cpp

     
    6969        deserialize.NumberFixed_Unbounded("height", m_WaterHeight);
    7070    }
    7171
    72     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     72    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    7373    {
    7474        switch (msg.GetType())
    7575        {
  • source/simulation2/components/tests/test_Position.h

     
    8989
    9090        // Latch new position for interpolation
    9191        CMessageTurnStart msg;
    92         test.HandleMessage(cmp, msg, false);
     92        test.HandleMessage(cmp, msg, SubscriptionType::OWN);
    9393
    9494        // Move smoothly to new position
    9595        cmp->MoveTo(entity_pos_t::FromInt(400), entity_pos_t::FromInt(300));
  • source/simulation2/components/tests/test_RangeManager.h

     
    102102
    103103        cmp->SetBounds(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0), entity_pos_t::FromInt(512), entity_pos_t::FromInt(512), 512/TERRAIN_TILE_SIZE + 1);
    104104        cmp->Verify();
    105         { CMessageCreate msg(100); cmp->HandleMessage(msg, false); }
     105        { CMessageCreate msg(100); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    106106        cmp->Verify();
    107         { CMessageOwnershipChanged msg(100, -1, 1); cmp->HandleMessage(msg, false); }
     107        { CMessageOwnershipChanged msg(100, -1, 1); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    108108        cmp->Verify();
    109         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(247), entity_pos_t::FromDouble(257.95), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     109        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(247), entity_pos_t::FromDouble(257.95), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    110110        cmp->Verify();
    111         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(247), entity_pos_t::FromInt(253), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     111        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(247), entity_pos_t::FromInt(253), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    112112        cmp->Verify();
    113113
    114         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256), entity_pos_t::FromInt(256), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     114        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256), entity_pos_t::FromInt(256), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    115115        cmp->Verify();
    116116
    117         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256)+entity_pos_t::Epsilon(), entity_pos_t::FromInt(256), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     117        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256) + entity_pos_t::Epsilon(), entity_pos_t::FromInt(256), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    118118        cmp->Verify();
    119         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256)-entity_pos_t::Epsilon(), entity_pos_t::FromInt(256), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     119        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256) - entity_pos_t::Epsilon(), entity_pos_t::FromInt(256), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    120120        cmp->Verify();
    121         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256), entity_pos_t::FromInt(256)+entity_pos_t::Epsilon(), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     121        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256), entity_pos_t::FromInt(256) + entity_pos_t::Epsilon(), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    122122        cmp->Verify();
    123         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256), entity_pos_t::FromInt(256)-entity_pos_t::Epsilon(), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     123        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(256), entity_pos_t::FromInt(256) - entity_pos_t::Epsilon(), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    124124        cmp->Verify();
    125125
    126         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(383), entity_pos_t::FromInt(84), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     126        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(383), entity_pos_t::FromInt(84), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    127127        cmp->Verify();
    128         { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(348), entity_pos_t::FromInt(83), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     128        { CMessagePositionChanged msg(100, true, entity_pos_t::FromInt(348), entity_pos_t::FromInt(83), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    129129        cmp->Verify();
    130130
    131131        WELL512 rng;
     
    133133        {
    134134            double x = boost::uniform_real<>(0.0, 512.0)(rng);
    135135            double z = boost::uniform_real<>(0.0, 512.0)(rng);
    136             { CMessagePositionChanged msg(100, true, entity_pos_t::FromDouble(x), entity_pos_t::FromDouble(z), entity_angle_t::Zero()); cmp->HandleMessage(msg, false); }
     136            { CMessagePositionChanged msg(100, true, entity_pos_t::FromDouble(x), entity_pos_t::FromDouble(z), entity_angle_t::Zero()); cmp->HandleMessage(msg, SubscriptionType::OWN); }
    137137            cmp->Verify();
    138138        }
    139139    }
  • source/simulation2/docs/CCmpExample.cpp

     
    4646        // ...
    4747    }
    4848
    49     virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     49    virtual void HandleMessage(const CMessage& msg, SubscriptionType UNUSED(subscriberType))
    5050    {
    5151        // ...
    5252    }
  • source/simulation2/MessageTypes.h

     
    3434#define DEFAULT_MESSAGE_IMPL(name) \
    3535    virtual int GetType() const { return MT_##name; } \
    3636    virtual const char* GetScriptHandlerName() const { return "On" #name; } \
     37    virtual const char* GetScriptSubscribedHandlerName() const { return "OnSubscribed" #name; } \
    3738    virtual const char* GetScriptGlobalHandlerName() const { return "OnGlobal" #name; } \
    3839    virtual JS::Value ToJSVal(ScriptInterface& scriptInterface) const; \
    3940    static CMessage* FromJSVal(ScriptInterface&, JS::HandleValue val);
  • source/simulation2/scripting/ScriptComponent.cpp

     
    5353    m_ScriptInterface.CallFunctionVoid(m_Instance, "Deinit");
    5454}
    5555
    56 void CComponentTypeScript::HandleMessage(const CMessage& msg, bool global)
     56void CComponentTypeScript::HandleMessage(const CMessage& msg, SubscriptionType subscriberType)
    5757{
    5858    JSContext* cx = m_ScriptInterface.GetContext();
    5959    JSAutoRequest rq(cx);
    6060   
    61     const char* name = global ? msg.GetScriptGlobalHandlerName() : msg.GetScriptHandlerName();
     61    const char* name;
     62    switch (subscriberType)
     63    {
     64    case SubscriptionType::OWN:
     65        name = msg.GetScriptHandlerName();
     66        break;
     67    case SubscriptionType::SUBSCRIBED:
     68        name = msg.GetScriptSubscribedHandlerName();
     69        break;
     70    case SubscriptionType::GLOBAL:
     71        name = msg.GetScriptGlobalHandlerName();
     72        break;
     73    default:
     74        LOGERROR("Unknown message subscription type");
     75        return;
     76    }
    6277
    6378    JS::RootedValue msgVal(cx, msg.ToJSValCached(m_ScriptInterface));
    6479
  • source/simulation2/scripting/ScriptComponent.h

     
    4040
    4141    void Init(const CParamNode& paramNode, entity_id_t ent);
    4242    void Deinit();
    43     void HandleMessage(const CMessage& msg, bool global);
     43    void HandleMessage(const CMessage& msg, SubscriptionType subscriberType);
    4444
    4545    void Serialize(ISerializer& serialize);
    4646    void Deserialize(const CParamNode& paramNode, IDeserializer& deserialize, entity_id_t ent);
  • source/simulation2/system/Component.h

     
    7272    { \
    7373        m_Script.Deinit(); \
    7474    } \
    75     virtual void HandleMessage(const CMessage& msg, bool global) \
     75    virtual void HandleMessage(const CMessage& msg, SubscriptionType subscriberType) \
    7676    { \
    77         m_Script.HandleMessage(msg, global); \
     77        m_Script.HandleMessage(msg, subscriberType); \
    7878    } \
    7979    virtual void Serialize(ISerializer& serialize) \
    8080    { \
  • source/simulation2/system/ComponentManager.cpp

     
    4040    virtual int GetType() const { return mtid; }
    4141    virtual const char* GetScriptHandlerName() const { return handlerName.c_str(); }
    4242    virtual const char* GetScriptGlobalHandlerName() const { return globalHandlerName.c_str(); }
     43    virtual const char* GetScriptSubscribedHandlerName() const { return subscribedHandlerName.c_str(); }
    4344    virtual JS::Value ToJSVal(ScriptInterface& UNUSED(scriptInterface)) const { return msg.get(); }
    4445
    4546    CMessageScripted(ScriptInterface& scriptInterface, int mtid, const std::string& name, JS::HandleValue msg) :
    46         mtid(mtid), handlerName("On" + name), globalHandlerName("OnGlobal" + name), msg(scriptInterface.GetJSRuntime(), msg)
     47        mtid(mtid), handlerName("On" + name), subscribedHandlerName("OnSubscribed" + name),
     48        globalHandlerName("OnGlobal" + name), msg(scriptInterface.GetJSRuntime(), msg)
    4749    {
    4850    }
    4951
    5052    int mtid;
    5153    std::string handlerName;
     54    std::string subscribedHandlerName;
    5255    std::string globalHandlerName;
    5356    JS::PersistentRootedValue msg;
    5457};
     
    7982        m_ScriptInterface.RegisterFunction<IComponent*, int, int, CComponentManager::Script_QueryInterface> ("QueryInterface");
    8083        m_ScriptInterface.RegisterFunction<std::vector<int>, int, CComponentManager::Script_GetEntitiesWithInterface> ("GetEntitiesWithInterface");
    8184        m_ScriptInterface.RegisterFunction<std::vector<IComponent*>, int, CComponentManager::Script_GetComponentsWithInterface> ("GetComponentsWithInterface");
    82         m_ScriptInterface.RegisterFunction<void, int, int, JS::HandleValue, CComponentManager::Script_PostMessage> ("PostMessage");
     85        m_ScriptInterface.RegisterFunction<void, int, int, int, CComponentManager::Script_SubscribeToEntity>("SubscribeToEntity");
     86        m_ScriptInterface.RegisterFunction<void, int, int, int, CComponentManager::Script_UnsubscribeFromEntity>("UnsubscribeFromEntity");
     87        m_ScriptInterface.RegisterFunction<void, int, int, JS::HandleValue, CComponentManager::Script_PostMessage>("PostMessage");
    8388        m_ScriptInterface.RegisterFunction<void, int, JS::HandleValue, CComponentManager::Script_BroadcastMessage> ("BroadcastMessage");
    8489        m_ScriptInterface.RegisterFunction<int, std::string, CComponentManager::Script_AddEntity> ("AddEntity");
    8590        m_ScriptInterface.RegisterFunction<int, std::string, CComponentManager::Script_AddLocalEntity> ("AddLocalEntity");
     
    222227            if (ctit != types.end())
    223228                types.erase(ctit);
    224229        }
     230        for (it = componentManager->m_SubscriberMessageSubscriptions.begin(); it != componentManager->m_SubscriberMessageSubscriptions.end(); ++it)
     231        {
     232            std::vector<ComponentTypeId>& types = it->second;
     233            std::vector<ComponentTypeId>::iterator ctit = find(types.begin(), types.end(), cid);
     234            if (ctit != types.end())
     235                types.erase(ctit);
     236        }
    225237        for (it = componentManager->m_GlobalMessageSubscriptions.begin(); it != componentManager->m_GlobalMessageSubscriptions.end(); ++it)
    226238        {
    227239            std::vector<ComponentTypeId>& types = it->second;
     
    277289    {
    278290        std::string name = (*it).substr(2); // strip the "On" prefix
    279291
    280         // Handle "OnGlobalFoo" functions specially
    281         bool isGlobal = false;
    282         if (name.substr(0, 6) == "Global")
     292        SubscriptionType subscriptionType = SubscriptionType::OWN;
     293       
     294        if (name.substr(0, 10) == "Subscribed")
    283295        {
    284             isGlobal = true;
     296            subscriptionType = SubscriptionType::SUBSCRIBED;
     297            name = name.substr(10);
     298        }
     299        else if (name.substr(0, 6) == "Global")
     300        {
     301            subscriptionType = SubscriptionType::GLOBAL;
    285302            name = name.substr(6);
    286303        }
    287304
     
    292309            componentManager->m_ScriptInterface.ReportError(msg.c_str());
    293310            return;
    294311        }
    295 
    296         if (isGlobal)
     312       
     313        if (subscriptionType == SubscriptionType::SUBSCRIBED)
     314            componentManager->SubscribeOnSubscriptionToMessageType(mit->second);
     315        else if (subscriptionType == SubscriptionType::GLOBAL)
    297316            componentManager->SubscribeGloballyToMessageType(mit->second);
    298317        else
    299318            componentManager->SubscribeToMessageType(mit->second);
     
    439458    }
    440459}
    441460
     461void CComponentManager::Script_SubscribeToEntity(ScriptInterface::CxPrivate* pCxPrivate, int iid, int subscriber, int target)
     462{
     463    CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData);
     464
     465    const SEntityComponentCache* entcache = componentManager->LookupEntityHandle(subscriber).GetComponentCache();
     466
     467    if (iid >= entcache->numInterfaces || entcache->interfaces[iid] == NULL)
     468    {
     469        LOGWARNING("Interface %i of entity %i trying to subscribe to entity %i but there is no component for that interface",
     470            iid, subscriber, target);
     471        return;
     472    }
     473    IComponent* component = entcache->interfaces[iid];
     474
     475    componentManager->SubscribeToEntity(component, target);
     476}
     477
     478void CComponentManager::Script_UnsubscribeFromEntity(ScriptInterface::CxPrivate* pCxPrivate, int iid, int subscriber, int target)
     479{
     480    CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData);
     481
     482    const SEntityComponentCache* entcache = componentManager->LookupEntityHandle(subscriber).GetComponentCache();
     483
     484    if (iid >= entcache->numInterfaces || entcache->interfaces[iid] == NULL)
     485    {
     486        LOGWARNING("Interface %i of entity %i trying to unsubscribe from entity %i but there is no component for that interface",
     487            iid, subscriber, target);
     488        return;
     489    }
     490    IComponent* component = entcache->interfaces[iid];
     491
     492    componentManager->UnsubscribeFromEntity(component, target);
     493}
     494
    442495void CComponentManager::Script_PostMessage(ScriptInterface::CxPrivate* pCxPrivate, int ent, int mtid, JS::HandleValue data)
    443496{
    444497    CComponentManager* componentManager = static_cast<CComponentManager*> (pCxPrivate->pCBData);
     
    577630    std::sort(types.begin(), types.end()); // TODO: just sort once at the end of LoadComponents
    578631}
    579632
     633void CComponentManager::SubscribeOnSubscriptionToMessageType(MessageTypeId mtid)
     634{
     635    // TODO: verify mtid
     636    ENSURE(m_CurrentComponent != CID__Invalid);
     637    std::vector<ComponentTypeId>& types = m_SubscriberMessageSubscriptions[mtid];
     638    types.push_back(m_CurrentComponent);
     639    std::sort(types.begin(), types.end()); // TODO: just sort once at the end of LoadComponents
     640}
     641
    580642void CComponentManager::SubscribeGloballyToMessageType(MessageTypeId mtid)
    581643{
    582644    // TODO: verify mtid
     
    586648    std::sort(types.begin(), types.end()); // TODO: just sort once at the end of LoadComponents
    587649}
    588650
     651void CComponentManager::SubscribeToEntity(IComponent* subscriber, entity_id_t target)
     652{
     653    // [] operator calls the default constructor if it doesn't exist, resulting in an empty vector
     654    // which is what we want in this case.
     655    std::vector<IComponent*>& subscribers = m_SubscriptionsToEntities[target];
     656   
     657    if (ENTITY_IS_LOCAL(target))
     658    {
     659        LOGWARNING("Component type %i of entity %i is trying to subscribe to local entity %i",
     660            subscriber->GetComponentTypeId(), subscriber->GetEntityId(), target);
     661        return;
     662    }
     663
     664    // make sure we aren't already subscribed
     665    if (std::find(subscribers.begin(), subscribers.end(), subscriber) != subscribers.end())
     666    {
     667        LOGWARNING("Component type %i of entity %i trying to subscribe several times to messages of %i",
     668            subscriber->GetComponentTypeId(), subscriber->GetEntityId(), target);
     669        return;
     670    }
     671
     672    m_SubscriptionsToEntitiesByComponent[subscriber].insert(target);
     673    subscribers.push_back(subscriber);
     674}
     675void CComponentManager::UnsubscribeFromEntity(IComponent* subscriber, entity_id_t target)
     676{
     677    auto subscribers = m_SubscriptionsToEntities.find(target);
     678
     679    if (subscribers == m_SubscriptionsToEntities.end())
     680    {
     681        LOGWARNING("Component type %i of entity %i trying to unsubscribe from entity %i but hasnt subscribed",
     682            subscriber->GetComponentTypeId(), subscriber->GetEntityId(), target);
     683        return;
     684    }
     685
     686    std::vector<IComponent*>::iterator subit = std::find(subscribers->second.begin(), subscribers->second.end(), subscriber);
     687    if (subit == subscribers->second.end())
     688    {
     689        LOGWARNING("Component type %i of entity %i trying to unsubscribe from entity %i but hasnt subscribed - 2",
     690            subscriber->GetComponentTypeId(), subscriber->GetEntityId(), target);
     691        return;
     692    }
     693
     694    m_SubscriptionsToEntitiesByComponent[subscriber].erase(target);
     695
     696    std::swap(*subit, subscribers->second.back());
     697    subscribers->second.pop_back();
     698}
     699
    589700void CComponentManager::FlattenDynamicSubscriptions()
    590701{
    591702    std::map<MessageTypeId, CDynamicSubscription>::iterator it;
     
    9251036                std::map<entity_id_t, IComponent*>::iterator eit = iit->second.find(ent);
    9261037                if (eit != iit->second.end())
    9271038                {
     1039                    m_SubscriptionsToEntitiesByComponent.erase(eit->second);
    9281040                    eit->second->Deinit();
    9291041                    RemoveComponentDynamicSubscriptions(eit->second);
    9301042                    m_ComponentTypesById[iit->first].dealloc(eit->second);
     
    10011113{
    10021114    PROFILE2_IFSPIKE("Post Message", 0.0005);
    10031115    PROFILE2_ATTR("%s", msg.GetScriptHandlerName());
    1004     // Send the message to components of ent, that subscribed locally to this message
     1116
     1117    // check that some components care about this message
    10051118    std::map<MessageTypeId, std::vector<ComponentTypeId> >::const_iterator it;
    10061119    it = m_LocalMessageSubscriptions.find(msg.GetType());
    10071120    if (it != m_LocalMessageSubscriptions.end())
    10081121    {
    1009         std::vector<ComponentTypeId>::const_iterator ctit = it->second.begin();
    1010         for (; ctit != it->second.end(); ++ctit)
     1122        const SEntityComponentCache* entcache = LookupEntityHandle(ent).GetComponentCache();
     1123        for (const ComponentTypeId& ctype : it->second)
    10111124        {
    1012             // Find the component instances of this type (if any)
    1013             std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> >::const_iterator emap = m_ComponentsByTypeId.find(*ctit);
    1014             if (emap == m_ComponentsByTypeId.end())
    1015                 continue;
     1125            std::map<ComponentTypeId, ComponentType>::const_iterator ctit = m_ComponentTypesById.find(ctype);
    10161126
    1017             // Send the message to all of them
    1018             std::map<entity_id_t, IComponent*>::const_iterator eit = emap->second.find(ent);
    1019             if (eit != emap->second.end())
    1020                 eit->second->HandleMessage(msg, false);
     1127            // send the message to the target entity components of that type if they exist
     1128            if (entcache && entcache->interfaces[ctit->second.iid] != NULL)
     1129                entcache->interfaces[ctit->second.iid]->HandleMessage(msg, SubscriptionType::OWN);
    10211130        }
    10221131    }
    10231132
     1133    SendSubscribedMessage(ent, msg);
    10241134    SendGlobalMessage(ent, msg);
    10251135}
    10261136
     
    10421152            // Send the message to all of them
    10431153            std::map<entity_id_t, IComponent*>::const_iterator eit = emap->second.begin();
    10441154            for (; eit != emap->second.end(); ++eit)
    1045                 eit->second->HandleMessage(msg, false);
     1155            {
     1156                eit->second->HandleMessage(msg, SubscriptionType::OWN);
     1157            }
    10461158        }
    10471159    }
    10481160
     1161    SendSubscribedMessage(INVALID_ENTITY, msg);
    10491162    SendGlobalMessage(INVALID_ENTITY, msg);
    10501163}
    10511164
     1165void CComponentManager::SendSubscribedMessage(entity_id_t ent, const CMessage& msg)
     1166{
     1167    // find subscribers, ie components that listen to that entity
     1168    std::unordered_map<entity_id_t, std::vector<IComponent*> >::const_iterator subscribers;
     1169    subscribers = m_SubscriptionsToEntities.find(ent);
     1170    bool hasSubscribers = subscribers != m_SubscriptionsToEntities.end();
     1171    if (!hasSubscribers)
     1172        return;
     1173
     1174    // find component types that want this message
     1175    std::map<MessageTypeId, std::vector<ComponentTypeId> >::const_iterator sit;
     1176    sit = m_SubscriberMessageSubscriptions.find(msg.GetType());
     1177    if (sit == m_SubscriberMessageSubscriptions.end())
     1178        return;
     1179
     1180    // send it to them
     1181    for (const ComponentTypeId& ctype : sit->second)
     1182    {
     1183        for (IComponent* subscriber : subscribers->second)
     1184        {
     1185            if (subscriber->GetComponentTypeId() != ctype)
     1186                continue;
     1187            subscriber->HandleMessage(msg, SubscriptionType::SUBSCRIBED);
     1188        }
     1189    }
     1190}
     1191
    10521192void CComponentManager::SendGlobalMessage(entity_id_t ent, const CMessage& msg)
    10531193{
    10541194    PROFILE2_IFSPIKE("SendGlobalMessage", 0.001);
     
    10811221            // Send the message to all of them
    10821222            std::map<entity_id_t, IComponent*>::const_iterator eit = emap->second.begin();
    10831223            for (; eit != emap->second.end(); ++eit)
    1084                 eit->second->HandleMessage(msg, true);
     1224                eit->second->HandleMessage(msg, SubscriptionType::GLOBAL);
    10851225        }
    10861226    }
    10871227
     
    10921232        dit->second.Flatten();
    10931233        const std::vector<IComponent*>& dynamic = dit->second.GetComponents();
    10941234        for (size_t i = 0; i < dynamic.size(); i++)
    1095             dynamic[i]->HandleMessage(msg, false);
     1235            dynamic[i]->HandleMessage(msg, SubscriptionType::OWN);
    10961236    }
    10971237}
    10981238
  • source/simulation2/system/ComponentManager.h

     
    2828#include <boost/unordered_map.hpp>
    2929
    3030#include <map>
     31#include <unordered_map>
    3132
    3233class IComponent;
    3334class CParamNode;
     
    149150    void SubscribeToMessageType(MessageTypeId mtid);
    150151
    151152    /**
     153    * Subscribe the current component type to the given message type for subscribed entities
     154    * Each component's HandleMessage will be called on any BroadcastMessage of this message type,
     155    * or on any PostMessage of this type targeted at an entity this entity subscribes to.
     156    * Must only be called by a component type's ClassInit.
     157    */
     158    void SubscribeOnSubscriptionToMessageType(MessageTypeId mtid);
     159
     160    /**
    152161     * Subscribe the current component type to all messages of the given message type.
    153162     * Each component's HandleMessage will be called on any BroadcastMessage or PostMessage of this message type,
    154163     * regardless of the entity.
     
    157166    void SubscribeGloballyToMessageType(MessageTypeId mtid);
    158167
    159168    /**
     169    * Allow an entity to receive messages about an entity.
     170    * Called automatically by entities upon themselves on creation
     171    * Can be called at anytime by an entity interested in another entity.
     172    */
     173    void SubscribeToEntity(IComponent* subscriber, entity_id_t target);
     174
     175    void UnsubscribeFromEntity(IComponent* subscriber, entity_id_t target);
     176
     177    /**
    160178     * Subscribe the given component instance to all messages of the given message type.
    161179     * The component's HandleMessage will be called on any BroadcastMessage or PostMessage of
    162180     * this message type, regardless of the entity.
     
    319337    static IComponent* Script_QueryInterface(ScriptInterface::CxPrivate* pCxPrivate, int ent, int iid);
    320338    static std::vector<int> Script_GetEntitiesWithInterface(ScriptInterface::CxPrivate* pCxPrivate, int iid);
    321339    static std::vector<IComponent*> Script_GetComponentsWithInterface(ScriptInterface::CxPrivate* pCxPrivate, int iid);
     340    static void Script_SubscribeToEntity(ScriptInterface::CxPrivate* pCxPrivate, int iid, int subscriber, int target);
     341    static void Script_UnsubscribeFromEntity(ScriptInterface::CxPrivate* pCxPrivate, int iid, int subscriber, int target);
    322342    static void Script_PostMessage(ScriptInterface::CxPrivate* pCxPrivate, int ent, int mtid, JS::HandleValue data);
    323343    static void Script_BroadcastMessage(ScriptInterface::CxPrivate* pCxPrivate, int mtid, JS::HandleValue data);
    324344    static int Script_AddEntity(ScriptInterface::CxPrivate* pCxPrivate, const std::string& templateName);
     
    334354    static Status FindJSONFilesCallback(const VfsPath&, const CFileInfo&, const uintptr_t);
    335355
    336356    CMessage* ConstructMessage(int mtid, JS::HandleValue data);
     357    void SendSubscribedMessage(entity_id_t ent, const CMessage& msg);
    337358    void SendGlobalMessage(entity_id_t ent, const CMessage& msg);
    338359
    339360    void FlattenDynamicSubscriptions();
     
    357378    std::vector<boost::unordered_map<entity_id_t, IComponent*> > m_ComponentsByInterface; // indexed by InterfaceId
    358379    std::map<ComponentTypeId, std::map<entity_id_t, IComponent*> > m_ComponentsByTypeId;
    359380    std::map<MessageTypeId, std::vector<ComponentTypeId> > m_LocalMessageSubscriptions;
     381    std::map<MessageTypeId, std::vector<ComponentTypeId> > m_SubscriberMessageSubscriptions;
    360382    std::map<MessageTypeId, std::vector<ComponentTypeId> > m_GlobalMessageSubscriptions;
    361383    std::map<std::string, ComponentTypeId> m_ComponentTypeIdsByName;
    362384    std::map<std::string, MessageTypeId> m_MessageTypeIdsByName;
     
    363385    std::map<MessageTypeId, std::string> m_MessageTypeNamesById;
    364386    std::map<std::string, InterfaceId> m_InterfaceIdsByName;
    365387
     388    std::unordered_map<entity_id_t, std::vector<IComponent*> > m_SubscriptionsToEntities;
     389    std::map<IComponent*, std::set<entity_id_t> > m_SubscriptionsToEntitiesByComponent;
     390
    366391    std::map<MessageTypeId, CDynamicSubscription> m_DynamicMessageSubscriptionsNonsync;
    367392    std::map<IComponent*, std::set<MessageTypeId> > m_DynamicMessageSubscriptionsNonsyncByComponent;
    368393
  • source/simulation2/system/ComponentTest.h

     
    109109        m_ComponentManager.AddMockComponent(handle, iid, component);
    110110    }
    111111
    112     void HandleMessage(IComponent* cmp, const CMessage& msg, bool global)
     112    void HandleMessage(IComponent* cmp, const CMessage& msg, SubscriptionType subscriberType)
    113113    {
    114         cmp->HandleMessage(msg, global);
     114        cmp->HandleMessage(msg, subscriberType);
    115115    }
    116116
    117117    /**
  • source/simulation2/system/IComponent.cpp

     
    2929    return "<empty/>";
    3030}
    3131
    32 void IComponent::HandleMessage(const CMessage& UNUSED(msg), bool UNUSED(global))
     32void IComponent::HandleMessage(const CMessage& UNUSED(msg), SubscriptionType UNUSED(subscriberType))
    3333{
    3434}
    3535
  • source/simulation2/system/IComponent.h

     
    3030class ISerializer;
    3131class IDeserializer;
    3232
     33enum struct SubscriptionType
     34{
     35    OWN,
     36    SUBSCRIBED,
     37    GLOBAL
     38};
     39
    3340class IComponent
    3441{
    3542public:
     
    4047    virtual void Init(const CParamNode& paramNode) = 0;
    4148    virtual void Deinit() = 0;
    4249
    43     virtual void HandleMessage(const CMessage& msg, bool global);
     50    virtual void HandleMessage(const CMessage& msg, SubscriptionType subscriptionType);
    4451
    4552    CEntityHandle GetEntityHandle() const { return m_EntityHandle; }
    4653    void SetEntityHandle(CEntityHandle ent) { m_EntityHandle = ent; }
  • source/simulation2/system/Message.h

     
    3030    virtual ~CMessage() { }
    3131    virtual int GetType() const = 0;
    3232    virtual const char* GetScriptHandlerName() const = 0;
     33    virtual const char* GetScriptSubscribedHandlerName() const = 0;
    3334    virtual const char* GetScriptGlobalHandlerName() const = 0;
    3435    virtual JS::Value ToJSVal(ScriptInterface&) const = 0;
    3536    JS::Value ToJSValCached(ScriptInterface&) const;
  • source/simulation2/tests/test_ComponentManager.h

     
    173173        TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent4, IID_Test1))->GetX(), 11000);
    174174        TS_ASSERT_EQUALS(static_cast<ICmpTest2*> (man.QueryInterface(ent4, IID_Test2))->GetX(), 21000);
    175175
     176        debug_printf("sending mess\n");
     177
    176178        // Test_1A subscribed locally to msg1, nothing subscribed globally
    177179        man.PostMessage(ent1, msg1);
    178180        man.PostMessage(ent1, msg2);
     
    482484    {
    483485        CSimContext context;
    484486        CComponentManager man(context, g_ScriptRuntime);
     487
    485488        man.LoadComponentTypes();
    486489        TS_ASSERT(man.LoadScript(L"simulation/components/test-msg.js"));
    487490
     491        man.ResetState();
     492
    488493        entity_id_t ent1 = 1, ent2 = 2, ent3 = 3;
    489494        CEntityHandle hnd1 = man.AllocateEntityHandle(ent1);
    490495        CEntityHandle hnd2 = man.AllocateEntityHandle(ent2);
     
    497502        man.AddComponent(hnd2, CID_Test2A, noParam);
    498503        man.AddComponent(hnd3, man.LookupCID("TestScript1B"), noParam);
    499504
     505        debug_printf("ahajhtzrt");
     506
    500507        TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 100);
    501508        TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent2, IID_Test1))->GetX(), 100);
    502509        TS_ASSERT_EQUALS(static_cast<ICmpTest2*> (man.QueryInterface(ent2, IID_Test2))->GetX(), 21000);
     
    505512        // This GetX broadcasts messages
    506513        TS_ASSERT_EQUALS(static_cast<ICmpTest2*> (man.QueryInterface(ent1, IID_Test2))->GetX(), 200);
    507514
     515        debug_printf("before");
     516
    508517        TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent1, IID_Test1))->GetX(), 650);
    509518        TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent2, IID_Test1))->GetX(), 5150);
    510519        TS_ASSERT_EQUALS(static_cast<ICmpTest2*> (man.QueryInterface(ent2, IID_Test2))->GetX(), 26050);
    511520        TS_ASSERT_EQUALS(static_cast<ICmpTest1*> (man.QueryInterface(ent3, IID_Test1))->GetX(), 5650);
     521        debug_printf("ended");
     522
    512523    }
    513524
    514525    void test_script_template()