Understanding XML Params and Values

#1
Hello!
I'm having some trouble understanding the XML system for Cryengine.
Is the way I'm currently doing it an acceptable way?

What does rootNode->getAttr() actually do? what does FindFilteredChild() do?

I want to keep this modder friendly, where you can modify the XML and make new structures on the fly. I will likely add the mesh path in the xml as well
How can I improve this to make this easier when create my building types?

ResourceManager Code

Code: Select all

void CResourceManager::ReadBuidlingParams(const XmlNodeRef& rootNode, const char* buildingClassName) { CGameXmlParamReader reader(rootNode); //gEnv->pSystem->LoadXmlFromFile(resourceXMLPath); //Edit* This goes somewhere else IGameFramework* pGameFramework = gEnv->pGameFramework; IItemSystem* pItemSystem = pGameFramework->GetIItemSystem(); rootNode->getAttr(/*how does this work*/); FUNCTION_PROFILER(GetISystem(), PROFILE_GAME); //Dont know what this is. copied from GameSDK. looks important XmlNodeRef paramsNode = reader.FindFilteredChild(buildingClassName /*+Dont know how to add words :( */ "params"); CGameXmlParamReader paramsReader(paramsNode); paramsReader.FindFilteredChild("inputwater"); paramsReader.FindFilteredChild("outputwater"); //TODO: put more things here float inputWater = paramsReader.ReadParamValue<float>("inputwater", water); float outputWater = paramsReader.ReadParamValue<float>("outputwater", water); }
XML Code

Code: Select all

<Resources> <ResourceTypes> <WaterTowerParams name="WaterTower" inputmoney="1.0" outputwater="1.0" /> <RoadParams name="Road" inputmoney="1.0" /> <OilPumpParams name="OilPump" inputmoney="1.0" outputoil="1.0" /> <GasPlantParams name="GasPlant" inputoil="1.0" inputlabor="1.0" outputgas="2.0" /> <GasStationParams name="GasStation" inputgas="1.0" outputmoney="2.0" /> <HouseParams name="House" inputwater="1" outputlabor"2" /> </ResourceTypes> </Resources>
C++ Pic
XML Pic
and yes I know the xml stuff is named in a borderline retarded way

Thanks!
-Moose
ImageTwitterImage

Re: Understanding XML Params and Values

#2
Itemsystem not needed in that example.
Function profiler is for performance monitoring not needed.

An xml node is basically the tags. Eg. Resources is a node (root node). ResourceTypes is a child node etc.

An xml attribute is a property set on the node. name is an attribute of water tower node.

Xml node contents is everything between the nodes tags.

You basically get the root noe as you done. Then iterate over its child nodes and read the attributes etc.

Cheers
Uniflare
CRYENGINE Technical Community Manager
Here to help the community and social channels grow and thrive.

My personal belongings;
Beginner Guides | My GitHub | Splash Plugin

Re: Understanding XML Params and Values

#3
Thanks!
I am using the item system to hold the building types. As time goes on, this seems less like a good idea.

how does this:

Code: Select all

float outputWater = paramsReader.ReadParamValue<float>("outputwater", water);
differ from

Code: Select all

childNode->getAttr("outputwater", outputWater);
?

also, what does

Code: Select all

paramsReader.FindFilteredChild("outputwater");
do? is it necessary?

And it doesn't seem like I should use the first bit, as water is a global value, that is meant to be increased and decreased
ImageTwitterImage

Re: Understanding XML Params and Values

#4
I used something similar to below code snippets for a basic crafting system's blueprints manager.

Code: Select all

char * file_name = "file_name.xml"; XmlNodeRef rootNode = GetISystem()->LoadXmlFromFile(file_name); if (rootNode) { CryLog("%s found!", file_name); for (size_t i = 0; i < rootNode->getChildCount(); i++) // iterate over a tag's children(tags). { XmlNodeRef child = rootNode->getChild(i); CryLog(child->getTag()); } rootNode->findChild("DestructibleParts"); // find a child with name, not sure what happens when there are multiple children with similar names. rootNode->getTag(); // get tag's name. return s a "const char *". const char *att_value; att_value = rootNode->getAttr("AttName"); // get attribute's value with name. for (size_t j = 0; j < rootNode->getNumAttributes(); j++) // I haven't tried this but I think this is how you iterate over a tag's attributes. { char *key; char *value; rootNode->getAttributeByIndex(j, &key, &value); } } else { CryLog("Failed to find file: %s", file_name); }
Add and remove nodes:

Code: Select all

rootNode->addChild(rootNode->createNode("hi1")); rootNode->addChild(rootNode->createNode("hi2")); rootNode->addChild(rootNode->createNode("hi3")); rootNode->addChild(rootNode->createNode("hi4")); rootNode->removeChild(child_node); rootNode->saveToFile(m_file_name);
Create an XML file from scratch. (maybe for a save file):

Code: Select all

XmlNodeRef a = GetISystem()->CreateXmlNode("Hello"); XmlNodeRef b = a->createNode("Hi"); b->setAttr("att", "val"); a->addChild(b); a->saveToFile("%USER%/some_file2.xml"); // saves the file to user profile directory (the "user" folder in root folder) //XmlNodeRef rootNode; //rootNode->setTag("Hello"); //rootNode->saveToFile("some_file2.xml");

Re: Understanding XML Params and Values

#5

Code: Select all

XmlNodeRef FindFilteredChild(const char* childName) const
Ok, "Find" "Filtered" "Child".
It will find the child of the current node by name "childName".
BUT, it will filter the results, it will skip children that are filtered out by them specifying "GAME" or "DEVMODE" as an attribute of the node.

eg, if you want a node to ONLY be available in DEV Mode then you would add the attribute "DEVMODE" to that node. (no value needed).
Then it will only be read in dev mode, not in release etc.

similarly, if you want your node to only be read during a specific GameMode, you would put a GAME="SP" or GAME="MP" attribute, it will only be read when the engine is in this game mode.

If the node does not specify a filter attribute, it will not be filtered and you will get that node when reading in any mode.

-----------------------

Code: Select all

const char* ReadParamValue(const char* paramName, const char* defaultValue) const
Misleading, this calls the nodes "params". it assumes your node has a "value" attribute, and internally calls childNode->GetAttr("value");.
This is also filtered same as above with copied code.

----------------------

Code: Select all

const char* getAttr(const char* name) const
This is raw, no filtering, no assumptions. It will do exactly what you ask, return the value associated to the specified attribute.



hope this helps.
Uniflare
CRYENGINE Technical Community Manager
Here to help the community and social channels grow and thrive.

My personal belongings;
Beginner Guides | My GitHub | Splash Plugin

Re: Understanding XML Params and Values

#6
Thanks a lot for your help!

I was able to modify the script to get my building names, which will get an xml of the same name that holds the resource data

Code: Select all

void CBuildingManager::LoadBuildingXML() { char * file_name = "Scripts/Buildings/BuildingList.xml"; XmlNodeRef rootNode = GetISystem()->LoadXmlFromFile(file_name); if (rootNode) { CryLog("%s found!", file_name); /*Iterate Nodes*/ for (size_t i = 0; i < rootNode->getChildCount(); i++) { XmlNodeRef child = rootNode->getChild(i); for (size_t y = 0; y < child->getChildCount(); y++) { XmlNodeRef tags = child->getChild(y); CGameXmlParamReader reader(tags); for (size_t j = 0; j < tags->getNumAttributes(); j++) { const char *name; const char *value; tags->getAttributeByIndex(j, &name, &value); CryLog("%s = %s", name, value); } } } } }
This is surely the best documentation for XML scripting we have to date (afaik)
-Moose
ImageTwitterImage

Who is online

Users browsing this forum: No registered users and 2 guests

cron