Ticket #599: fogging+optimization.patch

File fogging+optimization.patch, 43.4 KB (added by Itms, 10 years ago)
  • binaries/data/mods/public/simulation/components/BuildingAI.js

     
    335335
    336336    var cmpRangeManager = Engine.QueryInterface(SYSTEM_ENTITY, IID_RangeManager);
    337337
     338    // Entities that are hidden and miraged are considered visible
     339    var cmpFogging = Engine.QueryInterface(target, IID_Fogging);
     340    if (cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner()))
     341        return true;
     342
    338343    if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner(), false) == "hidden")
    339344        return false;
    340345
  • binaries/data/mods/public/simulation/components/BuildRestrictions.js

     
    102102        if (!cmpRangeManager || !cmpOwnership)
    103103            return result; // Fail
    104104
     105        var cmpFogging = Engine.QueryInterface(this.entity, IID_Fogging);
    105106        var explored = (cmpRangeManager.GetLosVisibility(this.entity, cmpOwnership.GetOwner(), true) != "hidden");
    106         if (!explored)
     107        if (!explored && !(cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner())))
    107108        {
    108109            result.message = markForTranslation("%(name)s cannot be built in unexplored area");
    109110            return result; // Fail
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    175175        "garrisonHolder": null,
    176176        "gate": null,
    177177        "guard": null,
     178        "mirage": null,
    178179        "pack": null,
    179180        "player": -1,
    180181        "position": null,
     
    303304        };
    304305    }
    305306
     307    var cmpMirage = Engine.QueryInterface(ent, IID_Mirage);
     308    if (cmpMirage)
     309    {
     310        ret.mirage = {
     311            "parent": cmpMirage.GetParent(),
     312        };
     313    }
     314
    306315    var cmpGate = Engine.QueryInterface(ent, IID_Gate);
    307316    if (cmpGate)
    308317    {
  • binaries/data/mods/public/simulation/components/interfaces/Messages.js

     
    1 /**
    2  * Broadcast message
    3  * sent when one entity is changed to other:
    4  * from Foundation component when building constuction is done
    5  * and from Promotion component when unit is promoted
    6  * Data: { entity: <integer>, newentity: <integer> }
    7  */
    8 Engine.RegisterMessageType("EntityRenamed");
    9 
    101Engine.RegisterMessageType("DiplomacyChanged");
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    38963896    if (cmpFormation)
    38973897        return true;
    38983898
     3899    var cmpMirage = Engine.QueryInterface(ent, IID_Mirage);
     3900    if (cmpMirage)
     3901        return true;
     3902
    38993903    var cmpHealth = Engine.QueryInterface(ent, IID_Health);
    39003904    if (!cmpHealth)
    39013905        return false;
     
    43864390    if (!cmpRangeManager)
    43874391        return false;
    43884392
     4393    // Entities that are hidden and miraged are considered visible
     4394    var cmpFogging = Engine.QueryInterface(target, IID_Fogging);
     4395    if (cmpFogging && cmpFogging.IsMiraged(cmpOwnership.GetOwner()))
     4396        return true;
     4397
    43894398    if (cmpRangeManager.GetLosVisibility(target, cmpOwnership.GetOwner(), false) == "hidden")
    43904399        return false;
    43914400
  • binaries/data/mods/public/simulation/templates/template_gaia.xml

     
    11<?xml version="1.0" encoding="utf-8"?>
    22<Entity parent="template_entity_quasi">
     3  <Fogging/>
    34  <Identity>
    45    <Civ>gaia</Civ>
    56    <GenericName>Gaia</GenericName>
  • binaries/data/mods/public/simulation/templates/template_structure.xml

     
    3737    <SinkRate>3.0</SinkRate>
    3838    <SinkAccel>9.8</SinkAccel>
    3939  </Decay>
     40  <Fogging/>
    4041  <Health>
    4142    <DeathType>corpse</DeathType>
    4243    <RegenRate>0</RegenRate>
  • source/ps/TemplateLoader.cpp

     
    8080        return true;
    8181    }
    8282
     83    // Handle special case "mirage|foo"
     84    if (templateName.find("mirage|") == 0)
     85    {
     86        // Load the base entity template, if it wasn't already loaded
     87        std::string baseName = templateName.substr(7);
     88        if (!LoadTemplateFile(baseName, depth+1))
     89        {
     90            LOGERROR(L"Failed to load entity template '%hs'", baseName.c_str());
     91            return false;
     92        }
     93        // Copy a subset to the requested template
     94        CopyMirageSubset(m_TemplateFileData[templateName], m_TemplateFileData[baseName]);
     95        return true;
     96    }
     97
    8398    // Handle special case "foundation|foo"
    8499    if (templateName.find("foundation|") == 0)
    85100    {
     
    380395    }
    381396}
    382397
     398void CTemplateLoader::CopyMirageSubset(CParamNode& out, const CParamNode& in)
     399{
     400    // Currently used for mirage entities replacing real ones in fog-of-war
     401
     402    std::set<std::string> permittedComponentTypes;
     403    permittedComponentTypes.insert("Footprint");
     404    permittedComponentTypes.insert("Health");
     405    permittedComponentTypes.insert("Minimap");
     406    permittedComponentTypes.insert("Ownership");
     407    permittedComponentTypes.insert("Position");
     408    permittedComponentTypes.insert("ResourceSupply");
     409    permittedComponentTypes.insert("Selectable");
     410    permittedComponentTypes.insert("VisualActor");
     411
     412    CParamNode::LoadXMLString(out, "<Entity/>");
     413    out.CopyFilteredChildrenOfChild(in, "Entity", permittedComponentTypes);
     414
     415    // Select a subset of identity data. We don't want to have, for example, a CC mirage
     416    // that has also the CC class and then prevents construction of other CCs
     417    std::set<std::string> identitySubset;
     418    identitySubset.insert("Civ");
     419    identitySubset.insert("GenericName");
     420    identitySubset.insert("SpecificName");
     421    identitySubset.insert("Tooltip");
     422    identitySubset.insert("History");
     423    identitySubset.insert("Icon");
     424    CParamNode identity;
     425    CParamNode::LoadXMLString(identity, "<Identity/>");
     426    identity.CopyFilteredChildrenOfChild(in.GetChild("Entity"), "Identity", identitySubset);
     427    CParamNode::LoadXMLString(out, ("<Entity>"+utf8_from_wstring(identity.ToXML())+"</Entity>").c_str());
     428
     429    // Set the entity as mirage entity
     430    CParamNode::LoadXMLString(out, "<Entity><Mirage/></Entity>");
     431    CParamNode::LoadXMLString(out, "<Entity><Vision><Range>0</Range><RetainInFog>true</RetainInFog><AlwaysVisible>false</AlwaysVisible></Vision></Entity>");
     432}
     433
    383434void CTemplateLoader::CopyFoundationSubset(CParamNode& out, const CParamNode& in)
    384435{
    385436    // TODO: this is all kind of yucky and hard-coded; it'd be nice to have a more generic
     
    394445    permittedComponentTypes.insert("Obstruction");
    395446    permittedComponentTypes.insert("Selectable");
    396447    permittedComponentTypes.insert("Footprint");
     448    permittedComponentTypes.insert("Fogging");
    397449    permittedComponentTypes.insert("Armour");
    398450    permittedComponentTypes.insert("Health");
    399451    permittedComponentTypes.insert("StatusBars");
  • source/ps/TemplateLoader.h

     
    7979    void CopyPreviewSubset(CParamNode& out, const CParamNode& in, bool corpse);
    8080
    8181    /**
     82     * Copy the components of an entity template necessary for a fogged "mirage"
     83     * entity (position, actor) into a new entity template
     84     */
     85    void CopyMirageSubset(CParamNode& out, const CParamNode& in);
     86
     87    /**
    8288     * Copy the components of an entity template necessary for a construction foundation
    8389     * (position, actor, armour, health, etc) into a new entity template
    8490     */
  • source/simulation2/components/CCmpFogging.cpp

     
     1/* Copyright (C) 2014 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#include "precompiled.h"
     19
     20#include "simulation2/system/Component.h"
     21#include "simulation2/MessageTypes.h"
     22#include "ICmpFogging.h"
     23
     24#include "lib/utf8.h"
     25
     26#include "ICmpOwnership.h"
     27#include "ICmpPlayerManager.h"
     28#include "ICmpRangeManager.h"
     29#include "ICmpTemplateManager.h"
     30#include "ICmpVisual.h"
     31
     32#include "ICmpMirage.h"
     33#include "ICmpPosition.h"
     34
     35class CCmpFogging : public ICmpFogging
     36{
     37public:
     38    static void ClassInit(CComponentManager& componentManager)
     39    {
     40        componentManager.SubscribeToMessageType(MT_VisibilityChanged);
     41        componentManager.SubscribeToMessageType(MT_Destroy);
     42    }
     43
     44    DEFAULT_COMPONENT_ALLOCATOR(Fogging)
     45
     46    static std::string GetSchema()
     47    {
     48        return "<a:help>Allows this entity to be replaced by mirages entities in the fog-of-war.</a:help>"
     49            "<empty/>";
     50    }
     51
     52    virtual void Init(const CParamNode& UNUSED(paramNode))
     53    {
     54        CmpPtr<ICmpPlayerManager> cmpPlayerManager(GetSystemEntity());
     55        size_t numPlayers = cmpPlayerManager->GetNumPlayers();
     56
     57        for (size_t i = 0; i < numPlayers; ++i)
     58        {
     59            m_Mirages.push_back(INVALID_ENTITY);
     60            m_Miraged.push_back(false);
     61        }
     62    }
     63
     64    virtual void Deinit()
     65    {
     66    }
     67
     68    template<typename S>
     69    void SerializeCommon(S& serialize)
     70    {
     71        SerializeVector<SerializeU32_Unbounded>()(serialize, "mirages", m_Mirages);
     72        SerializeVector<SerializeBool>()(serialize, "enable mirages", m_Miraged);
     73    }
     74
     75    virtual void Serialize(ISerializer& serialize)
     76    {
     77        SerializeCommon(serialize);
     78    }
     79
     80    virtual void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize)
     81    {
     82        SerializeCommon(deserialize);
     83    }
     84
     85    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     86    {
     87        switch (msg.GetType())
     88        {
     89        case MT_VisibilityChanged:
     90        {
     91            const CMessageVisibilityChanged& msgData = static_cast<const CMessageVisibilityChanged&> (msg);
     92            UpdateMirage(msgData.player);
     93            break;
     94        }
     95        case MT_Destroy:
     96            for (std::vector<entity_id_t>::iterator it = m_Mirages.begin(); it < m_Mirages.end(); ++it)
     97            {
     98                CmpPtr<ICmpMirage> cmpMirage(GetSimContext(), *it);
     99                if (cmpMirage)
     100                    cmpMirage->SetParent(INVALID_ENTITY);
     101            }
     102            break;
     103        }
     104    }
     105
     106    virtual void UpdateMirage(player_id_t player)
     107    {
     108        CComponentManager& componentManager = GetSimContext().GetComponentManager();
     109        CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
     110        CmpPtr<ICmpTemplateManager> cmpTemplateManager(GetSystemEntity());
     111       
     112        std::string templateName = "mirage|" + cmpTemplateManager->GetCurrentTemplateName(GetEntityId());
     113       
     114        ICmpRangeManager::ELosVisibility visibility = cmpRangeManager->GetLosVisibility(GetEntityHandle(), player);
     115
     116        // Nothing to update
     117        if (visibility == ICmpRangeManager::VIS_FOGGED)
     118            return;
     119           
     120        // Destroy mirages when we get back into LoS
     121        if (visibility == ICmpRangeManager::VIS_VISIBLE)
     122        {
     123            if (m_Mirages[player] != INVALID_ENTITY)
     124            {
     125                componentManager.DestroyComponentsSoon(m_Mirages[player]);
     126                m_Mirages[player] = INVALID_ENTITY;
     127            }
     128            return;
     129        }
     130           
     131        // Else, we are hidden and we should consider miraging
     132
     133        if (!m_Miraged[player] || m_Mirages[player] != INVALID_ENTITY)
     134            return;
     135               
     136        m_Mirages[player] = componentManager.AllocateNewEntity();
     137        componentManager.AddEntity(wstring_from_utf8(templateName), m_Mirages[player]);
     138
     139        CmpPtr<ICmpMirage> cmpMirage(GetSimContext(), m_Mirages[player]);
     140        if (!cmpMirage)
     141        {
     142            LOGERROR(L"Failed to load mirage entity for template %hs", templateName.c_str());
     143            m_Mirages[player] = INVALID_ENTITY;
     144            return;
     145        }
     146
     147        // Setup basic mirage properties
     148        cmpMirage->SetPlayer(player);
     149        cmpMirage->SetParent(GetEntityId());
     150
     151        // Copy cmpOwnership data
     152        CmpPtr<ICmpOwnership> cmpParentOwnership(GetEntityHandle());
     153        if (!cmpParentOwnership)
     154        {
     155            LOGERROR(L"Failed to access the ownership data of the fogged entity %hs", templateName.c_str());
     156            return;
     157        }
     158        CmpPtr<ICmpOwnership> cmpMirageOwnership(GetSimContext(), m_Mirages[player]);
     159        if (!cmpMirageOwnership)
     160        {
     161            LOGERROR(L"No valid Ownership in template %hs", templateName.c_str());
     162            return;
     163        }
     164        player_id_t parentOwner = cmpParentOwnership->GetOwner();
     165        cmpMirageOwnership->SetOwner(parentOwner);
     166
     167        // Copy cmpPosition data
     168        CmpPtr<ICmpPosition> cmpParentPosition(GetEntityHandle());
     169        if (!cmpParentPosition)
     170        {
     171            LOGERROR(L"Failed to access the position data of the fogged entity %hs", templateName.c_str());
     172            return;
     173        }
     174        CmpPtr<ICmpPosition> cmpMiragePosition(GetSimContext(), m_Mirages[player]);
     175        if (!cmpMiragePosition)
     176        {
     177            LOGERROR(L"No valid Position component in template %hs", templateName.c_str());
     178            return;
     179        }
     180        // The entity may not have been moved in-world yet, if we are e.g. placing a new building
     181        if (!cmpParentPosition->IsInWorld())
     182            return;
     183        CFixedVector3D pos = cmpParentPosition->GetPosition();
     184        cmpMiragePosition->JumpTo(pos.X, pos.Z);
     185        CFixedVector3D rot = cmpParentPosition->GetRotation();
     186        cmpMiragePosition->SetXZRotation(rot.X, rot.Z);
     187        cmpMiragePosition->SetYRotation(rot.Y);
     188
     189        // Copy cmpVisualActor data
     190        CmpPtr<ICmpVisual> cmpParentVisualActor(GetEntityHandle());
     191        if (!cmpParentVisualActor)
     192        {
     193            LOGERROR(L"Failed to access the visual actor of the fogged entity %hs", templateName.c_str());
     194            return;
     195        }
     196        CmpPtr<ICmpVisual> cmpMirageVisualActor(GetSimContext(), m_Mirages[player]);
     197        if (!cmpMirageVisualActor)
     198        {
     199            LOGERROR(L"No valid Visual actor in template %hs", templateName.c_str());
     200            return;
     201        }
     202        u32 parentSeed = cmpParentVisualActor->GetActorSeed();
     203        cmpMirageVisualActor->SetActorSeed(parentSeed);
     204    }
     205
     206    virtual bool IsMiraged(player_id_t player)
     207    {
     208        if (player > m_Miraged.size())
     209        {
     210            LOGERROR(L"Tried to query miraging info for invalid player");
     211            return false;
     212        }
     213       
     214        return m_Miraged[player];
     215    }
     216
     217    virtual void SetMiraged(player_id_t player, bool enable)
     218    {
     219        if (player > m_Miraged.size())
     220        {
     221            LOGERROR(L"Tried to enable/disable a mirage for invalid player");
     222            return;
     223        }
     224       
     225        m_Miraged[player] = enable;
     226    }
     227
     228private:
     229    /// Vector of mirages, one for each player
     230    std::vector<entity_id_t> m_Mirages;
     231
     232    /// For each player, remember if the entity must be mirage'd
     233    /// (i.e. has already been seen) or not.
     234    std::vector<bool> m_Miraged;
     235};
     236
     237REGISTER_COMPONENT_TYPE(Fogging)
  • source/simulation2/components/CCmpMirage.cpp

    Property changes on: source/simulation2/components/CCmpFogging.cpp
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
     1/* Copyright (C) 2014 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#include "precompiled.h"
     19
     20#include "simulation2/system/Component.h"
     21#include "simulation2/MessageTypes.h"
     22#include "ICmpMirage.h"
     23#include "ICmpRangeManager.h"
     24
     25class CCmpMirage : public ICmpMirage
     26{
     27public:
     28    static void ClassInit(CComponentManager& componentManager)
     29    {
     30        componentManager.SubscribeToMessageType(MT_VisibilityChanged);
     31        componentManager.SubscribeToMessageType(MT_Destroy);
     32    }
     33
     34    DEFAULT_COMPONENT_ALLOCATOR(Mirage)
     35
     36    static std::string GetSchema()
     37    {
     38        return "<a:help>Mirage entities replace real entities in the fog-of-war.</a:help>"
     39            "<empty/>";
     40    }
     41
     42    virtual void Init(const CParamNode& UNUSED(paramNode))
     43    {
     44    }
     45
     46    virtual void Deinit()
     47    {
     48    }
     49
     50    template<typename S>
     51    void SerializeCommon(S& serialize)
     52    {
     53        serialize.NumberI32_Unbounded("player", m_Player);
     54        serialize.NumberU32_Unbounded("parent", m_Parent);
     55    }
     56
     57    virtual void Serialize(ISerializer& serialize)
     58    {
     59        SerializeCommon(serialize);
     60    }
     61
     62    virtual void Deserialize(const CParamNode& UNUSED(paramNode), IDeserializer& deserialize)
     63    {
     64        SerializeCommon(deserialize);
     65    }
     66
     67    virtual void HandleMessage(const CMessage& msg, bool UNUSED(global))
     68    {
     69        switch (msg.GetType())
     70        {
     71        case MT_VisibilityChanged:
     72        {
     73            const CMessageVisibilityChanged& msgData = static_cast<const CMessageVisibilityChanged&> (msg);
     74            if (msgData.player == m_Player
     75                && msgData.newVisibility == ICmpRangeManager::VIS_VISIBLE
     76                && m_Parent == INVALID_ENTITY)
     77                GetSimContext().GetComponentManager().DestroyComponentsSoon(GetEntityId());
     78            break;
     79        }
     80        case MT_Destroy:
     81        {
     82            if (GetParent() == INVALID_ENTITY)
     83                break;
     84               
     85            CMessageEntityRenamed msg(GetEntityId(), GetParent());
     86            GetSimContext().GetComponentManager().BroadcastMessage(msg);
     87            break;
     88        }
     89        }
     90    }
     91
     92    virtual void SetPlayer(player_id_t player)
     93    {
     94        m_Player = player;
     95    }
     96
     97    virtual player_id_t GetPlayer()
     98    {
     99        return m_Player;
     100    }
     101
     102    virtual void SetParent(entity_id_t ent)
     103    {
     104        m_Parent = ent;
     105    }
     106
     107    virtual entity_id_t GetParent()
     108    {
     109        return m_Parent;
     110    }
     111
     112private:
     113    player_id_t m_Player;
     114    entity_id_t m_Parent;
     115};
     116
     117REGISTER_COMPONENT_TYPE(Mirage)
  • source/simulation2/components/CCmpRangeManager.cpp

    Property changes on: source/simulation2/components/CCmpMirage.cpp
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    2323#include "ICmpTerrain.h"
    2424#include "simulation2/system/EntityMap.h"
    2525#include "simulation2/MessageTypes.h"
     26#include "simulation2/components/ICmpFogging.h"
     27#include "simulation2/components/ICmpMirage.h"
     28#include "simulation2/components/ICmpOwnership.h"
    2629#include "simulation2/components/ICmpPosition.h"
    2730#include "simulation2/components/ICmpTerritoryManager.h"
    2831#include "simulation2/components/ICmpVision.h"
     
    3942#include "renderer/Scene.h"
    4043#include "lib/ps_stl.h"
    4144
    42 
     45#define LOS_TILES_RATIO 8
    4346#define DEBUG_RANGE_MANAGER_BOUNDS 0
    4447
    4548/**
     
    138141    EntityData() : retainInFog(0), owner(-1), inWorld(0), flags(1) { }
    139142    entity_pos_t x, z;
    140143    entity_pos_t visionRange;
     144    u32 visibilities; // 2-bit visibility, per player
    141145    u8 retainInFog; // boolean
    142146    i8 owner;
    143147    u8 inWorld; // boolean
     
    144148    u8 flags; // See GetEntityFlagMask
    145149};
    146150
    147 cassert(sizeof(EntityData) == 16);
     151cassert(sizeof(EntityData) == 20);
    148152
    149153/**
    150154 * Serialization helper template for Query
     
    197201        serialize.NumberFixed_Unbounded("z", value.z);
    198202        serialize.NumberFixed_Unbounded("vision", value.visionRange);
    199203        serialize.NumberU8("retain in fog", value.retainInFog, 0, 1);
     204        serialize.NumberU32_Unbounded("visibilities", value.visibilities);
    200205        serialize.NumberI8_Unbounded("owner", value.owner);
    201206        serialize.NumberU8("in world", value.inWorld, 0, 1);
    202207        serialize.NumberU8_Unbounded("flags", value.flags);
     
    283288    bool m_LosCircular;
    284289    i32 m_TerrainVerticesPerSide;
    285290    size_t m_TerritoriesDirtyID;
     291   
     292    // Cache for visibility tracking (not serialized)
     293    i32 m_LosTilesPerSide;
     294    bool* m_DirtyVisibility;
     295    std::vector<std::set<entity_id_t>> m_LosTiles;
     296    // List of entities that must be updated, regardless of the status of their tile
     297    std::vector<entity_id_t> m_ModifiedEntities;
    286298
    287299    // Counts of units seeing vertex, per vertex, per player (starting with player 0).
    288300    // Use u16 to avoid overflows when we have very large (but not infeasibly large) numbers
     
    332344        m_LosCircular = false;
    333345        m_TerrainVerticesPerSide = 0;
    334346
     347        m_DirtyVisibility = NULL;
     348
    335349        m_TerritoriesDirtyID = 0;
    336350    }
    337351
    338352    virtual void Deinit()
    339353    {
     354        delete[] m_DirtyVisibility;
    340355    }
    341356
    342357    template<typename S>
     
    355370        serialize.Bool("los circular", m_LosCircular);
    356371        serialize.NumberI32_Unbounded("terrain verts per side", m_TerrainVerticesPerSide);
    357372
    358         // We don't serialize m_Subdivision or m_LosPlayerCounts
     373        SerializeVector<SerializeU32_Unbounded>()(serialize, "modified entities", m_ModifiedEntities);
     374
     375        // We don't serialize m_Subdivision, m_LosPlayerCounts or m_LosTiles
    359376        // since they can be recomputed from the entity data when deserializing;
    360377        // m_LosState must be serialized since it depends on the history of exploration
    361378
     
    432449                    CFixedVector2D to(msgData.x, msgData.z);
    433450                    m_Subdivision.Move(ent, from, to);
    434451                    LosMove(it->second.owner, it->second.visionRange, from, to);
     452                    i32 oldLosTile = PosToLosTilesHelper(it->second.x, it->second.z);
     453                    i32 newLosTile = PosToLosTilesHelper(msgData.x, msgData.z);
     454                    if (oldLosTile != newLosTile)
     455                    {
     456                        RemoveFromTile(oldLosTile, ent);
     457                        AddToTile(newLosTile, ent);
     458                    }
    435459                }
    436460                else
    437461                {
     
    438462                    CFixedVector2D to(msgData.x, msgData.z);
    439463                    m_Subdivision.Add(ent, to);
    440464                    LosAdd(it->second.owner, it->second.visionRange, to);
     465                    AddToTile(PosToLosTilesHelper(msgData.x, msgData.z), ent);
    441466                }
    442467
    443468                it->second.inWorld = 1;
     
    451476                    CFixedVector2D from(it->second.x, it->second.z);
    452477                    m_Subdivision.Remove(ent, from);
    453478                    LosRemove(it->second.owner, it->second.visionRange, from);
     479                    RemoveFromTile(PosToLosTilesHelper(it->second.x, it->second.z), ent);
    454480                }
    455481
    456482                it->second.inWorld = 0;
     
    458484                it->second.z = entity_pos_t::Zero();
    459485            }
    460486
     487            m_ModifiedEntities.push_back(ent);
     488
    461489            break;
    462490        }
    463491        case MT_OwnershipChanged:
     
    495523                break;
    496524
    497525            if (it->second.inWorld)
     526            {
    498527                m_Subdivision.Remove(ent, CFixedVector2D(it->second.x, it->second.z));
     528                RemoveFromTile(PosToLosTilesHelper(it->second.x, it->second.z), ent);
     529            }
    499530
    500531            // This will be called after Ownership's OnDestroy, so ownership will be set
    501532            // to -1 already and we don't have to do a LosRemove here
     
    539570        case MT_Update:
    540571        {
    541572            m_DebugOverlayDirty = true;
     573            UpdateVisibilityData();
    542574            UpdateTerritoriesLos();
    543575            ExecuteActiveQueries();
    544576            break;
     
    559591        m_WorldX1 = x1;
    560592        m_WorldZ1 = z1;
    561593        m_TerrainVerticesPerSide = (i32)vertices;
     594       
     595        m_LosTilesPerSide = (m_TerrainVerticesPerSide - 1)/LOS_TILES_RATIO;
    562596
    563597        ResetDerivedData(false);
    564598    }
     
    639673        }
    640674        m_LosStateRevealed.clear();
    641675        m_LosStateRevealed.resize(m_TerrainVerticesPerSide*m_TerrainVerticesPerSide);
     676       
     677        delete[] m_DirtyVisibility;
     678        m_DirtyVisibility = new bool[m_LosTilesPerSide*m_LosTilesPerSide]();
     679        m_LosTiles.clear();
     680        m_LosTiles.resize(m_LosTilesPerSide*m_LosTilesPerSide);
    642681
    643682        for (EntityMap<EntityData>::const_iterator it = m_EntityData.begin(); it != m_EntityData.end(); ++it)
    644683        {
    645684            if (it->second.inWorld)
     685            {
    646686                LosAdd(it->second.owner, it->second.visionRange, CFixedVector2D(it->second.x, it->second.z));
     687                AddToTile(PosToLosTilesHelper(it->second.x, it->second.z), it->first);
     688            }
    647689        }
    648690
    649691        m_TotalInworldVertices = 0;
     
    13641406        CLosQuerier los(GetSharedLosMask(player), m_LosState, m_TerrainVerticesPerSide);
    13651407
    13661408        if (los.IsVisible(i, j))
     1409        {
     1410            // If we see an entity, we should mirage it as soon as it falls into fog-of-war
     1411            CmpPtr<ICmpFogging> cmpFogging(ent);
     1412            if (cmpFogging)
     1413                cmpFogging->SetMiraged(player, true);
     1414           
    13671415            return VIS_VISIBLE;
     1416        }
    13681417
    13691418        // Fogged if the 'retain in fog' flag is set, and in a non-visible explored region
    13701419        if (los.IsExplored(i, j))
     
    13711420        {
    13721421            CmpPtr<ICmpVision> cmpVision(ent);
    13731422            if (forceRetainInFog || (cmpVision && cmpVision->GetRetainInFog()))
    1374                 return VIS_FOGGED;
     1423            {
     1424                // Mirage entities are visible for one specific player
     1425                CmpPtr<ICmpMirage> cmpMirage(ent);
     1426                if (cmpMirage)
     1427                {
     1428                    if (cmpMirage->GetPlayer() == player)
     1429                        return VIS_FOGGED;
     1430                    else
     1431                        return VIS_HIDDEN;
     1432                }
     1433
     1434                // Normal entities should be visible only for their owner
     1435                CmpPtr<ICmpOwnership> cmpOwnership(ent);
     1436                if (cmpOwnership)
     1437                {
     1438                    if (cmpOwnership->GetOwner() == player)
     1439                        return VIS_FOGGED;
     1440                    else
     1441                        return VIS_HIDDEN;
     1442                }
     1443               
     1444                return VIS_VISIBLE;
     1445            }
    13751446        }
    13761447
    13771448        // Otherwise not visible
     
    13841455        return GetLosVisibility(handle, player, forceRetainInFog);
    13851456    }
    13861457
     1458    i32 PosToLosTilesHelper(entity_pos_t x, entity_pos_t z)
     1459    {
     1460        i32 i = Clamp(
     1461            (x/(entity_pos_t::FromInt(TERRAIN_TILE_SIZE * LOS_TILES_RATIO))).ToInt_RoundToZero(),
     1462            0,
     1463            m_LosTilesPerSide - 1);
     1464        i32 j = Clamp(
     1465            (z/(entity_pos_t::FromInt(TERRAIN_TILE_SIZE * LOS_TILES_RATIO))).ToInt_RoundToZero(),
     1466            0,
     1467            m_LosTilesPerSide - 1);
     1468        return j*m_LosTilesPerSide + i;
     1469    }
    13871470
     1471    void AddToTile(i32 tile, entity_id_t ent)
     1472    {
     1473        m_LosTiles[tile].insert(ent);
     1474    }
     1475
     1476    void RemoveFromTile(i32 tile, entity_id_t ent)
     1477    {
     1478        for (std::set<entity_id_t>::iterator tileIt = m_LosTiles[tile].begin();
     1479            tileIt != m_LosTiles[tile].end();
     1480            ++tileIt)
     1481        {
     1482            if (*tileIt == ent)
     1483            {
     1484                m_LosTiles[tile].erase(tileIt);
     1485                return;
     1486            }
     1487        }
     1488    }
     1489
     1490    void UpdateVisibilityData()
     1491    {
     1492        PROFILE("UpdateVisibilityData");
     1493       
     1494        for (i32 n = 0; n < m_LosTilesPerSide*m_LosTilesPerSide; ++n)
     1495        {
     1496            if (m_DirtyVisibility[n])
     1497            {
     1498                for (std::set<entity_id_t>::iterator it = m_LosTiles[n].begin();
     1499                    it != m_LosTiles[n].end();
     1500                    ++it)
     1501                {
     1502                    UpdateVisibility(*it);
     1503                }
     1504                m_DirtyVisibility[n] = false;
     1505            }
     1506        }
     1507
     1508        for (std::vector<entity_id_t>::iterator it = m_ModifiedEntities.begin(); it != m_ModifiedEntities.end(); ++it)
     1509        {
     1510            UpdateVisibility(*it);
     1511        }
     1512        m_ModifiedEntities.clear();
     1513    }
     1514
     1515    void UpdateVisibility(entity_id_t ent)
     1516    {
     1517        EntityMap<EntityData>::iterator itEnts = m_EntityData.find(ent);
     1518        if (itEnts == m_EntityData.end())
     1519            return;
     1520       
     1521        for (player_id_t player = 1; player <= MAX_LOS_PLAYER_ID; ++player)
     1522        {
     1523            u8 oldVis = (itEnts->second.visibilities >> (2*player)) & 0x3;
     1524            u8 newVis = GetLosVisibility(itEnts->first, player, false);
     1525
     1526            if (oldVis != newVis)
     1527            {
     1528                CMessageVisibilityChanged msg(player, ent, oldVis, newVis);
     1529                GetSimContext().GetComponentManager().PostMessage(ent, msg);
     1530                itEnts->second.visibilities = (itEnts->second.visibilities & ~(0x3 << 2*player)) | (newVis << 2*player);
     1531            }
     1532        }
     1533    }
     1534
    13881535    virtual void SetLosRevealAll(player_id_t player, bool enabled)
    13891536    {
    13901537        if (player == -1)
     
    15321679                    explored += !(m_LosState[idx] & (LOS_EXPLORED << (2*(owner-1))));
    15331680                    m_LosState[idx] |= ((LOS_VISIBLE | LOS_EXPLORED) << (2*(owner-1)));
    15341681                }
     1682                m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = true;
    15351683            }
    15361684
    15371685            ASSERT(counts[idx] < 65535);
     
    15591707            {
    15601708                // (If LosIsOffWorld then this is a no-op, so don't bother doing the check)
    15611709                m_LosState[idx] &= ~(LOS_VISIBLE << (2*(owner-1)));
     1710
     1711                i32 i = i0 + idx - idx0;
     1712                m_DirtyVisibility[(j/LOS_TILES_RATIO)*m_LosTilesPerSide + i/LOS_TILES_RATIO] = true;
    15621713            }
    15631714        }
    15641715    }
  • source/simulation2/components/CCmpUnitRenderer.cpp

     
    391391        CmpPtr<ICmpVision> cmpVision(unit.entity);
    392392        if (cmpVision && cmpVision->GetAlwaysVisible())
    393393            unit.visibility = ICmpRangeManager::VIS_VISIBLE;
     394
     395        // Uncomment the following two lines to prevent the models from popping into existence
     396        // near the LOS boundary. Is rather resource intensive.
     397        //else if (cmpVision && cmpVision->GetRetainInFog())
     398        //  unit.visibility = ICmpRangeManager::VIS_VISIBLE;
     399
    394400        else
    395401        {
    396402            CmpPtr<ICmpRangeManager> cmpRangeManager(GetSystemEntity());
    397             // Uncomment the following lines to prevent the models from popping into existence
    398             // near the LOS boundary. Is rather resource intensive.
    399             //if (cmpVision->GetRetainInFog())
    400             //  unit.visibility = ICmpRangeManager::VIS_VISIBLE;
    401             //else
    402                 unit.visibility = cmpRangeManager->GetLosVisibility(unit.entity,
    403                     GetSimContext().GetCurrentDisplayedPlayer());
     403            unit.visibility = cmpRangeManager->GetLosVisibility(unit.entity,
     404                GetSimContext().GetCurrentDisplayedPlayer());
    404405        }
    405406    }
    406407    else
  • source/simulation2/components/CCmpVisualActor.cpp

     
    532532    void ReloadActor();
    533533
    534534    void Update(fixed turnLength);
    535     void UpdateVisibility();
    536535};
    537536
    538537REGISTER_COMPONENT_TYPE(VisualActor)
  • source/simulation2/components/ICmpFogging.cpp

     
     1/* Copyright (C) 2014 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#include "precompiled.h"
     19
     20#include "ICmpFogging.h"
     21
     22#include "simulation2/system/InterfaceScripted.h"
     23
     24BEGIN_INTERFACE_WRAPPER(Fogging)
     25DEFINE_INTERFACE_METHOD_1("UpdateMirage", void, ICmpFogging, UpdateMirage, player_id_t)
     26DEFINE_INTERFACE_METHOD_1("IsMiraged", bool, ICmpFogging, IsMiraged, player_id_t)
     27DEFINE_INTERFACE_METHOD_2("SetMiraged", void, ICmpFogging, SetMiraged, player_id_t, bool)
     28END_INTERFACE_WRAPPER(Fogging)
  • source/simulation2/components/ICmpFogging.h

    Property changes on: source/simulation2/components/ICmpFogging.cpp
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
     1/* Copyright (C) 2014 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_ICMPFOGGING
     19#define INCLUDED_ICMPFOGGING
     20
     21#include "simulation2/system/Interface.h"
     22
     23#include "simulation2/helpers/Player.h"
     24
     25
     26/**
     27 * Handles the fogging of out-of-sight enemy entities, by creating mirage
     28 * entities.
     29 * This allows hiding changes, especially destruction status or health.
     30 */
     31class ICmpFogging : public IComponent
     32{
     33public:
     34    virtual void UpdateMirage(player_id_t player) = 0;
     35    virtual bool IsMiraged(player_id_t player) = 0;
     36    virtual void SetMiraged(player_id_t player, bool enable) = 0;
     37    DECLARE_INTERFACE_TYPE(Fogging)
     38};
     39
     40#endif // INCLUDED_ICMPFOGGING
  • source/simulation2/components/ICmpMirage.cpp

    Property changes on: source/simulation2/components/ICmpFogging.h
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
     1/* Copyright (C) 2014 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#include "precompiled.h"
     19
     20#include "ICmpMirage.h"
     21
     22#include "simulation2/system/InterfaceScripted.h"
     23
     24BEGIN_INTERFACE_WRAPPER(Mirage)
     25DEFINE_INTERFACE_METHOD_1("SetPlayer", void, ICmpMirage, SetPlayer, player_id_t)
     26DEFINE_INTERFACE_METHOD_0("GetPlayer", player_id_t, ICmpMirage, GetPlayer)
     27DEFINE_INTERFACE_METHOD_1("SetParent", void, ICmpMirage, SetParent, entity_id_t)
     28DEFINE_INTERFACE_METHOD_0("GetParent", entity_id_t, ICmpMirage, GetParent)
     29END_INTERFACE_WRAPPER(Mirage)
  • source/simulation2/components/ICmpMirage.h

    Property changes on: source/simulation2/components/ICmpMirage.cpp
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
     1/* Copyright (C) 2014 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_ICMPMIRAGE
     19#define INCLUDED_ICMPMIRAGE
     20
     21#include "simulation2/system/Interface.h"
     22
     23#include "simulation2/helpers/Player.h"
     24
     25/**
     26 * Component allowing mirage entities to communicate with their parent entity.
     27 * See ICmpFogging.
     28 */
     29class ICmpMirage : public IComponent
     30{
     31public:
     32    virtual void SetPlayer(player_id_t player) = 0;
     33    virtual player_id_t GetPlayer() = 0;
     34    virtual void SetParent(entity_id_t ent) = 0;
     35    virtual entity_id_t GetParent() = 0;
     36    DECLARE_INTERFACE_TYPE(Mirage)
     37};
     38
     39#endif // INCLUDED_ICMPMIRAGE
  • source/simulation2/components/ICmpRangeManager.cpp

    Property changes on: source/simulation2/components/ICmpMirage.h
    ___________________________________________________________________
    Added: svn:eol-style
    ## -0,0 +1 ##
    +native
    \ No newline at end of property
     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
  • source/simulation2/components/ICmpRangeManager.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    216216
    217217    enum ELosVisibility
    218218    {
    219         VIS_HIDDEN,
    220         VIS_FOGGED,
    221         VIS_VISIBLE
     219        VIS_HIDDEN = 0,
     220        VIS_FOGGED = 1,
     221        VIS_VISIBLE = 2
    222222    };
    223223
    224224    /**
  • source/simulation2/MessageTypes.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    241241    entity_id_t entity;
    242242};
    243243
     244/**
     245 * This is sent when one entity is changed to other: from Foundation component when building
     246 * constuction is done, from Promotion component, from Fogging component etc.
     247 */
     248class CMessageEntityRenamed : public CMessage
     249{
     250public:
     251    DEFAULT_MESSAGE_IMPL(EntityRenamed)
     252
     253    CMessageEntityRenamed(entity_id_t entity, entity_id_t newentity) :
     254        entity(entity), newentity(newentity)
     255    {
     256    }
     257
     258    entity_id_t entity;
     259    entity_id_t newentity;
     260};
     261
    244262class CMessageOwnershipChanged : public CMessage
    245263{
    246264public:
     
    362380};
    363381
    364382/**
     383 * Sent, at most once per turn, when the visibility of an entity changed
     384 */
     385class CMessageVisibilityChanged : public CMessage
     386{
     387public:
     388    DEFAULT_MESSAGE_IMPL(VisibilityChanged)
     389
     390    CMessageVisibilityChanged(player_id_t player, entity_id_t ent, int oldVisibility, int newVisibility) :
     391        player(player), ent(ent), oldVisibility(oldVisibility), newVisibility(newVisibility)
     392    {
     393    }
     394
     395    player_id_t player;
     396    entity_id_t ent;
     397    int oldVisibility;
     398    int newVisibility;
     399};
     400
     401/**
    365402 * Sent when ObstructionManager's view of the shape of the world has changed
    366403 * (changing the TILE_OUTOFBOUNDS tiles returned by Rasterise).
    367404 */
  • source/simulation2/scripting/MessageTypeConversions.cpp

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    194194
    195195////////////////////////////////
    196196
     197jsval CMessageEntityRenamed::ToJSVal(ScriptInterface& scriptInterface) const
     198{
     199    TOJSVAL_SETUP();
     200    SET_MSG_PROPERTY(entity);
     201    SET_MSG_PROPERTY(newentity);
     202    return OBJECT_TO_JSVAL(obj);
     203}
     204
     205CMessage* CMessageEntityRenamed::FromJSVal(ScriptInterface& scriptInterface, jsval val)
     206{
     207    FROMJSVAL_SETUP();
     208    GET_MSG_PROPERTY(entity_id_t, entity);
     209    GET_MSG_PROPERTY(entity_id_t, newentity);
     210    return new CMessageEntityRenamed(entity, newentity);
     211}
     212
     213////////////////////////////////
     214
    197215jsval CMessageOwnershipChanged::ToJSVal(ScriptInterface& scriptInterface) const
    198216{
    199217    TOJSVAL_SETUP();
     
    310328
    311329////////////////////////////////
    312330
     331jsval CMessageVisibilityChanged::ToJSVal(ScriptInterface& scriptInterface) const
     332{
     333    TOJSVAL_SETUP();
     334    SET_MSG_PROPERTY(player);
     335    SET_MSG_PROPERTY(ent);
     336    SET_MSG_PROPERTY(oldVisibility);
     337    SET_MSG_PROPERTY(newVisibility);
     338    return OBJECT_TO_JSVAL(obj);
     339}
     340
     341CMessage* CMessageVisibilityChanged::FromJSVal(ScriptInterface& scriptInterface, jsval val)
     342{
     343    FROMJSVAL_SETUP();
     344    GET_MSG_PROPERTY(player_id_t, player);
     345    GET_MSG_PROPERTY(entity_id_t, ent);
     346    GET_MSG_PROPERTY(int, oldVisibility);
     347    GET_MSG_PROPERTY(int, newVisibility);
     348    return new CMessageVisibilityChanged(player, ent, oldVisibility, newVisibility);
     349}
     350
     351////////////////////////////////
     352
    313353jsval CMessageWaterChanged::ToJSVal(ScriptInterface& scriptInterface) const
    314354{
    315355    TOJSVAL_SETUP();
  • source/simulation2/TypeList.h

     
    1 /* Copyright (C) 2013 Wildfire Games.
     1/* Copyright (C) 2014 Wildfire Games.
    22 * This file is part of 0 A.D.
    33 *
    44 * 0 A.D. is free software: you can redistribute it and/or modify
     
    4141MESSAGE(Deserialized) // non-deterministic (use with caution)
    4242MESSAGE(Create)
    4343MESSAGE(Destroy)
     44MESSAGE(EntityRenamed)
    4445MESSAGE(OwnershipChanged)
    4546MESSAGE(PositionChanged)
    4647MESSAGE(InterpolatedPositionChanged)
     
    4849MESSAGE(MotionChanged)
    4950MESSAGE(RangeUpdate)
    5051MESSAGE(TerrainChanged)
     52MESSAGE(VisibilityChanged)
    5153MESSAGE(WaterChanged)
    5254MESSAGE(ObstructionMapShapeChanged)
    5355MESSAGE(TerritoriesChanged)
     
    8082INTERFACE(Decay)
    8183COMPONENT(Decay)
    8284
     85INTERFACE(Fogging)
     86COMPONENT(Fogging)
     87
    8388// Note: The VisualActor component relies on this component being initialized before itself, in order to support using
    8489// an entity's footprint shape for the selection boxes. This dependency is not strictly necessary, but it does avoid
    8590// some extra plumbing code to set up on-demand initialization. If you find yourself forced to break this dependency,
     
    96101INTERFACE(Minimap)
    97102COMPONENT(Minimap)
    98103
     104INTERFACE(Mirage)
     105COMPONENT(Mirage)
     106
    99107INTERFACE(Motion)
    100108COMPONENT(MotionBall)
    101109COMPONENT(MotionScripted)