BVB Source Codes

CRYENGINE Show SerializeWriterXMLCPBin.cpp Source code

Return Download CRYENGINE: download SerializeWriterXMLCPBin.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. #include "StdAfx.h"
  4. #include "SerializeWriterXMLCPBin.h"
  5. #include <CryEntitySystem/IEntitySystem.h>
  6.  
  7. static const size_t MAX_NODE_STACK_DEP = 40;
  8.  
  9. #define TAG_SCRIPT_VALUE "v"
  10. #define TAG_SCRIPT_TYPE  "t"
  11. #define TAG_SCRIPT_NAME  "n"
  12.  
  13. CSerializeWriterXMLCPBin::CSerializeWriterXMLCPBin(const XMLCPB::CNodeLiveWriterRef& nodeRef, XMLCPB::CWriterInterface& binWriter)
  14.         : m_binWriter(binWriter)
  15. {
  16.         assert(nodeRef.IsValid());
  17.         m_curTime = gEnv->pTimer->GetFrameStartTime();
  18.         m_nodeStack.reserve(MAX_NODE_STACK_DEP);
  19.         m_nodeStack.push_back(nodeRef);
  20.         m_luaSaveStack.reserve(10);
  21. }
  22.  
  23. //////////////////////////////////////////////////////////////////////////
  24. CSerializeWriterXMLCPBin::~CSerializeWriterXMLCPBin()
  25. {
  26.         if (m_nodeStack.size() != 1)
  27.         {
  28.                 CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!BeginGroup/EndGroup mismatch in SaveGame");
  29.         }
  30. }
  31.  
  32. //////////////////////////////////////////////////////////////////////////
  33. bool CSerializeWriterXMLCPBin::Value(const char* name, CTimeValue value)
  34. {
  35.         if (value == CTimeValue(0.0f))
  36.                 AddValue(name, "zero");
  37.         else
  38.                 AddValue(name, (value - m_curTime).GetSeconds());
  39.         return true;
  40. }
  41.  
  42. bool CSerializeWriterXMLCPBin::Value(const char* name, ScriptAnyValue& value)
  43. {
  44.         m_luaSaveStack.resize(0);
  45.         ScriptValue(CurNode(), NULL, name, value, true);
  46.         return true;
  47. }
  48.  
  49. void CSerializeWriterXMLCPBin::RecursiveAddXmlNodeRef(XMLCPB::CNodeLiveWriterRef BNode, XmlNodeRef xmlNode)
  50. {
  51.         XMLCPB::CNodeLiveWriterRef BChild = BNode->AddChildNode(xmlNode->getTag());
  52.         for (int i = 0; i < xmlNode->getNumAttributes(); ++i)
  53.         {
  54.                 const char* pKey = NULL;
  55.                 const char* pVal = NULL;
  56.                 bool ok = xmlNode->getAttributeByIndex(i, &pKey, &pVal);
  57.                 assert(ok);
  58.                 BChild->AddAttr(pKey, pVal);
  59.         }
  60.  
  61.         for (int i = 0; i < xmlNode->getChildCount(); ++i)
  62.         {
  63.                 RecursiveAddXmlNodeRef(BChild, xmlNode->getChild(i));
  64.         }
  65. }
  66.  
  67. bool CSerializeWriterXMLCPBin::Value(const char* name, XmlNodeRef& value)
  68. {
  69.         if (!value)
  70.                 return false;
  71.  
  72.         if (value->getNumAttributes() == 0 && value->getChildCount() == 0)
  73.                 return false;
  74.  
  75.         XMLCPB::CNodeLiveWriterRef BNode = CurNode()->AddChildNode(name);
  76.         RecursiveAddXmlNodeRef(BNode, value);
  77.         return true;
  78. }
  79.  
  80. bool CSerializeWriterXMLCPBin::ValueByteArray(const char* name, const uint8* data, uint32 len)
  81. {
  82.         XMLCPB::CNodeLiveWriterRef& curNode = CurNode();
  83.  
  84. #ifndef _RELEASE
  85.         if (GetISystem()->IsDevMode() && curNode.IsValid())
  86.         {
  87.                 if (curNode->HaveAttr(name))
  88.                 {
  89.                         assert(0);
  90.                         CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Duplicate tag Value( \"%s\" ) in Group %s", name, GetStackInfo());
  91.                 }
  92.         }
  93. #endif
  94.  
  95.         if (!IsDefaultValue(data, len))
  96.         {
  97.                 curNode->AddAttr(name, data, len);
  98.         }
  99.  
  100.         return true;
  101. }
  102.  
  103. //////////////////////////////////////////////////////////////////////////
  104.  
  105. void CSerializeWriterXMLCPBin::ScriptValue(XMLCPB::CNodeLiveWriterRef addTo, const char* tag, const char* name, const ScriptAnyValue& value, bool bCheckEntityOnScript)
  106. {
  107.         CHECK_SCRIPT_STACK;
  108.  
  109.         bool bShouldAdd = true;
  110.  
  111.         m_luaSaveStack.push_back(name);
  112.  
  113.         assert(tag || name);
  114.         XMLCPB::CNodeLiveWriterRef node = addTo->AddChildNode(tag ? tag : name);
  115.         if (tag && name)
  116.                 node->AddAttr(TAG_SCRIPT_NAME, name);
  117.  
  118.         switch (value.type)
  119.         {
  120.         case ANY_TNIL:
  121.                 node->AddAttr(TAG_SCRIPT_TYPE, "nil");
  122.                 break;
  123.         case ANY_TBOOLEAN:
  124.                 node->AddAttr(TAG_SCRIPT_VALUE, value.b);
  125.                 node->AddAttr(TAG_SCRIPT_TYPE, "b");
  126.                 break;
  127.         case ANY_THANDLE:
  128.                 {
  129.                         // We are always writing a uint64 for handles. In x86, this is a bit inefficient. But when dealing
  130.                         //      with writing in x86 and reading in x64 (or vice versa), this ensures we don't have to guess which DWORD
  131.                         //      to cast from when reading (especially for Endian).
  132.                         uint64 v = (uint64)(UINT_PTR)value.ptr;
  133.                         node->AddAttr(TAG_SCRIPT_VALUE, v);
  134.                         node->AddAttr(TAG_SCRIPT_TYPE, "h");
  135.                 }
  136.                 break;
  137.         case ANY_TNUMBER:
  138.                 node->AddAttr(TAG_SCRIPT_VALUE, value.number);
  139.                 node->AddAttr(TAG_SCRIPT_TYPE, "n");
  140.                 break;
  141.         case ANY_TSTRING:
  142.                 node->AddAttr(TAG_SCRIPT_VALUE, value.str);
  143.                 node->AddAttr(TAG_SCRIPT_TYPE, "s");
  144.                 break;
  145.         case ANY_TVECTOR:
  146.                 {
  147.                         Vec3 temp(value.vec3.x, value.vec3.y, value.vec3.z);
  148.                         node->AddAttr(TAG_SCRIPT_VALUE, temp);
  149.                         node->AddAttr(TAG_SCRIPT_TYPE, "v");
  150.                 }
  151.                 break;
  152.         case ANY_TTABLE:
  153.                 if (!value.table)
  154.                         node->AddAttr(TAG_SCRIPT_TYPE, "nil");
  155.                 else
  156.                 {
  157.                         // Check for recursion.
  158.                         if (std::find(m_savedTables.begin(), m_savedTables.end(), value.table) == m_savedTables.end())
  159.                         {
  160.                                 m_savedTables.push_back(value.table);
  161.                                 WriteTable(node, value.table, true);
  162.                                 m_savedTables.pop_back();
  163.                         }
  164.                         else
  165.                         {
  166.                                 // Trying to write table recursively.
  167.                                 assert(0 && "Writing script table recursively");
  168.                                 CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Writing script table recursively: %s", GetStackInfo());
  169.                                 bShouldAdd = false;
  170.                         }
  171.                 }
  172.                 break;
  173.         default:
  174.                 CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Unhandled script-any-type %s of type:%d in Group %s", name, value.type, GetStackInfo());
  175.                 Failed();
  176.                 bShouldAdd = false;
  177.         }
  178.  
  179.         m_luaSaveStack.pop_back();
  180. }
  181.  
  182. //////////////////////////////////////////////////////////////////////////
  183. void CSerializeWriterXMLCPBin::BeginGroup(const char* szName)
  184. {
  185.         XMLCPB::CNodeLiveWriterRef node = CurNode()->AddChildNode(szName);
  186.         m_nodeStack.push_back(node);
  187.         if (m_nodeStack.size() > MAX_NODE_STACK_DEP)
  188.                 CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Too Deep Node Stack:\r\n%s", GetStackInfo());
  189. }
  190.  
  191. bool CSerializeWriterXMLCPBin::BeginOptionalGroup(const char* szName, bool condition)
  192. {
  193.         if (condition)
  194.                 BeginGroup(szName);
  195.  
  196.         return condition;
  197. }
  198.  
  199. void CSerializeWriterXMLCPBin::EndGroup()
  200. {
  201.         if (m_nodeStack.size() == 1)
  202.         {
  203.                 CryWarning(VALIDATOR_MODULE_SYSTEM, VALIDATOR_WARNING, "!Misplaced EndGroup() for BeginGroup(%s)", CurNode()->GetTag());
  204.         }
  205.         CurNode()->Done();   // this call is actually not needed. because the XMLCPBin will already detect when the node can be closed. But it does not hurt to do it explicitely.
  206.         m_nodeStack.pop_back();
  207.         assert(!m_nodeStack.empty());
  208. }
  209.  
  210. // TODO: need to re-look carefully at all this script management code. Right now it is esentially a copy paste from CSerializeXMLWriter
  211. //////////////////////////////////////////////////////////////////////////
  212.  
  213. bool CSerializeWriterXMLCPBin::ShouldSkipValue(const char* name, const ScriptAnyValue& value)
  214. {
  215.         CHECK_SCRIPT_STACK;
  216.  
  217.         if (!name)
  218.                 return true;
  219.  
  220.         if (strlen(name) >= 2)
  221.                 if (name[0] == '_' && name[1] == '_')
  222.                         return true;
  223.         if (!strlen(name))
  224.                 return true;
  225.  
  226.         switch (value.type)
  227.         {
  228.         case ANY_TBOOLEAN:
  229.         case ANY_THANDLE:
  230.         case ANY_TNIL:
  231.         case ANY_TNUMBER:
  232.         case ANY_TSTRING:
  233.         case ANY_TVECTOR:
  234.                 return false;
  235.         case ANY_TTABLE:
  236.                 {
  237.                         ScriptAnyValue temp;
  238.                         value.table->GetValueAny("__nopersist", temp);
  239.                         return temp.type != ANY_TNIL;
  240.                 }
  241.         default:
  242.                 return true;
  243.         }
  244. }
  245.  
  246. void CSerializeWriterXMLCPBin::WriteTable(XMLCPB::CNodeLiveWriterRef node, SmartScriptTable tbl, bool bCheckEntityOnScript)
  247. {
  248.         CHECK_SCRIPT_STACK;
  249.  
  250.         EntityId entityId;
  251.         if (bCheckEntityOnScript && IsEntity(tbl, entityId))
  252.         {
  253.                 node->AddAttr(TAG_SCRIPT_TYPE, "entityId");
  254.                 node->AddAttr(TAG_SCRIPT_VALUE, entityId);
  255.         }
  256.         else if (IsVector(tbl))
  257.         {
  258.                 Vec3 value;
  259.                 tbl->GetValue("x", value.x);
  260.                 tbl->GetValue("y", value.y);
  261.                 tbl->GetValue("z", value.z);
  262.                 node->AddAttr(TAG_SCRIPT_TYPE, "vec");
  263.                 node->AddAttr(TAG_SCRIPT_VALUE, value);
  264.         }
  265.         else
  266.         {
  267.                 node->AddAttr(TAG_SCRIPT_TYPE, "table");
  268.                 CHECK_SCRIPT_STACK;
  269.                 int arrayCount = tbl->Count();
  270.                 if (arrayCount)
  271.                 {
  272.                         node->AddAttr("count", arrayCount);
  273.                         CHECK_SCRIPT_STACK;
  274.                         for (int i = 1; i <= arrayCount; i++)
  275.                         {
  276.                                 ScriptAnyValue tempValue;
  277.                                 tbl->GetAtAny(i, tempValue);
  278.                                 if (tempValue.type != ANY_TFUNCTION && tempValue.type != ANY_TUSERDATA && tempValue.type != ANY_ANY)
  279.                                         ScriptValue(node, "i", NULL, tempValue, true);
  280.                         }
  281.                 }
  282.                 else
  283.                 {
  284.                         CHECK_SCRIPT_STACK;
  285.                         IScriptTable::Iterator iter = tbl->BeginIteration();
  286.                         while (tbl->MoveNext(iter))
  287.                         {
  288.                                 if (iter.sKey)
  289.                                 {
  290.                                         ScriptAnyValue tempValue;
  291.                                         tbl->GetValueAny(iter.sKey, tempValue);
  292.                                         if (ShouldSkipValue(iter.sKey, tempValue))
  293.                                                 continue;
  294.                                         if (tempValue.type != ANY_TFUNCTION && tempValue.type != ANY_TUSERDATA && tempValue.type != ANY_ANY)
  295.                                                 ScriptValue(node, "te", iter.sKey, tempValue, true);
  296.                                 }
  297.                         }
  298.                         tbl->EndIteration(iter);
  299.                 }
  300.         }
  301. }
  302.  
  303. //////////////////////////////////////////////////////////////////////////
  304. bool CSerializeWriterXMLCPBin::IsEntity(SmartScriptTable tbl, EntityId& entityId)
  305. {
  306.         CHECK_SCRIPT_STACK;
  307.  
  308.         bool bEntityTable = false;
  309.         ScriptHandle hdlId, hdlThis;
  310.         if (tbl->GetValue("id", hdlId))
  311.         {
  312.                 if (hdlId.n && tbl->GetValue("__this", hdlThis))
  313.                 {
  314.                         bEntityTable = true;
  315.                         if ((EntityId)(TRUNCATE_PTR)hdlThis.ptr == (EntityId)(TRUNCATE_PTR)gEnv->pEntitySystem->GetEntity((EntityId)hdlId.n))
  316.                         {
  317.                                 entityId = (EntityId)hdlId.n;
  318.                         }
  319.                 }
  320.         }
  321.         return bEntityTable;
  322. }
  323.  
  324. //////////////////////////////////////////////////////////////////////////
  325. bool CSerializeWriterXMLCPBin::IsVector(SmartScriptTable tbl)
  326. {
  327.         CHECK_SCRIPT_STACK;
  328.  
  329.         if (tbl->Count())
  330.                 return false;
  331.  
  332.         bool have[3] = { false, false, false };
  333.  
  334.         IScriptTable::Iterator iter = tbl->BeginIteration();
  335.         while (tbl->MoveNext(iter))
  336.         {
  337.                 if (iter.sKey)
  338.                 {
  339.                         if (strlen(iter.sKey) > 1)
  340.                         {
  341.                                 tbl->EndIteration(iter);
  342.                                 return false;
  343.                         }
  344.                         char elem = iter.sKey[0];
  345.                         if (elem < 'x' || elem > 'z')
  346.                         {
  347.                                 tbl->EndIteration(iter);
  348.                                 return false;
  349.                         }
  350.                         have[elem - 'x'] = true;
  351.                 }
  352.         }
  353.         tbl->EndIteration(iter);
  354.         return have[0] && have[1] && have[2];
  355. }
  356.  
  357. //////////////////////////////////////////////////////////////////////////
  358. const char* CSerializeWriterXMLCPBin::GetStackInfo() const
  359. {
  360.         static string str;
  361.         str.assign("");
  362.         for (int i = 0; i < (int)m_nodeStack.size(); i++)
  363.         {
  364.                 const char* name = m_nodeStack[i]->ReadAttrStr(TAG_SCRIPT_NAME);
  365.                 if (name && name[0])
  366.                         str += name;
  367.                 else
  368.                         str += m_nodeStack[i]->GetTag();
  369.                 if (i != m_nodeStack.size() - 1)
  370.                         str += "/";
  371.         }
  372.         return str.c_str();
  373. }
  374.  
  375. //////////////////////////////////////////////////////////////////////////
  376. const char* CSerializeWriterXMLCPBin::GetLuaStackInfo() const
  377. {
  378.         static string str;
  379.         str.assign("");
  380.         for (int i = 0; i < (int)m_luaSaveStack.size(); i++)
  381.         {
  382.                 const char* name = m_luaSaveStack[i];
  383.                 str += name;
  384.                 if (i != m_luaSaveStack.size() - 1)
  385.                         str += ".";
  386.         }
  387.         return str.c_str();
  388. }
  389.  
downloadSerializeWriterXMLCPBin.cpp Source code - Download CRYENGINE Source code
Related Source Codes/Software:
postal - 2017-06-11
reactide - Reactide is the first dedicated IDE for React web ... 2017-06-11
rkt - rkt is a pod-native container engine for Linux. It... 2017-06-11
uWebSockets - Tiny WebSockets https://for... 2017-06-11
realworld - TodoMVC for the RealWorld - Exemplary fullstack Me... 2017-06-11
CRYENGINE - CRYENGINE is a powerful real-time game development... 2017-06-11
goreplay - GoReplay is an open-source tool for capturing and ... 2017-06-10
pyenv - Simple Python version management 2017-06-10
redux-saga - An alternative side effect model for Redux apps ... 2017-06-10
angular-starter - 2017-06-10

 Back to top