aboutsummaryrefslogtreecommitdiff
path: root/Minecraft.Client/Common/GameRules/GameRuleManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Minecraft.Client/Common/GameRules/GameRuleManager.cpp')
-rw-r--r--Minecraft.Client/Common/GameRules/GameRuleManager.cpp767
1 files changed, 767 insertions, 0 deletions
diff --git a/Minecraft.Client/Common/GameRules/GameRuleManager.cpp b/Minecraft.Client/Common/GameRules/GameRuleManager.cpp
new file mode 100644
index 00000000..0c6a7804
--- /dev/null
+++ b/Minecraft.Client/Common/GameRules/GameRuleManager.cpp
@@ -0,0 +1,767 @@
+#include "stdafx.h"
+#include "..\..\..\Minecraft.World\compression.h"
+#include "..\..\..\Minecraft.World\StringHelpers.h"
+#include "..\..\..\Minecraft.World\File.h"
+#include "..\..\..\Minecraft.World\compression.h"
+#include "..\DLC\DLCPack.h"
+#include "..\DLC\DLCLocalisationFile.h"
+#include "..\DLC\DLCGameRulesFile.h"
+#include "..\DLC\DLCGameRules.h"
+#include "..\DLC\DLCGameRulesHeader.h"
+#include "..\..\StringTable.h"
+#include "ConsoleGameRules.h"
+#include "GameRuleManager.h"
+
+WCHAR *GameRuleManager::wchTagNameA[] =
+{
+ L"", // eGameRuleType_Root
+ L"MapOptions", // eGameRuleType_LevelGenerationOptions
+ L"ApplySchematic", // eGameRuleType_ApplySchematic
+ L"GenerateStructure", // eGameRuleType_GenerateStructure
+ L"GenerateBox", // eGameRuleType_GenerateBox
+ L"PlaceBlock", // eGameRuleType_PlaceBlock
+ L"PlaceContainer", // eGameRuleType_PlaceContainer
+ L"PlaceSpawner", // eGameRuleType_PlaceSpawner
+ L"BiomeOverride", // eGameRuleType_BiomeOverride
+ L"StartFeature", // eGameRuleType_StartFeature
+ L"AddItem", // eGameRuleType_AddItem
+ L"AddEnchantment", // eGameRuleType_AddEnchantment
+ L"LevelRules", // eGameRuleType_LevelRules
+ L"NamedArea", // eGameRuleType_NamedArea
+ L"UseTile", // eGameRuleType_UseTileRule
+ L"CollectItem", // eGameRuleType_CollectItemRule
+ L"CompleteAll", // eGameRuleType_CompleteAllRule
+ L"UpdatePlayer", // eGameRuleType_UpdatePlayerRule
+};
+
+WCHAR *GameRuleManager::wchAttrNameA[] =
+{
+ L"descriptionName", // eGameRuleAttr_descriptionName
+ L"promptName", // eGameRuleAttr_promptName
+ L"dataTag", // eGameRuleAttr_dataTag
+ L"enchantmentId", // eGameRuleAttr_enchantmentId
+ L"enchantmentLevel", // eGameRuleAttr_enchantmentLevel
+ L"itemId", // eGameRuleAttr_itemId
+ L"quantity", // eGameRuleAttr_quantity
+ L"auxValue", // eGameRuleAttr_auxValue
+ L"slot", // eGameRuleAttr_slot
+ L"name", // eGameRuleAttr_name
+ L"food", // eGameRuleAttr_food
+ L"health", // eGameRuleAttr_health
+ L"tileId", // eGameRuleAttr_tileId
+ L"useCoords", // eGameRuleAttr_useCoords
+ L"seed", // eGameRuleAttr_seed
+ L"flatworld", // eGameRuleAttr_flatworld
+ L"filename", // eGameRuleAttr_filename
+ L"rot", // eGameRuleAttr_rot
+ L"data", // eGameRuleAttr_data
+ L"block", // eGameRuleAttr_block
+ L"entity", // eGameRuleAttr_entity
+ L"facing", // eGameRuleAttr_facing
+ L"edgeTile", // eGameRuleAttr_edgeTile
+ L"fillTile", // eGameRuleAttr_fillTile
+ L"skipAir", // eGameRuleAttr_skipAir
+ L"x", // eGameRuleAttr_x
+ L"x0", // eGameRuleAttr_x0
+ L"x1", // eGameRuleAttr_x1
+ L"y", // eGameRuleAttr_y
+ L"y0", // eGameRuleAttr_y0
+ L"y1", // eGameRuleAttr_y1
+ L"z", // eGameRuleAttr_z
+ L"z0", // eGameRuleAttr_z0
+ L"z1", // eGameRuleAttr_z1
+ L"chunkX", // eGameRuleAttr_chunkX
+ L"chunkZ", // eGameRuleAttr_chunkZ
+ L"yRot", // eGameRuleAttr_yRot
+ L"spawnX", // eGameRuleAttr_spawnX
+ L"spawnY", // eGameRuleAttr_spawnY
+ L"spawnZ", // eGameRuleAttr_spawnZ
+ L"orientation",
+ L"dimension",
+ L"topTileId", // eGameRuleAttr_topTileId
+ L"biomeId", // eGameRuleAttr_biomeId
+ L"feature", // eGameRuleAttr_feature
+};
+
+GameRuleManager::GameRuleManager()
+{
+ m_currentGameRuleDefinitions = NULL;
+ m_currentLevelGenerationOptions = NULL;
+}
+
+void GameRuleManager::loadGameRules(DLCPack *pack)
+{
+ StringTable *strings = NULL;
+
+ if(pack->doesPackContainFile(DLCManager::e_DLCType_LocalisationData,L"languages.loc"))
+ {
+ DLCLocalisationFile *localisationFile = (DLCLocalisationFile *)pack->getFile(DLCManager::e_DLCType_LocalisationData, L"languages.loc");
+ strings = localisationFile->getStringTable();
+ }
+
+ int gameRulesCount = pack->getDLCItemsCount(DLCManager::e_DLCType_GameRulesHeader);
+ for(int i = 0; i < gameRulesCount; ++i)
+ {
+ DLCGameRulesHeader *dlcHeader = (DLCGameRulesHeader *)pack->getFile(DLCManager::e_DLCType_GameRulesHeader, i);
+ DWORD dSize;
+ byte *dData = dlcHeader->getData(dSize);
+
+ LevelGenerationOptions *createdLevelGenerationOptions = new LevelGenerationOptions();
+ // = loadGameRules(dData, dSize); //, strings);
+
+ createdLevelGenerationOptions->setGrSource( dlcHeader );
+
+ readRuleFile(createdLevelGenerationOptions, dData, dSize, strings);
+
+ createdLevelGenerationOptions->setSrc( LevelGenerationOptions::eSrc_fromDLC );
+
+
+ //createdLevelGenerationOptions->setSrc( LevelGenerationOptions::eSrc_fromDLC );
+ dlcHeader->lgo = createdLevelGenerationOptions;
+ }
+
+ gameRulesCount = pack->getDLCItemsCount(DLCManager::e_DLCType_GameRules);
+ for (int i = 0; i < gameRulesCount; ++i)
+ {
+ DLCGameRulesFile *dlcFile = (DLCGameRulesFile *)pack->getFile(DLCManager::e_DLCType_GameRules, i);
+
+ DWORD dSize;
+ byte *dData = dlcFile->getData(dSize);
+
+ LevelGenerationOptions *createdLevelGenerationOptions = new LevelGenerationOptions();
+ // = loadGameRules(dData, dSize); //, strings);
+
+ createdLevelGenerationOptions->setGrSource( new JustGrSource() );
+ readRuleFile(createdLevelGenerationOptions, dData, dSize, strings);
+
+ createdLevelGenerationOptions->setSrc( LevelGenerationOptions::eSrc_tutorial );
+
+ //createdLevelGenerationOptions->set_DLCGameRulesFile( dlcFile );
+
+ createdLevelGenerationOptions->setLoadedData();
+ }
+}
+
+LevelGenerationOptions *GameRuleManager::loadGameRules(byte *dIn, UINT dSize)
+{
+ LevelGenerationOptions *lgo = new LevelGenerationOptions();
+ lgo->setGrSource( new JustGrSource() );
+ lgo->setSrc( LevelGenerationOptions::eSrc_fromSave );
+ loadGameRules(lgo, dIn, dSize);
+ lgo->setLoadedData();
+ return lgo;
+}
+
+// 4J-JEV: Reverse of saveGameRules.
+void GameRuleManager::loadGameRules(LevelGenerationOptions *lgo, byte *dIn, UINT dSize)
+{
+ app.DebugPrintf("GameRuleManager::LoadingGameRules:\n");
+
+ ByteArrayInputStream bais( byteArray(dIn,dSize) );
+ DataInputStream dis(&bais);
+
+ // Read file header.
+
+ //dis.readInt(); // File Size
+
+ short version = dis.readShort();
+ assert( 0x1 == version );
+ app.DebugPrintf("\tversion=%d.\n", version);
+
+ for (int i = 0; i < 8; i++) dis.readByte();
+
+ BYTE compression_type = dis.readByte();
+
+ app.DebugPrintf("\tcompressionType=%d.\n", compression_type);
+
+ UINT compr_len, decomp_len;
+ compr_len = dis.readInt();
+ decomp_len = dis.readInt();
+
+ app.DebugPrintf("\tcompr_len=%d.\n\tdecomp_len=%d.\n", compr_len, decomp_len);
+
+
+ // Decompress File Body
+
+ byteArray content(new BYTE[decomp_len], decomp_len),
+ compr_content(new BYTE[compr_len], compr_len);
+ dis.read(compr_content);
+
+ Compression::getCompression()->SetDecompressionType( (Compression::ECompressionTypes)compression_type );
+ Compression::getCompression()->DecompressLZXRLE( content.data, &content.length,
+ compr_content.data, compr_content.length);
+ Compression::getCompression()->SetDecompressionType( SAVE_FILE_PLATFORM_LOCAL );
+
+ dis.close();
+ bais.close();
+
+ delete [] compr_content.data;
+
+ ByteArrayInputStream bais2( content );
+ DataInputStream dis2( &bais2 );
+
+ // Read StringTable.
+ byteArray bStringTable;
+ bStringTable.length = dis2.readInt();
+ bStringTable.data = new BYTE[ bStringTable.length ];
+ dis2.read(bStringTable);
+ StringTable *strings = new StringTable(bStringTable.data, bStringTable.length);
+
+ // Read RuleFile.
+ byteArray bRuleFile;
+ bRuleFile.length = content.length - bStringTable.length;
+ bRuleFile.data = new BYTE[ bRuleFile.length ];
+ dis2.read(bRuleFile);
+
+ // 4J-JEV: I don't believe that the path-name is ever used.
+ //DLCGameRulesFile *dlcgr = new DLCGameRulesFile(L"__PLACEHOLDER__");
+ //dlcgr->addData(bRuleFile.data,bRuleFile.length);
+
+ if (readRuleFile(lgo, bRuleFile.data, bRuleFile.length, strings))
+ {
+ // Set current gen options and ruleset.
+ //createdLevelGenerationOptions->setFromSaveGame(true);
+ lgo->setSrc(LevelGenerationOptions::eSrc_fromSave);
+ setLevelGenerationOptions( lgo );
+ //m_currentGameRuleDefinitions = lgo->getRequiredGameRules();
+ }
+ else
+ {
+ delete lgo;
+ }
+
+ //delete [] content.data;
+
+ // Close and return.
+ dis2.close();
+ bais2.close();
+
+ return ;
+}
+
+// 4J-JEV: Reverse of loadGameRules.
+void GameRuleManager::saveGameRules(byte **dOut, UINT *dSize)
+{
+ if (m_currentGameRuleDefinitions == NULL &&
+ m_currentLevelGenerationOptions == NULL)
+ {
+ app.DebugPrintf("GameRuleManager:: Nothing here to save.");
+ *dOut = NULL;
+ *dSize = 0;
+ return;
+ }
+
+ app.DebugPrintf("GameRuleManager::saveGameRules:\n");
+
+ // Initialise output stream.
+ ByteArrayOutputStream baos;
+ DataOutputStream dos(&baos);
+
+ // Write header.
+
+ // VERSION NUMBER
+ dos.writeShort( 0x1 ); // version_number
+
+ // Write 8 bytes of empty space in case we need them later.
+ // Mainly useful for the ones we save embedded in game saves.
+ for (UINT i = 0; i < 8; i++)
+ dos.writeByte(0x0);
+
+ dos.writeByte(APPROPRIATE_COMPRESSION_TYPE); // m_compressionType
+
+ // -- START COMPRESSED -- //
+ ByteArrayOutputStream compr_baos;
+ DataOutputStream compr_dos(&compr_baos);
+
+ if (m_currentGameRuleDefinitions == NULL)
+ {
+ compr_dos.writeInt( 0 ); // numStrings for StringTable
+ compr_dos.writeInt( version_number );
+ compr_dos.writeByte(Compression::eCompressionType_None); // compression type
+ for (int i=0; i<2; i++) compr_dos.writeByte(0x0); // Padding.
+ compr_dos.writeInt( 0 ); // StringLookup.length
+ compr_dos.writeInt( 0 ); // SchematicFiles.length
+ compr_dos.writeInt( 0 ); // XmlObjects.length
+ }
+ else
+ {
+ StringTable *st = m_currentGameRuleDefinitions->getStringTable();
+
+ if (st == NULL)
+ {
+ app.DebugPrintf("GameRuleManager::saveGameRules: StringTable == NULL!");
+ }
+ else
+ {
+ // Write string table.
+ byteArray stba;
+ m_currentGameRuleDefinitions->getStringTable()->getData(&stba.data, &stba.length);
+ compr_dos.writeInt( stba.length );
+ compr_dos.write( stba );
+
+ // Write game rule file to second
+ // buffer and generate string lookup.
+ writeRuleFile(&compr_dos);
+ }
+ }
+
+ // Compress compr_dos and write to dos.
+ byteArray compr_ba(new BYTE[ compr_baos.buf.length ], compr_baos.buf.length);
+ Compression::getCompression()->CompressLZXRLE( compr_ba.data, &compr_ba.length,
+ compr_baos.buf.data, compr_baos.buf.length );
+
+ app.DebugPrintf("\tcompr_ba.length=%d.\n\tcompr_baos.buf.length=%d.\n",
+ compr_ba.length, compr_baos.buf.length );
+
+ dos.writeInt( compr_ba.length ); // Write length
+ dos.writeInt( compr_baos.buf.length );
+ dos.write(compr_ba);
+
+ delete [] compr_ba.data;
+
+ compr_dos.close();
+ compr_baos.close();
+ // -- END COMPRESSED -- //
+
+ // return
+ *dSize = baos.buf.length;
+ *dOut = baos.buf.data;
+
+ baos.buf.data = NULL;
+
+ dos.close(); baos.close();
+}
+
+// 4J-JEV: Reverse of readRuleFile.
+void GameRuleManager::writeRuleFile(DataOutputStream *dos)
+{
+ // Write Header
+ dos->writeShort(version_number); // Version number.
+ dos->writeByte(Compression::eCompressionType_None); // compression type
+ for (int i=0; i<8; i++) dos->writeBoolean(false); // Padding.
+
+ // Write string lookup.
+ int numStrings = ConsoleGameRules::eGameRuleType_Count + ConsoleGameRules::eGameRuleAttr_Count;
+ dos->writeInt(numStrings);
+ for (int i = 0; i < ConsoleGameRules::eGameRuleType_Count; i++) dos->writeUTF( wchTagNameA[i] );
+ for (int i = 0; i < ConsoleGameRules::eGameRuleAttr_Count; i++) dos->writeUTF( wchAttrNameA[i] );
+
+ // Write schematic files.
+ unordered_map<wstring, ConsoleSchematicFile *> *files;
+ files = getLevelGenerationOptions()->getUnfinishedSchematicFiles();
+ dos->writeInt( files->size() );
+ for (AUTO_VAR(it, files->begin()); it != files->end(); it++)
+ {
+ wstring filename = it->first;
+ ConsoleSchematicFile *file = it->second;
+
+ ByteArrayOutputStream fileBaos;
+ DataOutputStream fileDos(&fileBaos);
+ file->save(&fileDos);
+
+ dos->writeUTF(filename);
+ //dos->writeInt(file->m_data.length);
+ dos->writeInt(fileBaos.buf.length);
+ dos->write((byteArray)fileBaos.buf);
+
+ fileDos.close(); fileBaos.close();
+ }
+
+ // Write xml objects.
+ dos->writeInt( 2 ); // numChildren
+ m_currentLevelGenerationOptions->write(dos);
+ m_currentGameRuleDefinitions->write(dos);
+}
+
+bool GameRuleManager::readRuleFile(LevelGenerationOptions *lgo, byte *dIn, UINT dSize, StringTable *strings) //(DLCGameRulesFile *dlcFile, StringTable *strings)
+{
+ bool levelGenAdded = false;
+ bool gameRulesAdded = false;
+ LevelGenerationOptions *levelGenerator = lgo;//new LevelGenerationOptions();
+ LevelRuleset *gameRules = new LevelRuleset();
+
+ //DWORD dwLen = 0;
+ //PBYTE pbData = dlcFile->getData(dwLen);
+ //byteArray data(pbData,dwLen);
+
+ byteArray data(dIn, dSize);
+ ByteArrayInputStream bais(data);
+ DataInputStream dis(&bais);
+
+ // Read File.
+
+ // version_number
+ __int64 version = dis.readShort();
+ unsigned char compressionType = 0;
+ if(version == 0)
+ {
+ for (int i = 0; i < 14; i++) dis.readByte(); // Read padding.
+ }
+ else
+ {
+ compressionType = dis.readByte();
+
+ // Read the spare bytes we inserted for future use
+ for(int i = 0; i < 8; ++i) dis.readBoolean();
+ }
+
+ ByteArrayInputStream *contentBais = NULL;
+ DataInputStream *contentDis = NULL;
+
+ if(compressionType == Compression::eCompressionType_None)
+ {
+ // No compression
+ // No need to read buffer size, as we can read the stream as it is;
+ app.DebugPrintf("De-compressing game rules with: None\n");
+ contentDis = &dis;
+ }
+ else
+ {
+ unsigned int uncompressedSize = dis.readInt();
+ unsigned int compressedSize = dis.readInt();
+ byteArray compressedBuffer(compressedSize);
+ dis.read(compressedBuffer);
+
+ byteArray decompressedBuffer = byteArray(uncompressedSize);
+
+ switch(compressionType)
+ {
+ case Compression::eCompressionType_None:
+ memcpy(decompressedBuffer.data, compressedBuffer.data, uncompressedSize);
+ break;
+
+ case Compression::eCompressionType_RLE:
+ app.DebugPrintf("De-compressing game rules with: RLE\n");
+ Compression::getCompression()->Decompress( decompressedBuffer.data, &decompressedBuffer.length, compressedBuffer.data, compressedSize);
+ break;
+
+ default:
+ app.DebugPrintf("De-compressing game rules.");
+#ifndef _CONTENT_PACKAGE
+ assert( compressionType == APPROPRIATE_COMPRESSION_TYPE );
+#endif
+ // 4J-JEV: DecompressLZXRLE uses the correct platform specific compression type. (need to assert that the data is compressed with it though).
+ Compression::getCompression()->DecompressLZXRLE(decompressedBuffer.data, &decompressedBuffer.length, compressedBuffer.data, compressedSize);
+ break;
+/* 4J-JEV:
+ Each platform has only 1 method of compression, 'compression.h' file deals with it.
+
+ case Compression::eCompressionType_LZXRLE:
+ app.DebugPrintf("De-compressing game rules with: LZX+RLE\n");
+ Compression::getCompression()->DecompressLZXRLE( decompressedBuffer.data, &uncompressedSize, compressedBuffer.data, compressedSize);
+ break;
+ default:
+ app.DebugPrintf("Invalid compression type %d found\n", compressionType);
+ __debugbreak();
+
+ delete [] compressedBuffer.data; delete [] decompressedBuffer.data;
+ dis.close(); bais.reset();
+
+ if(!gameRulesAdded) delete gameRules;
+ return false;
+ */
+ };
+
+ delete [] compressedBuffer.data;
+
+ contentBais = new ByteArrayInputStream(decompressedBuffer);
+ contentDis = new DataInputStream(contentBais);
+ }
+
+ // string lookup.
+ UINT numStrings = contentDis->readInt();
+ vector<wstring> tagsAndAtts;
+ for (UINT i = 0; i < numStrings; i++)
+ tagsAndAtts.push_back( contentDis->readUTF() );
+
+ unordered_map<int, ConsoleGameRules::EGameRuleType> tagIdMap;
+ for(int type = (int)ConsoleGameRules::eGameRuleType_Root; type < (int)ConsoleGameRules::eGameRuleType_Count; ++type)
+ {
+ for(UINT i = 0; i < numStrings; ++i)
+ {
+ if(tagsAndAtts[i].compare(wchTagNameA[type]) == 0)
+ {
+ tagIdMap.insert( unordered_map<int, ConsoleGameRules::EGameRuleType>::value_type(i, (ConsoleGameRules::EGameRuleType)type) );
+ break;
+ }
+ }
+ }
+
+ // 4J-JEV: TODO: As yet unused.
+ /*
+ unordered_map<int, ConsoleGameRules::EGameRuleAttr> attrIdMap;
+ for(int attr = (int)ConsoleGameRules::eGameRuleAttr_descriptionName; attr < (int)ConsoleGameRules::eGameRuleAttr_Count; ++attr)
+ {
+ for (UINT i = 0; i < numStrings; i++)
+ {
+ if (tagsAndAtts[i].compare(wchAttrNameA[attr]) == 0)
+ {
+ tagIdMap.insert( unordered_map<int, ConsoleGameRules::EGameRuleAttr>::value_type(i , (ConsoleGameRules::EGameRuleAttr)attr) );
+ break;
+ }
+ }
+ }*/
+
+ // subfile
+ UINT numFiles = contentDis->readInt();
+ for (UINT i = 0; i < numFiles; i++)
+ {
+ wstring sFilename = contentDis->readUTF();
+ int length = contentDis->readInt();
+ byteArray ba( length );
+
+ contentDis->read(ba);
+
+ levelGenerator->loadSchematicFile(sFilename, ba.data, ba.length);
+
+ }
+
+ LEVEL_GEN_ID lgoID = LEVEL_GEN_ID_NULL;
+
+ // xml objects
+ UINT numObjects = contentDis->readInt();
+ for(UINT i = 0; i < numObjects; ++i)
+ {
+ int tagId = contentDis->readInt();
+ ConsoleGameRules::EGameRuleType tagVal = ConsoleGameRules::eGameRuleType_Invalid;
+ AUTO_VAR(it,tagIdMap.find(tagId));
+ if(it != tagIdMap.end()) tagVal = it->second;
+
+ GameRuleDefinition *rule = NULL;
+
+ if(tagVal == ConsoleGameRules::eGameRuleType_LevelGenerationOptions)
+ {
+ rule = levelGenerator;
+ levelGenAdded = true;
+ //m_levelGenerators.addLevelGenerator(L"",levelGenerator);
+ lgoID = addLevelGenerationOptions(levelGenerator);
+ levelGenerator->loadStringTable(strings);
+ }
+ else if(tagVal == ConsoleGameRules::eGameRuleType_LevelRules)
+ {
+ rule = gameRules;
+ gameRulesAdded = true;
+ m_levelRules.addLevelRule(L"",gameRules);
+ levelGenerator->setRequiredGameRules(gameRules);
+ gameRules->loadStringTable(strings);
+ }
+
+ readAttributes(contentDis, &tagsAndAtts, rule);
+ readChildren(contentDis, &tagsAndAtts, &tagIdMap, rule);
+ }
+
+ if(compressionType != 0)
+ {
+ // Not default
+ contentDis->close();
+ if(contentBais != NULL) delete contentBais;
+ delete contentDis;
+ }
+
+ dis.close();
+ bais.reset();
+
+ //if(!levelGenAdded) { delete levelGenerator; levelGenerator = NULL; }
+ if(!gameRulesAdded) delete gameRules;
+
+ return true;
+ //return levelGenerator;
+}
+
+LevelGenerationOptions *GameRuleManager::readHeader(DLCGameRulesHeader *grh)
+{
+ LevelGenerationOptions *out =
+ new LevelGenerationOptions();
+
+
+ out->setSrc(LevelGenerationOptions::eSrc_fromDLC);
+ out->setGrSource(grh);
+ addLevelGenerationOptions(out);
+
+ return out;
+}
+
+void GameRuleManager::readAttributes(DataInputStream *dis, vector<wstring> *tagsAndAtts, GameRuleDefinition *rule)
+{
+ int numAttrs = dis->readInt();
+ for (UINT att = 0; att < numAttrs; ++att)
+ {
+ int attID = dis->readInt();
+ wstring value = dis->readUTF();
+
+ if(rule != NULL) rule->addAttribute(tagsAndAtts->at(attID),value);
+ }
+}
+
+void GameRuleManager::readChildren(DataInputStream *dis, vector<wstring> *tagsAndAtts, unordered_map<int, ConsoleGameRules::EGameRuleType> *tagIdMap, GameRuleDefinition *rule)
+{
+ int numChildren = dis->readInt();
+ for(UINT child = 0; child < numChildren; ++child)
+ {
+ int tagId = dis->readInt();
+ ConsoleGameRules::EGameRuleType tagVal = ConsoleGameRules::eGameRuleType_Invalid;
+ AUTO_VAR(it,tagIdMap->find(tagId));
+ if(it != tagIdMap->end()) tagVal = it->second;
+
+ GameRuleDefinition *childRule = NULL;
+ if(rule != NULL) childRule = rule->addChild(tagVal);
+
+ readAttributes(dis,tagsAndAtts,childRule);
+ readChildren(dis,tagsAndAtts,tagIdMap,childRule);
+ }
+}
+
+void GameRuleManager::processSchematics(LevelChunk *levelChunk)
+{
+ if(getLevelGenerationOptions() != NULL)
+ {
+ LevelGenerationOptions *levelGenOptions = getLevelGenerationOptions();
+ levelGenOptions->processSchematics(levelChunk);
+ }
+}
+
+void GameRuleManager::processSchematicsLighting(LevelChunk *levelChunk)
+{
+ if(getLevelGenerationOptions() != NULL)
+ {
+ LevelGenerationOptions *levelGenOptions = getLevelGenerationOptions();
+ levelGenOptions->processSchematicsLighting(levelChunk);
+ }
+}
+
+void GameRuleManager::loadDefaultGameRules()
+{
+#ifdef _XBOX
+#ifdef _TU_BUILD
+ wstring fileRoot = L"UPDATE:\\res\\GameRules\\Tutorial.pck";
+#else
+ wstring fileRoot = L"GAME:\\res\\TitleUpdate\\GameRules\\Tutorial.pck";
+#endif
+ File packedTutorialFile(fileRoot);
+ if(loadGameRulesPack(&packedTutorialFile))
+ {
+ m_levelGenerators.getLevelGenerators()->at(0)->setWorldName(app.GetString(IDS_PLAY_TUTORIAL));
+ //m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName(L"Tutorial");
+ m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME));
+ }
+
+#ifndef _CONTENT_PACKAGE
+ // 4J Stu - Remove these just now
+ //File testRulesPath(L"GAME:\\GameRules");
+ //vector<File *> *packFiles = testRulesPath.listFiles();
+
+ //for(AUTO_VAR(it,packFiles->begin()); it != packFiles->end(); ++it)
+ //{
+ // loadGameRulesPack(*it);
+ //}
+ //delete packFiles;
+#endif
+
+#else // _XBOX
+
+ wstring fpTutorial = L"Tutorial.pck";
+ if(app.getArchiveFileSize(fpTutorial) >= 0)
+ {
+ DLCPack *pack = new DLCPack(L"",0xffffffff);
+ DWORD dwFilesProcessed = 0;
+ if ( app.m_dlcManager.readDLCDataFile(dwFilesProcessed,fpTutorial,pack,true) )
+ {
+ app.m_dlcManager.addPack(pack);
+ m_levelGenerators.getLevelGenerators()->at(0)->setWorldName(app.GetString(IDS_PLAY_TUTORIAL));
+ m_levelGenerators.getLevelGenerators()->at(0)->setDefaultSaveName(app.GetString(IDS_TUTORIALSAVENAME));
+ }
+ else delete pack;
+ }
+ /*StringTable *strings = new StringTable(baStrings.data, baStrings.length);
+ LevelGenerationOptions *lgo = new LevelGenerationOptions();
+ lgo->setGrSource( new JustGrSource() );
+ lgo->setSrc( LevelGenerationOptions::eSrc_tutorial );
+ readRuleFile(lgo, tutorial.data, tutorial.length, strings);
+ lgo->setLoadedData();*/
+
+#endif
+}
+
+bool GameRuleManager::loadGameRulesPack(File *path)
+{
+ bool success = false;
+#ifdef _XBOX
+ if(path->exists())
+ {
+ DLCPack *pack = new DLCPack(L"",0xffffffff);
+ DWORD dwFilesProcessed = 0;
+ if( app.m_dlcManager.readDLCDataFile(dwFilesProcessed, path->getPath(),pack))
+ {
+ app.m_dlcManager.addPack(pack);
+ success = true;
+ }
+ else
+ {
+ delete pack;
+ }
+ }
+#endif
+ return success;
+}
+
+void GameRuleManager::setLevelGenerationOptions(LevelGenerationOptions *levelGen)
+{
+ m_currentGameRuleDefinitions = NULL;
+ m_currentLevelGenerationOptions = levelGen;
+
+ if(m_currentLevelGenerationOptions != NULL && m_currentLevelGenerationOptions->requiresGameRules() )
+ {
+ m_currentGameRuleDefinitions = m_currentLevelGenerationOptions->getRequiredGameRules();
+ }
+
+ if(m_currentLevelGenerationOptions != NULL)
+ m_currentLevelGenerationOptions->reset_start();
+}
+
+LPCWSTR GameRuleManager::GetGameRulesString(const wstring &key)
+{
+ if(m_currentGameRuleDefinitions != NULL && !key.empty() )
+ {
+ return m_currentGameRuleDefinitions->getString(key);
+ }
+ else
+ {
+ return L"";
+ }
+}
+
+LEVEL_GEN_ID GameRuleManager::addLevelGenerationOptions(LevelGenerationOptions *lgo)
+{
+ vector<LevelGenerationOptions *> *lgs = m_levelGenerators.getLevelGenerators();
+
+ for (int i = 0; i<lgs->size(); i++)
+ if (lgs->at(i) == lgo)
+ return i;
+
+ lgs->push_back(lgo);
+ return lgs->size() - 1;
+}
+
+void GameRuleManager::unloadCurrentGameRules()
+{
+ if (m_currentLevelGenerationOptions != NULL)
+ {
+ if (m_currentGameRuleDefinitions != NULL
+ && m_currentLevelGenerationOptions->isFromSave())
+ m_levelRules.removeLevelRule( m_currentGameRuleDefinitions );
+
+ if (m_currentLevelGenerationOptions->isFromSave())
+ {
+ m_levelGenerators.removeLevelGenerator( m_currentLevelGenerationOptions );
+
+ delete m_currentLevelGenerationOptions;
+ }
+ else if (m_currentLevelGenerationOptions->isFromDLC())
+ {
+ m_currentLevelGenerationOptions->reset_finish();
+ }
+ }
+
+ m_currentGameRuleDefinitions = NULL;
+ m_currentLevelGenerationOptions = NULL;
+}