/* EQ2Emulator: Everquest II Server Emulator Copyright (C) 2007 EQ2EMulator Development Team (http://www.eq2emulator.net) This file is part of EQ2Emulator. EQ2Emulator is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. EQ2Emulator is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with EQ2Emulator. If not, see . */ #include "ConfigReader.h" #include "Log.h" ConfigReader::~ConfigReader(){ MStructs.lock(); DestroyStructs(); MStructs.unlock(); } PacketStruct* ConfigReader::getStructByVersion(const char* name, int16 version){ PacketStruct* packet = 0; PacketStruct* newpacket = 0; MStructs.lock(); vector* struct_versions = structs[string(name)]; if(struct_versions){ vector::iterator iter; for(iter = struct_versions->begin(); iter != struct_versions->end(); iter++){ packet = *iter; if(packet && packet->GetVersion() == version){ newpacket = new PacketStruct(packet, version); break; } } } MStructs.unlock(); if(!newpacket) LogWrite(PACKET__ERROR, 0, "Packet", "Could not find struct named '%s' with version: %i", name, version); return newpacket; } void ConfigReader::ReloadStructs(){ MStructs.lock(); DestroyStructs(); for(int32 i=0;i*>::iterator struct_iterator; for(struct_iterator=structs.begin();struct_iterator!=structs.end();struct_iterator++) { vector* versions = struct_iterator->second; vector::iterator version_iter; if(versions){ for(version_iter = versions->begin(); version_iter != versions->end(); version_iter++){ safe_delete(*version_iter); } } safe_delete(versions); } structs.clear(); } PacketStruct* ConfigReader::getStruct(const char* name, int16 version){ PacketStruct* latest_version = 0; PacketStruct* new_latest_version = 0; MStructs.lock(); vector* struct_versions = structs[string(name)]; if(struct_versions){ vector::iterator iter; for(iter = struct_versions->begin(); iter != struct_versions->end(); iter++){ if((*iter)->GetVersion() <= version && (!latest_version || (*iter)->GetVersion() > latest_version->GetVersion())) latest_version = *iter; } if (latest_version) { if (latest_version->GetOpcode() != OP_Unknown && (latest_version->GetOpcodeValue(version) == 0xFFFF || latest_version->GetOpcodeValue(version)==0xCDCD)) { LogWrite(PACKET__ERROR, 0, "Packet", "Could not find valid opcode for Packet Struct '%s' and client version %d", latest_version->GetName(), version); } else if(strlen(latest_version->GetOpcodeType()) == 0 || latest_version->GetOpcode() != OP_Unknown) new_latest_version = new PacketStruct(latest_version, version); } } MStructs.unlock(); if(!new_latest_version && !latest_version) LogWrite(PACKET__ERROR, 0, "Packet", "Could not find struct named '%s'", name); return new_latest_version; } int16 ConfigReader::GetStructVersion(const char* name, int16 version){ MStructs.lock(); vector* struct_versions = structs[string(name)]; int16 ret = 0; if(struct_versions){ vector::iterator iter; PacketStruct* latest_version = 0; for(iter = struct_versions->begin(); iter != struct_versions->end(); iter++){ if(!latest_version || ( (*iter)->GetVersion() > latest_version->GetVersion() && (*iter)->GetVersion() <= version) ) latest_version = *iter; } if(latest_version) ret = latest_version->GetVersion(); } MStructs.unlock(); return ret; } void ConfigReader::addStruct(const char* name, int16 version, PacketStruct* new_struct){ string strname(name); vector* struct_versions = structs[strname]; if(struct_versions) struct_versions->push_back(new_struct); else{ struct_versions = new vector; struct_versions->push_back(new_struct); structs[strname] = struct_versions; } } bool ConfigReader::LoadFile(const char* name){ load_files.push_back(name); return processXML_Elements(name); } bool ConfigReader::processXML_Elements(const char* fileName){ XMLNode xMainNode=XMLNode::openFileHelper(fileName,"EQ2Emulator"); if(xMainNode.isEmpty()) return false; for(int i=0;iSetName(struct_name); if(opcode_type) new_struct->SetOpcodeType(opcode_type); if(opcode_name){ if(!new_struct->SetOpcode(opcode_name)){ safe_delete(new_struct); continue; } } new_struct->SetVersion(version); loadDataStruct(new_struct, xMainNode.getChildNode("Struct", i)); addStruct(struct_name, version, new_struct); } return true; } void ConfigReader::loadDataStruct(PacketStruct* packet, XMLNode parentNode, bool array_packet){ for(int x=0;xGetVersion()); if(substruct_packet){ vector::iterator itr; vector* structs = substruct_packet->getStructs(); DataStruct* ds = 0; int i = 0; char tmp[10] = {0}; for(i=0;ibegin();itr!=structs->end();itr++) { ds = *itr; string new_name; if(array_packet) new_name = string(name).append("_").append(ds->GetStringName()); else new_name = string(name).append("_").append(ds->GetStringName()).append("_").append(tmp); DataStruct* ds2 = new DataStruct(new_name.c_str(), ds->GetType(),ds->GetLength(), ds->GetType2()); if(!array_packet && strlen(ds->GetArraySizeVariable()) > 1) ds2->SetArraySizeVariable(string(name).append("_").append(ds->GetArraySizeVariable()).append("_").append(tmp).c_str()); ds2->SetOversized(ds->GetOversized()); ds2->SetOversizedByte(ds->GetOversizedByte()); ds2->SetDefaultValue(ds->GetDefaultValue()); ds2->SetMaxArraySize(ds->GetMaxArraySize()); ds2->SetIfSetVariable(ds->GetIfSetVariable()); ds2->SetIfNotSetVariable(ds->GetIfNotSetVariable()); ds2->SetIfEqualsVariable(ds->GetIfEqualsVariable()); ds2->SetIfNotEqualsVariable(ds->GetIfNotEqualsVariable()); ds2->SetIfFlagNotSetVariable(ds->GetIfFlagNotSetVariable()); ds2->SetIfFlagSetVariable(ds->GetIfFlagSetVariable()); ds2->SetIsOptional(ds->IsOptional()); packet->add(ds2); } } if(!array_packet){ i--; substruct_packet->renameSubstructArray(name, i); //ds2->SetArraySizeVariable((char*)string(name).append("_").append(ds->GetArraySizeVariable()).append("_").append(tmp).c_str()); packet->addPacketArrays(substruct_packet); } safe_delete(substruct_packet); } continue; } else if(type && strncasecmp(type,"Array", 5)==0 && array_size){ PacketStruct* new_packet = new PacketStruct; new_packet->SetName(name); new_packet->IsSubPacket(true); new_packet->SetVersion(packet->GetVersion()); loadDataStruct(new_packet, parentNode.getChildNode("Data", x), true); packet->add(new_packet); } if(!name || !type) { LogWrite(MISC__WARNING, 0, "Misc", "Ignoring invalid Data Element, all elements must include at least an ElementName and Type!"); LogWrite(MISC__WARNING, 0, "Misc", "\tStruct: '%s', version: %i", parentNode.getAttribute("Name"), parentNode.getAttribute("ClientVersion")); continue; } DataStruct* ds = new DataStruct(name, type, num_size, type2); int8 oversized_value = 0; int8 oversized_byte_value = 255; if(oversized){ try{ oversized_value = atoi(oversized); } catch(...){} } if(oversized_byte){ try{ oversized_byte_value = atoi(oversized_byte); } catch(...){} } ds->SetOversizedByte(oversized_byte_value); ds->SetOversized(oversized_value); ds->SetMaxArraySize(max_array_size); if(array_size) ds->SetArraySizeVariable(array_size); ds->SetDefaultValue(byte_val); ds->SetIfSetVariable(if_variable); ds->SetIfNotSetVariable(if_not_variable); ds->SetIfEqualsVariable(if_equals_variable); ds->SetIfNotEqualsVariable(if_not_equals_variable); ds->SetIfFlagNotSetVariable(if_flag_not_set_variable); ds->SetIfFlagSetVariable(if_flag_set_variable); if (optional && strlen(optional) > 0 && (strcmp("true", optional) == 0 || strcmp("TRUE", optional) == 0 || strcmp("True", optional) == 0)) ds->SetIsOptional(true); packet->add(ds); } }