Práce s XML
Farming Simulátor stavà na xml souborech. Každý stroj je konfigurován v xml. A právÄ› k XML potÅ™ebujeme nÄ›co, jak ho ovládat. K tomu sloužà funkce, které jsou definovány pÅ™Ãmo v jádÅ™e hry. K tomu sloužà následujÃcà funkce:
- VytcoÅ™enÃ, naÄtenÃ, ukládánÃ:
- createXMLFile();
- loadXMLFile();
- saveXMLFile();
- NaÄÃtánà hodnot:
- getXMLInt();
- getXMLFloat();
- getXMLBool();
- getXMLString();
- Ukládánà hodnot:
- setXMLInt();
- setXMLFloat();
- setXMLBool();
- setXMLString();
- OstatnÃ:
- removeXMLProperty();
- hasXMLProperty();
Nynà si vÅ¡echny tyto funkce rozebereme a vysvÄ›tlÃme si co dÄ›lajÃ. Pokud vás nebude zajÃmat tento Älánek a orientujete se v dokumentaci zkuste GDN dokumentaci.
VytvoÅ™enÃ, naÄtenà a ukládánà XML souboru
Pro tyto tÅ™i vÄ›ci existujà funkce createXMLFile, loadXMLFile a saveXMLFile. Protože už neco vytvářÃme, musÃme vÄ›dÄ›t kam to uložit. K tomu nám sloužà promÄ›nné g_modsDirectory - odkazuje na složku s mody - a g_currentModDirectory - odkazuje na složku s aktuálnÃm modem pod kterým běžà skript. A protože potÅ™ebujeme ukládat a naÄÃtat XML soubory ze složky aktuálnÃho modu, a nebo do složky mods (v pÅ™ÃpadÄ› konfiguraÄnÃch souborů), velice se nám hodÃ. PromÄ›nnou g_currentModDirectory si vÅ¡ak jeÅ¡tÄ› pÅ™ed použitÃm ve tÅ™ÃdÄ› se skriptem musÃme pÅ™euložit do jiné promÄ›nné - po spuÅ¡tÄ›nà tÅ™Ãdy již nenà platná.
Nynà si v pÅ™Ãkladu vytvoÅ™Ãme jednoduchý XML soubor:
12mujSkript = {};34-- ulozeni aktualni cesty k modu do lokalni promenne ktera plati pro tento soubor5local MDR = g_currentModDirectory;67function mujSkript.prerequisitesPresent(specializations)8 return true;9end;1011function mujSkript:load(xmlFile)12 -- vytvoreni souboru xml a ulozeni jeho ID do promenne mojeXML13 local mojeXML = createXMLFile("mujXMLsoubor",MDR.."xmltest.xml","konfigurace");14 -- ulozeni XML souboru podle ID15 saveXMLFile(mojeXML);16end;1718function mujSkript:mouseEvent(posX, posY, isDown, isUp, button)19end;2021function mujSkript:keyEvent(unicode, sym, modifier, idDown)22end;2324function mujSkript:update(dt)25end;2627function mujSkript:updateTick(dt)28end;2930function mujSkript:draw()31end;
NynÃ, když se koukneme do složky s modem pod kterým skript běžel, můžeme vidÄ›t vedle modDesc.xml také soubor xmltest.xml a v nÄ›m nÄ›co jako <konfigurace />. Je to proto, protože jsme do nÄ›j nic neuložili. Vstupnà parametry funkce createXMLFile jsou (vnitÅ™nà název entity(souboru), Celá cesta k xml v PC, Název hlavnÃho prvku) a funkce vracà ID objektu. Funkce saveXMLFile má vstupnà parametr pouze ID objektu. Toto byl pÅ™Ãklad na createXMLFile a saveXMLFile. Nynà si ukážeme naÄtenà XML souboru.
12mujSkript = {};34-- ulozeni aktualni cesty k modu do lokalni promenne ktera plati pro tento soubor5local MDR = g_currentModDirectory;67function mujSkript.prerequisitesPresent(specializations)8 return true;9end;1011function mujSkript:load(xmlFile)12 -- nacteme XML soubor13 local soubor = loadXMLFile("mujXMLsoubor",MDR.."xmltest.xml");14 print("ID XML souboru je "..soubor);15 -- ulozeni XML souboru podle ID16 saveXMLFile(soubor);17end;1819function mujSkript:mouseEvent(posX, posY, isDown, isUp, button)20end;2122function mujSkript:keyEvent(unicode, sym, modifier, idDown)23end;2425function mujSkript:update(dt)26end;2728function mujSkript:updateTick(dt)29end;3031function mujSkript:draw()32end;
NaneÅ¡tÄ›stà funkce loadXMLFile vrátà ID souboru i pÅ™esto, že žádný nenà a vygeneruje chybovou hlášku. DÃky tomu nelze oÅ¡etÅ™it problém neexistence souboru a musÃte mÃt jistotu že tam ten soubor je a nebo prostÄ› složitÄ› ověřovat existenci (což je podle mÄ› zbyteÄné u menÅ¡Ãch projektů).
Proměnná xmlFile ve funkci :load
Již jste si mohli vÅ¡imnout, že ve funkci load je jednÃm vstupnÃm parametrem xmlFile. Tento parametr nám pÅ™edává ID XML souboru stroje a je tak velmi užiteÄný. DÃky nÄ›mu můžeme ÄÃst data z XML stroje a nemusÃme znát jeho název. Chová se jako klasický XML soubor. NedoporuÄuji pÅ™episovat.
NaÄÃtánà dat z XML
Je jasné že potÅ™ebujeme nÄ›kdy taky data naÄÃtat. K tomu nám sloužà funkce zaÄÃnajÃcà slůvkem "getXML" a pokraÄujà pÅ™Ãponou datového typu. ÄŒistÄ› teoreticky můžete použÃt pouze getXMLString a Lua si to pÅ™evede na co potÅ™ebuje, ovÅ¡em v takovém pÅ™ÃpadÄ› nelze tak jednoduÅ¡e ověřit zda tam to ÄÃslo nebo pravdivostnà hodnota opravdu je.
MÄ›jme xml soubor stroje a chceme z nÄ›j pÅ™eÄÃst data a provést výpoÄty. Zde je pÅ™Ãklad:
12mujSkript = {};34-- ulozeni aktualni cesty k modu do lokalni promenne ktera plati pro tento soubor5local MDR = g_currentModDirectory;67function mujSkript.prerequisitesPresent(specializations)8 return true;9end;1011function mujSkript:load(xmlFile)12 --[[ Nacitani z XML stroje ]]--13 local cisel = Utils.getNoNil(getXMLInt(xmlFile,"vehicle.mujSkript#pocetCisel"),5);14 local hodnoty = {};15 local soucet = 0;16 local maxCislo;17 for i=1, cisel do18 if Utils.getNoNil(getXMLString(xmlFile,"vehicle.mujSkript.cislo"..i.."#type"),"tag") == "tag" then19 hodnoty[i] = getXMLInt(xmlFile,"vehicle.mujSkript.cislo"..i);20 else21 hodnoty[i] = getXMLFloat(xmlFile,"vehicle.mujSkript.cislo"..i.."#hodnota");22 end;23 print(i..". nactene cislo je "..hodnoty[i]);24 end;25 for i=1, cisel do26 if hodnoty[i] ~= nil then27 soucet = soucet + hodnoty[i];28 if i == 1 then29 maxCislo = hodnoty[i];30 end;31 if maxCislo < hodnoty[i] then32 maxCislo = hodnoty[i];33 end;34 end;35 end;36 print("Prumer nactenych cisel: "..(soucet/cisel));37 print("Pocet nactenych cisel je "..cisel);38 print("Maximalni nactene cislo je "..maxCislo);39end;4041function mujSkript:mouseEvent(posX, posY, isDown, isUp, button)42end;4344function mujSkript:keyEvent(unicode, sym, modifier, idDown)45end;4647function mujSkript:update(dt)48end;4950function mujSkript:updateTick(dt)51end;5253function mujSkript:draw()54end;
V pÅ™Ãkladu jsem naneÅ¡tÄ›stà nevyužil getXMLBool, ovÅ¡em funkci si lze odvodit. NavÃc jsem použil funkci Utils.getNoNil();, která nám zajiÅ¡Å¥uje filtrovánà nil hodnot. VstupnÃm parametrem je hodnota a poté náhradnà hodnota. V pÅ™ÃpadÄ› že hodnota bude nil, funkce vrátà náhradnà hodnotu. Dále vÅ¡echny funkce na naÄÃtánà z xml, majà vstupnÃm parametrem Ä. 1 XML soubor a druhým je cesta k hodnotÄ›.
Ukládánà dat do XML
Tato Äást Vás nauÄÃ, jak ukládat data do XML. V žádném pÅ™ÃpadÄ› ale nepÅ™episujte XML soubor stroje! Tato funkce se hodà pro tvorbu napÅ™Ãklad konfiguraÄnÃch souborů pro nÄ›jaký mod. K ukládánÃ/modifikaci XML dat sloužà funkce zaÄÃnajÃcà slůvkem "setXML" a pokraÄujà pÅ™Ãponou datového typu. NarozdÃl od naÄÃtánÃ, zde hrajà datové typy důležitou roli - urÄujà v jakém tvaru bude co zapsáno.
Využijeme pÅ™edchozÃho pÅ™Ãkladu, s tÃm rozdÃlem, že teÄ naÄtené data uložÃme do jiného souboru.
12mujSkript = {};34-- ulozeni aktualni cesty k modu do lokalni promenne ktera plati pro tento soubor5local MDR = g_currentModDirectory;67function mujSkript.prerequisitesPresent(specializations)8 return true;9end;1011function mujSkript:load(xmlFile)12 --[[ Vytvoreni XML souboru ]]--13 local mojeXML = createXMLFile("mujXMLsoubor",MDR.."xmlSoubor.xml","mujSkript");14 --[[ Nacitani z XML stroje ]]--15 local cisel = Utils.getNoNil(getXMLInt(xmlFile,"vehicle.mujSkript#pocetCisel"),5);16 local hodnoty = {};17 local soucet = 0;18 local maxCislo;19 for i=1, cisel do20 if Utils.getNoNil(getXMLString(xmlFile,"vehicle.mujSkript.cislo"..i.."#type"),"tag") == "tag" then21 hodnoty[i] = getXMLInt(xmlFile,"vehicle.mujSkript.cislo"..i);22 else23 hodnoty[i] = getXMLFloat(xmlFile,"vehicle.mujSkript.cislo"..i.."#hodnota");24 end;25 print(i..". nactene cislo je "..hodnoty[i]);26 end;27 for i=1, cisel do28 if hodnoty[i] ~= nil then29 soucet = soucet + hodnoty[i];30 if i == 1 then31 maxCislo = hodnoty[i];32 end;33 if maxCislo < hodnoty[i] then34 maxCislo = hodnoty[i];35 end;36 if hodnoty[i] %2==0 then -- delitelnost37 setXMLFloat(mojeXML,"mujSkript.sude.cislo"..i.."",hodnoty[i]);38 else39 setXMLFloat(mojeXML,"mujSkript.liche.cislo"..i.."",hodnoty[i]);40 end;41 end;42 end;43 -- Novy XML soubor - zapisy44 setXMLString(mojeXML,"mujSkript#hlaska","Muj Skript Napsal Soubor");45 setXMLInt(mojeXML,"mujSkript.pocet",cisel);46 setXMLFloat(mojeXML,"mujSkript.maxCislo",maxCislo);47 setXMLFloat(mojeXML,"mujSkript.soucet",soucet);48 saveXMLFile(mojeXML);49end;5051function mujSkript:mouseEvent(posX, posY, isDown, isUp, button)52end;5354function mujSkript:keyEvent(unicode, sym, modifier, idDown)55end;5657function mujSkript:update(dt)58end;5960function mujSkript:updateTick(dt)61end;6263function mujSkript:draw()64end;
SamozÅ™ejmÄ› že si pak můžete pÅ™Ãklad upravit podle své libosti a upravovat ho. Dalo by se tak také naprogramovat poÄÃtadlo koupených/naÄtených strojů toho typu, kdy si vytvoÅ™Ãm mini XML soubor, z nÄ›j si pÅ™eÄtu kolik je pÅ™Ãstupů do souboru, soubor pÅ™epÃÅ¡u a uložÃm do nÄ›j nové ÄÃsla. DoporuÄuji vyzkouÅ¡et.