bool Mineserver::init() { // expand '~', '~user' in next vars bool error = false; const char* const vars[] = { "system.path.data", "system.path.plugins", "system.path.home", "system.pid_file", }; for (size_t i = 0; i < sizeof(vars) / sizeof(vars[0]); i++) { ConfigNode::Ptr node = config()->mData(vars[i]); if (!node) { LOG2(ERROR, std::string("Variable is missing: ") + vars[i]); error = true; continue; } if (node->type() != CONFIG_NODE_STRING) { LOG2(ERROR, std::string("Variable is not string: ") + vars[i]); error = true; continue; } const std::string newvalue = relativeToAbsolute(node->sData()); node->setData(newvalue); LOG2(INFO, std::string(vars[i]) + " = \"" + newvalue + "\""); } if (error) { return false; } const std::string str = config()->sData("system.path.home"); #ifdef WIN32 if (_chdir(str.c_str()) != 0) #else if (chdir(str.c_str()) != 0) #endif { LOG2(ERROR, "Failed to change working directory to: " + str); return false; } // Write PID to file std::ofstream pid_out((config()->sData("system.pid_file")).c_str()); if (!pid_out.fail()) { #ifdef WIN32 pid_out << _getpid(); #else pid_out << getpid(); #endif } pid_out.close(); // screen::init() needs m_plugin m_plugin = new Plugin; init_plugin_api(); if (config()->bData("system.interface.use_cli")) { // Init our Screen screen()->init(VERSION); } LOG2(INFO, "Welcome to Mineserver v" + VERSION); MapGen* mapgen = new MapGen; MapGen* nethergen = new NetherGen; MapGen* heavengen = new HeavenGen; MapGen* biomegen = new BiomeGen; MapGen* eximgen = new EximGen; m_mapGenNames.push_back(mapgen); m_mapGenNames.push_back(nethergen); m_mapGenNames.push_back(heavengen); m_mapGenNames.push_back(biomegen); m_mapGenNames.push_back(eximgen); m_saveInterval = m_config->iData("map.save_interval"); m_only_helmets = m_config->bData("system.armour.helmet_strict"); m_pvp_enabled = m_config->bData("system.pvp.enabled"); m_damage_enabled = m_config->bData("system.damage.enabled"); const char* key = "map.storage.nbt.directories"; // Prefix for worlds config if (m_config->has(key) && (m_config->type(key) == CONFIG_NODE_LIST)) { std::list<std::string> tmp = m_config->mData(key)->keys(); int n = 0; for (std::list<std::string>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { m_map.push_back(new Map()); Physics* phy = new Physics; phy->map = n; m_physics.push_back(phy); int k = m_config->iData((std::string(key) + ".") + (*it)); if ((uint32_t)k >= m_mapGenNames.size()) { std::ostringstream s; s << "Error! Mapgen number " << k << " in config. " << m_mapGenNames.size() << " Mapgens known"; LOG2(INFO, s.str()); } // WARNING: if k is too big this will be an access error! -- louisdx MapGen* m = m_mapGenNames[k]; m_mapGen.push_back(m); n++; } } else { LOG2(WARNING, "Cannot find map.storage.nbt.directories.*"); } if (m_map.size() == 0) { LOG2(ERROR, "No worlds in Config!"); return false; } m_chat = new Chat; m_furnaceManager = new FurnaceManager; m_packetHandler = new PacketHandler; m_inventory = new Inventory(m_config->sData("system.path.data") + '/' + "recipes", ".recipe", "ENABLED_RECIPES.cfg"); m_mobs = new Mobs; return true; }
bool ConfigParser::parse(std::istream& data, ConfigNode::Ptr ptr) { ConfigScanner scanner; ConfigLexer lexer(scanner); ConfigNode::Ptr root = ptr; data.seekg(0, std::ios::end); const size_t data_size = size_t(data.tellg()); data.seekg(0, std::ios::beg); char* buf = new char[data_size]; data.read(buf, data_size); std::string data_str(buf, data_size); delete[] buf; if (!scanner.read(data_str)) { std::cerr << "Couldn't read data!\n"; return false; } int token_type; std::string token_data; std::string token_label; std::stack<ConfigNode::Ptr> nodeStack; ConfigNode::Ptr currentNode = root; nodeStack.push(currentNode); while (lexer.get_token(token_type, token_data)) { if (!token_type) { std::cerr << "Unrecognised data!\n"; return false; } // Include other files only if we're in the root node if (token_type == CONFIG_TOKEN_ENTITY && token_data == "include" && currentNode == root) { int tmp_type; std::string tmp_data; lexer.get_token(tmp_type, tmp_data); if (tmp_type == CONFIG_TOKEN_STRING) { if (m_includes >= MAX_INCLUDES) { std::cerr << "reached maximum number of include directives: " << m_includes << "\n"; return false; } // allow only filename without path if ((tmp_data.find('/') != std::string::npos) || (tmp_data.find('\\') != std::string::npos)) { std::cerr << "include directive accepts only filename: " << tmp_data << "\n"; return false; } // prepend home path const std::string var = "system.path.home"; const ConfigNode::Ptr node = root->get(var, false); std::string home; if (!node || (home = node->sData()).empty()) { std::cerr << "include directive is not allowed before: " << var << "\n"; return false; } tmp_data = relativeToAbsolute(home) + PATH_SEPARATOR + tmp_data; if (!parse(tmp_data, root)) { return false; } m_includes++; continue; } else { lexer.put_token(tmp_type, tmp_data); } } if (token_type == CONFIG_TOKEN_ENTITY || token_type == CONFIG_TOKEN_LABEL) { token_label = token_data; } else if (token_type == CONFIG_TOKEN_OPERATOR_ASSIGN) { if (currentNode != root) { currentNode->clear(); } } else if (token_type == CONFIG_TOKEN_BOOLEAN) { ConfigNode::Ptr newNode(!token_label.empty() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode)); newNode->setData(token_data == "true"); if (!token_label.empty()) { currentNode->set(token_label, newNode, true); token_label.clear(); } else { currentNode->add(newNode); } } else if (token_type == CONFIG_TOKEN_STRING) { ConfigNode::Ptr newNode(!token_label.empty() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode)); newNode->setData(token_data); if (!token_label.empty()) { currentNode->set(token_label, newNode, true); token_label.clear(); } else { currentNode->add(newNode); } } else if (token_type == CONFIG_TOKEN_NUMBER) { ConfigNode::Ptr newNode(token_label.size() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode)); newNode->setData((double)::atof(token_data.c_str())); if (!token_label.empty()) { currentNode->set(token_label, newNode, true); token_label.clear(); } else { currentNode->add(newNode); } } else if (token_type == CONFIG_TOKEN_LIST_OPEN) { ConfigNode::Ptr newNode(token_label.size() && currentNode->has(token_label) ? currentNode->get(token_label) : ConfigNode::Ptr(new ConfigNode)); newNode->setType(CONFIG_NODE_LIST); if (!token_label.empty()) { currentNode->set(token_label, newNode, true); newNode = currentNode->get(token_label, true); token_label.clear(); } else { currentNode->add(newNode); } nodeStack.push(currentNode); currentNode = newNode; } else if (token_type == CONFIG_TOKEN_LIST_CLOSE) { currentNode = nodeStack.top(); nodeStack.pop(); } } return true; }