BVB Source Codes

CRYENGINE Show PipeManager.cpp Source code

Return Download CRYENGINE: download PipeManager.cpp Source code - Download CRYENGINE Source code - Type:.cpp
  1. // Copyright 2001-2016 Crytek GmbH / Crytek Group. All rights reserved.
  2.  
  3. /********************************************************************
  4.    -------------------------------------------------------------------------
  5.    File name:   PipeManager.cpp
  6.    $Id$
  7.    Description:
  8.  
  9.    -------------------------------------------------------------------------
  10.    History:
  11.    - 8:6:2005   14:17 : Created by Kirill Bulatsev
  12.  
  13.  *********************************************************************/
  14.  
  15. #include "StdAfx.h"
  16. #include <CryNetwork/ISerialize.h>
  17. #include "PipeManager.h"
  18. #include "GoalPipe.h"
  19. #include <CryCore/StlUtils.h>
  20.  
  21. CPipeManager::CPipeManager(void) :
  22.         m_bDynamicGoalPipes(false)
  23. {
  24.         CreateGoalPipe("_first_", SilentlyReplaceDuplicate);
  25. }
  26.  
  27. CPipeManager::~CPipeManager(void)
  28. {
  29.         GoalMap::iterator gi;
  30.         for (gi = m_mapGoals.begin(); gi != m_mapGoals.end(); ++gi)
  31.                 delete gi->second;
  32.  
  33.         m_mapGoals.clear();
  34. }
  35.  
  36. void CPipeManager::ClearAllGoalPipes()
  37. {
  38.         CGoalPipe* first = NULL;
  39.  
  40.         for (GoalMap::iterator gi = m_mapGoals.begin(); gi != m_mapGoals.end(); )
  41.         {
  42.                 if (gi->first != "_first_")
  43.                 {
  44.                         delete gi->second;
  45.                         m_mapGoals.erase(gi++);
  46.                 }
  47.                 else
  48.                 {
  49.                         first = gi->second;
  50.                         ++gi;
  51.                 }
  52.         }
  53.  
  54.         if (!first)
  55.                 CreateGoalPipe("_first_", SilentlyReplaceDuplicate);
  56.         else
  57.                 m_bDynamicGoalPipes = false;
  58. }
  59.  
  60. //
  61. //-----------------------------------------------------------------------------------------------------------
  62. IGoalPipe* CPipeManager::CreateGoalPipe(const char* pName,
  63.                                         const CPipeManager::ActionToTakeWhenDuplicateFound actionToTakeWhenDuplicateFound)
  64. {
  65.         if (!strcmp("_first_", pName))
  66.                 m_bDynamicGoalPipes = false;
  67.  
  68.         if (!strcmp("_last_", pName))
  69.         {
  70.                 m_bDynamicGoalPipes = true;
  71.                 return NULL;
  72.         }
  73.  
  74.         // always create a new goal pipe
  75.         CGoalPipe* pNewPipe = new CGoalPipe(pName, m_bDynamicGoalPipes);
  76.  
  77.         // try to insert the new element in the map
  78.         std::pair<GoalMap::iterator, bool> insertResult = m_mapGoals.insert(GoalMap::iterator::value_type(pName, pNewPipe));
  79.  
  80.         const bool goalPipeAlreadyExists = !insertResult.second;
  81.         if (goalPipeAlreadyExists)
  82.         {
  83.                 if (actionToTakeWhenDuplicateFound == ReplaceDuplicateAndReportError)
  84.                 {
  85.                         CryWarning(VALIDATOR_MODULE_AI, VALIDATOR_ERROR, "Goal pipe with name %s already exists. Replacing.", pName);
  86.                 }
  87.  
  88.                 // ...destroy the old one...
  89.                 delete insertResult.first->second;
  90.                 // ...and assign the new one
  91.                 insertResult.first->second = pNewPipe;
  92.         }
  93.  
  94.         return pNewPipe;
  95. }
  96.  
  97. //
  98. //-----------------------------------------------------------------------------------------------------------
  99. IGoalPipe* CPipeManager::OpenGoalPipe(const char* pName)
  100. {
  101.         if (!pName)
  102.                 return 0;
  103.         GoalMap::iterator gi = m_mapGoals.find(CONST_TEMP_STRING(pName));
  104.         return gi != m_mapGoals.end() ? gi->second : NULL;
  105. }
  106.  
  107. //
  108. //-----------------------------------------------------------------------------------------------------------
  109. CGoalPipe* CPipeManager::IsGoalPipe(const char* name)
  110. {
  111.         GoalMap::iterator gi = m_mapGoals.find(CONST_TEMP_STRING(name));
  112.         return gi != m_mapGoals.end() ? gi->second->Clone() : NULL;
  113. }
  114.  
  115. //
  116. //-----------------------------------------------------------------------------------------------------------
  117. void CPipeManager::Serialize(TSerialize ser)
  118. {
  119. #ifdef SERIALIZE_DYNAMIC_GOALPIPES
  120.         int counter(0);
  121.         char nameBuffer[16];
  122.         ser.BeginGroup("DynamicGoalPipes");
  123.         {
  124.                 cry_sprintf(nameBuffer, "DynPipe_%d", ++counter);
  125.                 if (ser.IsWriting())
  126.                 {
  127.                         for (GoalMap::iterator gi(m_mapGoals.begin()); gi != m_mapGoals.end(); ++gi)
  128.                         {
  129.                                 if (!gi->second->IsDynamic())
  130.                                         continue;
  131.                                 ser.BeginOptionalGroup(nameBuffer, true);
  132.                                 string tempstr = gi->first;
  133.                                 ser.Value("PipeName", tempstr);
  134.                                 gi->second->SerializeDynamic(ser);
  135.                                 ser.EndGroup();
  136.                                 cry_sprintf(nameBuffer, "DynPipe_%d", ++counter);
  137.                         }
  138.                         ser.BeginOptionalGroup(nameBuffer, false);
  139.                 }
  140.                 else
  141.                 {
  142.                         while (ser.BeginOptionalGroup(nameBuffer, true))
  143.                         {
  144.                                 string name;
  145.                                 ser.Value("PipeName", name);
  146.                                 CGoalPipe* pNewPipe = static_cast<CGoalPipe*>(CreateGoalPipe(name, SilentlyReplaceDuplicate));
  147.                                 pNewPipe->SerializeDynamic(ser);
  148.                                 ser.EndGroup();
  149.                                 cry_sprintf(nameBuffer, "DynPipe_%d", ++counter);
  150.                         }
  151.                 }
  152.         }
  153.         ser.EndGroup();
  154. #endif // SERIALIZE_DYNAMIC_GOALPIPES
  155. }
  156.  
  157. //
  158. //-----------------------------------------------------------------------------------------------------------
  159. struct CheckFuncCallScanDef
  160. {
  161.         int   p;    // compare iterator
  162.         char* str;  // function name to detect
  163. };
  164.  
  165. struct CheckFuncCall
  166. {
  167.         int                 fileId; // index to file where the function call comes from
  168.         int                 tok;    // index to function call def
  169.         std::vector<string> params; // function call params
  170. };
  171.  
  172. struct CheckGoalpipe
  173. {
  174.         string              name;          // name of the pipe
  175.         std::vector<string> embeddedPipes; // pipes that are embedded into this pipe when it is instantiated
  176.         std::vector<int>    usedInFile;    // index to files where the pipe is used
  177.         int                 fileId;        // index to file where the pipe is created
  178. };
  179.  
  180. typedef std::map<string, CheckGoalpipe*> CheckPipeMap;
  181.  
  182. //
  183. //-----------------------------------------------------------------------------------------------------------
  184. static void ScanFileForFunctionCalls(const char* filename, int fileId, std::vector<CheckFuncCall>& calls,
  185.                                      CheckFuncCallScanDef* scan, int nscan)
  186. {
  187.         FILE* fp = fxopen(filename, "rb");
  188.         if (!fp) return;
  189.  
  190.         if (fseek(fp, 0, SEEK_END))
  191.         {
  192.                 return;
  193.         }
  194.  
  195.         int size = ftell(fp);
  196.  
  197.         if (fseek(fp, 0, SEEK_SET))
  198.         {
  199.                 return;
  200.         }
  201.  
  202.         if (size < 2)
  203.         {
  204.                 fclose(fp);
  205.                 return;
  206.         }
  207.  
  208.         char* data = new char[size];
  209.         if (!data)
  210.         {
  211.                 fclose(fp);
  212.                 return;
  213.         }
  214.         fread(data, size, 1, fp);
  215.  
  216.         fclose(fp);
  217.  
  218.         char* end = data + size;
  219.         char* str = data;
  220.         char* eol = 0;
  221.         char* param = 0;
  222.         int state = 0;
  223.  
  224.         while (str != end)
  225.         {
  226.                 // Skip white spaces in the beginning of the line.
  227.                 while (str != end && (*str == ' ' || *str == '\t'))
  228.                         str++;
  229.  
  230.                 // Find the end of the line
  231.                 eol = str;
  232.                 while (eol != end && *eol != 0x0d && *eol != 0x0a) // advance until end of line
  233.                         ++eol;
  234.                 while (eol != end && (*eol == 0x0d || *eol == 0x0a)) // include the eol markers into the line
  235.                         ++eol;
  236.  
  237.                 // Skip the line if it is a comment
  238.                 if (str != end && (str + 1) != end && str[0] == '-' && str[1] == '-')
  239.                 {
  240.                         str = eol;
  241.                         continue;
  242.                 }
  243.  
  244.                 // Parse the line
  245.                 while (str != eol)
  246.                 {
  247.                         if (state == 0)
  248.                         {
  249.                                 if (*str == '.' || *str == ':')
  250.                                 {
  251.                                         // Reset tokens
  252.                                         for (int i = 0; i < nscan; ++i)
  253.                                                 scan[i].p = 0;
  254.                                         state = 1; // Check token
  255.                                 }
  256.                         }
  257.                         else if (state == 1)
  258.                         {
  259.                                 // Check if a token starts.
  260.                                 int passed = 0;
  261.                                 for (int i = 0; i < nscan; ++i)
  262.                                 {
  263.                                         CheckFuncCallScanDef& t = scan[i];
  264.                                         if (t.p == -1) continue; // invalid
  265.                                         if (t.str[t.p] == *str)
  266.                                         {
  267.                                                 ++t.p;
  268.                                                 ++passed;
  269.                                                 if (t.str[t.p] == '\0') // end of token?
  270.                                                 {
  271.                                                         param = 0;
  272.                                                         state = 2; // parse params
  273.  
  274.                                                         calls.resize(calls.size() + 1);
  275.                                                         calls.back().fileId = fileId;
  276.                                                         calls.back().tok = i;
  277.                                                 }
  278.                                         }
  279.                                         else
  280.                                                 t.p = -1;
  281.                                 }
  282.                                 if (!passed)
  283.                                         state = 0; // not a valid token, restart.
  284.                         }
  285.                         else if (state == 2)
  286.                         {
  287.                                 // Scan until open bracket
  288.                                 if (*str == '(')
  289.                                 {
  290.                                         state = 3; // scan params
  291.                                 }
  292.                         }
  293.                         else if (state == 3)
  294.                         {
  295.                                 if (*str == ',')
  296.                                 {
  297.                                         // Next param
  298.                                         *str = '\0';
  299.                                         if (param)
  300.                                                 calls.back().params.push_back(string(param));
  301.                                         param = 0;
  302.                                 }
  303.                                 else if (*str == ')')
  304.                                 {
  305.                                         // End of func call
  306.                                         *str = '\0';
  307.                                         if (param)
  308.                                                 calls.back().params.push_back(string(param));
  309.                                         param = 0;
  310.                                         // Restart
  311.                                         state = 0;
  312.                                 }
  313.                                 else
  314.                                 {
  315.                                         if (!param) // Init param start.
  316.                                                 param = str;
  317.                                 }
  318.                         }
  319.                         ++str;
  320.                 }
  321.  
  322.                 // Proceed to new line.
  323.                 str = eol;
  324.         }
  325.  
  326.         if (state != 0)
  327.         {
  328.                 CryLog("bad end of line! (state = %d)", state);
  329.         }
  330.  
  331.         delete[] data;
  332. }
  333.  
  334. //
  335. //-----------------------------------------------------------------------------------------------------------
  336. static void GetScriptFiles(const string& path, std::vector<string>& files)
  337. {
  338.         ICryPak* pCryPak = gEnv->pCryPak;
  339.         _finddata_t fd;
  340.  
  341.         string search(path);
  342.         search += "/*.*";
  343.         intptr_t handle = pCryPak->FindFirst(search.c_str(), &fd);
  344.  
  345.         string filename;
  346.  
  347.         char fext[_MAX_EXT];
  348.  
  349.         if (handle != -1)
  350.         {
  351.                 do
  352.                 {
  353.                         // Skip back folders.
  354.                         if (fd.name[0] == '.')
  355.                                 continue;
  356.  
  357.                         filename = path;
  358.                         filename += "/";
  359.                         filename += fd.name;
  360.  
  361.                         if (fd.attrib & _A_SUBDIR)
  362.                         {
  363.                                 // Recurse into subdir
  364.                                 GetScriptFiles(filename, files);
  365.                         }
  366.                         else
  367.                         {
  368.                                 // Check only lua files.
  369.                                 _splitpath(fd.name, 0, 0, 0, fext);
  370.                                 if (stricmp(fext, ".lua") != 0) continue;
  371.                                 files.push_back(filename);
  372.                         }
  373.                 }
  374.                 while (pCryPak->FindNext(handle, &fd) >= 0);
  375.                 pCryPak->FindClose(handle);
  376.         }
  377. }
  378.  
  379. //
  380. //-----------------------------------------------------------------------------------------------------------
  381. static bool ParseStringParam(int n, const std::vector<string>& params, string& out)
  382. {
  383.         out.clear();
  384.  
  385.         if (n >= (int)params.size())
  386.                 return false;
  387.  
  388.         const string& p = params[n];
  389.  
  390.         size_t first = p.find_first_of('\"');
  391.         if (first == p.npos)
  392.                 return false;
  393.         size_t last = p.find_first_of('\"', first + 1);
  394.         if (last == p.npos)
  395.                 return false;
  396.  
  397.         out = p.substr(first + 1, last - (first + 1));
  398.  
  399.         return true;
  400. }
  401.  
  402. //
  403. //-----------------------------------------------------------------------------------------------------------
  404. static void ParseGoalpipes(const std::vector<CheckFuncCall>& calls, const std::vector<string>& files, CheckPipeMap& pipes)
  405. {
  406.         CGoalPipe tmp("", false); // used for finding goalop names
  407.  
  408.         int type = 0;
  409.         CheckGoalpipe* pipe = 0;
  410.  
  411.         for (unsigned i = 0, ni = calls.size(); i < ni; ++i)
  412.         {
  413.                 const CheckFuncCall& c = calls[i];
  414.  
  415.                 if (c.tok == 0 || c.tok == 1) // AI.CreateGoalPipe(), AI.BeginGoalPipe()
  416.                 {
  417.                         if (pipe)
  418.                         {
  419.                                 std::pair<CheckPipeMap::iterator, bool> res = pipes.insert(std::make_pair(pipe->name, pipe));
  420.                                 if (!res.second)
  421.                                         delete pipe;
  422.                                 pipe = 0;
  423.                         }
  424.  
  425.                         pipe = new CheckGoalpipe;
  426.                         if (ParseStringParam(0, c.params, pipe->name))
  427.                         {
  428.                                 type = c.tok;
  429.                                 pipe->fileId = c.fileId;
  430.                         }
  431.                         else
  432.                         {
  433.                                 CryLog("Warning: Goal pipe name not a string: '%s' (maybe a variable?) - %s",
  434.                                        c.params.empty() ? "<null>" : c.params[0].c_str(),
  435.                                        files[c.fileId].c_str());
  436.                                 delete pipe;
  437.                                 pipe = 0;
  438.                         }
  439.                 }
  440.                 else if (c.tok == 2) // AI.PushGoal()
  441.                 {
  442.                         if (!pipe)
  443.                                 continue;
  444.                         string name;
  445.                         if (type == 0)
  446.                                 ParseStringParam(1, c.params, name);
  447.                         else
  448.                                 ParseStringParam(0, c.params, name);
  449.  
  450.                         EGoalOperations op;
  451.                         if (name.size() > 1 && name[0] == '+')
  452.                                 op = tmp.GetGoalOpEnum(name.c_str() + 1);
  453.                         else
  454.                                 op = tmp.GetGoalOpEnum(name.c_str());
  455.  
  456.                         if (op == eGO_LAST) // embedding another pipe
  457.                                 pipe->embeddedPipes.push_back(name);
  458.                 }
  459.         }
  460.  
  461.         if (pipe)
  462.         {
  463.                 std::pair<CheckPipeMap::iterator, bool> res = pipes.insert(std::make_pair(pipe->name, pipe));
  464.                 if (!res.second)
  465.                         delete pipe;
  466.                 pipe = 0;
  467.         }
  468. }
  469.  
  470. //
  471. //-----------------------------------------------------------------------------------------------------------
  472. static void ParsePipeUsage(const std::vector<CheckFuncCall>& calls, const std::vector<string>& files, CheckPipeMap& pipes)
  473. {
  474.         for (unsigned i = 0, ni = calls.size(); i < ni; ++i)
  475.         {
  476.                 const CheckFuncCall& c = calls[i];
  477.  
  478.                 // The pipe name is always the second parameter for SelectPipe() and InsertSubpipe().
  479.                 string pipeName;
  480.                 ParseStringParam(1, c.params, pipeName);
  481.  
  482.                 // Not using string to call the pipe.
  483.                 if (pipeName.size() < 1)
  484.                         continue;
  485.  
  486.                 // Find the pipe.
  487.                 CheckPipeMap::iterator it = pipes.find(pipeName);
  488.                 if (it == pipes.end())
  489.                 {
  490.                         // Pipe not found
  491.                         CryLog("Error: Cannot find pipe '%s' - %s",
  492.                                pipeName.c_str(),
  493.                                files[c.fileId].c_str());
  494.                 }
  495.                 else
  496.                 {
  497.                         // Pipe found, mark usage.
  498.                         CheckGoalpipe* pipe = it->second;
  499.                         stl::push_back_unique(pipe->usedInFile, c.fileId);
  500.                 }
  501.         }
  502.  
  503. }
  504. //
  505. //-----------------------------------------------------------------------------------------------------------
  506. static void MarkUsedEmbeddedPipe(CheckGoalpipe* pipe, CheckPipeMap& createdPipes,
  507.                                  const std::vector<string>& files)
  508. {
  509.         for (unsigned i = 0, ni = pipe->embeddedPipes.size(); i < ni; ++i)
  510.         {
  511.                 CheckPipeMap::iterator it = createdPipes.find(pipe->embeddedPipes[i]);
  512.  
  513.                 if (it == createdPipes.end())
  514.                 {
  515.                         CryLog("Error: Trying to embed invalid pipe '%s' into pipe '%s' - %s",
  516.                                pipe->embeddedPipes[i].c_str(),
  517.                                pipe->name.c_str(),
  518.                                files[pipe->fileId].c_str());
  519.                 }
  520.                 else
  521.                 {
  522.                         CheckGoalpipe* embeddedPipe = it->second;
  523.                         stl::push_back_unique(embeddedPipe->usedInFile, pipe->fileId);
  524.  
  525.                         // Recurse into children.
  526.                         MarkUsedEmbeddedPipe(embeddedPipe, createdPipes, files);
  527.                 }
  528.         }
  529. }
  530.  
  531. //
  532. //-----------------------------------------------------------------------------------------------------------
  533. void CPipeManager::CheckGoalpipes()
  534. {
  535.         // Find all calls to goalpipes
  536.         string path = gEnv->pSystem->GetRootFolder();
  537.         path += "Game/Scripts";
  538.  
  539.         // Collect all scrip files.
  540.         CryLog("- Collecting files...");
  541.         std::vector<string> files;
  542.         GetScriptFiles(path, files);
  543.  
  544.         // Scan used goalpipes.
  545.         std::vector<CheckFuncCall> pipesUsedCalls;
  546.         CheckFuncCallScanDef useFuncs[] = {
  547.                 { 0, "SelectPipe"    },
  548.                 { 0, "InsertSubpipe" },
  549.         };
  550.         CryLog("- Scanning used pipes...");
  551.         for (unsigned i = 0, ni = files.size(); i < ni; ++i)
  552.                 ScanFileForFunctionCalls(files[i].c_str(), (int)i, pipesUsedCalls, useFuncs, 2);
  553.  
  554.         // Scan created goalpipes
  555.         std::vector<CheckFuncCall> pipesCreatedCalls;
  556.         CheckFuncCallScanDef createFuncs[] = {
  557.                 { 0, "CreateGoalPipe" },
  558.                 { 0, "BeginGoalPipe"  },
  559.                 { 0, "PushGoal"       },
  560.                 { 0, "EndGoalPipe"    },
  561.         };
  562.         CryLog("- Scanning created pipes...");
  563.         for (unsigned i = 0, ni = files.size(); i < ni; ++i)
  564.                 ScanFileForFunctionCalls(files[i].c_str(), (int)i, pipesCreatedCalls, createFuncs, 4);
  565.  
  566.         // Parse pipes
  567.         CheckPipeMap createdPipes;
  568.         ParseGoalpipes(pipesCreatedCalls, files, createdPipes);
  569.  
  570.         // Parse pipe usage
  571.         ParsePipeUsage(pipesUsedCalls, files, createdPipes);
  572.  
  573.         // Check embedded pipes
  574.         for (CheckPipeMap::iterator it = createdPipes.begin(), end = createdPipes.end(); it != end; ++it)
  575.         {
  576.                 CheckGoalpipe* pipe = it->second;
  577.                 if (pipe->embeddedPipes.empty()) continue;
  578.  
  579.                 // The pipe is used, mark the embedded pipes as used too.
  580.                 if (!pipe->usedInFile.empty())
  581.                         MarkUsedEmbeddedPipe(pipe, createdPipes, files);
  582.         }
  583.  
  584.         CryLog("\n");
  585.  
  586.         // Create a list of pipes per file for more intuitive output.
  587.         std::vector<std::vector<CheckGoalpipe*>> unusedGoalsPerFile;
  588.         unusedGoalsPerFile.resize(files.size());
  589.  
  590.         int unusedCount = 0;
  591.         for (CheckPipeMap::iterator it = createdPipes.begin(), end = createdPipes.end(); it != end; ++it)
  592.         {
  593.                 CheckGoalpipe* pipe = it->second;
  594.                 if (pipe->usedInFile.empty())
  595.                 {
  596.                         unusedGoalsPerFile[pipe->fileId].push_back(pipe);
  597.                         unusedCount++;
  598.                 }
  599.         }
  600.  
  601.         // Output unused golapipes.
  602.         for (unsigned i = 0, ni = unusedGoalsPerFile.size(); i < ni; ++i)
  603.         {
  604.                 std::vector<CheckGoalpipe*>& pipes = unusedGoalsPerFile[i];
  605.                 if (pipes.empty()) continue;
  606.                 CryLog("%" PRISIZE_T " ununsed pipes in %s", pipes.size(), files[i].c_str());
  607.                 for (unsigned j = 0, nj = pipes.size(); j < nj; ++j)
  608.                         CryLog("    %s", pipes[j]->name.c_str());
  609.         }
  610.  
  611.         CryLog("\n");
  612.         CryLog("Unused goalpipes: %d of %" PRISIZE_T, unusedCount, createdPipes.size());
  613.  
  614.         // Cleanup
  615.         for (CheckPipeMap::iterator it = createdPipes.begin(), end = createdPipes.end(); it != end; ++it)
  616.                 delete it->second;
  617. }
  618.  
downloadPipeManager.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