When exiting a room where one was host, server sends a REMOVE_TEAM for the local team. It appears that this loop would not break in that case. Add a log message and a break. (I've hit a frozen frontend twice now)
/*
* Hedgewars, a free turn based strategy game
* Copyright (c) 2004-2012 Andrey Korotaev <unC0Rr@gmail.com>
*
* This program 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; version 2 of the License
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*/
/**
* @file
* @brief MapModel class implementation
*/
#include "MapModel.h"
void MapModel::loadMaps()
{
// this method resets the contents of this model (important to know for views).
beginResetModel();
// we'll need the DataManager a few times, so let's get a reference to it
DataManager & datamgr = DataManager::instance();
// fetch list of available maps
QStringList maps =
datamgr.entryList("Maps", QDir::AllDirs | QDir::NoDotAndDotDot);
// empty list, so that we can (re)fill it
QStandardItemModel::clear();
QList<QStandardItem *> genMaps;
QList<QStandardItem *> missionMaps;
QList<QStandardItem *> staticMaps;
// add generated/handdrawn maps to list
// TODO: icons for these
genMaps.append(
infoToItem(QIcon(), QComboBox::tr("generated map..."), GeneratedMap, "+rnd+"));
genMaps.append(
infoToItem(QIcon(), QComboBox::tr("generated maze..."), GeneratedMaze, "+maze+"));
genMaps.append(
infoToItem(QIcon(), QComboBox::tr("hand drawn map..."), HandDrawnMap, "+drawn+"));
// only 2 map relate files are relevant:
// - the cfg file that contains the settings/info of the map
// - the lua file - if it exists it's a mission, otherwise it isn't
QFile mapLuaFile;
QFile mapCfgFile;
// add mission/static maps to lists
foreach (QString map, maps)
{
mapCfgFile.setFileName(
datamgr.findFileForRead(QString("Maps/%1/map.cfg").arg(map)));
mapLuaFile.setFileName(
datamgr.findFileForRead(QString("Maps/%1/map.lua").arg(map)));
if (mapCfgFile.open(QFile::ReadOnly))
{
QString caption;
QString theme;
quint32 limit = 0;
QString scheme;
QString weapons;
// if there is a lua file for this map, then it's a mission
bool isMission = mapLuaFile.exists();
MapType type = isMission?MissionMap:StaticMap;
// load map info from file
QTextStream input(&mapCfgFile);
input >> theme;
input >> limit;
if (isMission) { // scheme and weapons are only relevant for missions
input >> scheme;
input >> weapons;
}
mapCfgFile.close();
// let's use some semi-sane hedgehog limit, rather than none
if (limit == 0)
limit = 18;
// the default scheme/weaponset for missions.
// if empty we assume the map sets these internally -> locked
if (isMission)
{
if (scheme.isEmpty())
scheme = "locked";
else
scheme.replace("_", " ");
if (weapons.isEmpty())
weapons = "locked";
else
weapons.replace("_", " ");
}
// add a mission caption prefix to missions
if (isMission)
{
// TODO: icon
caption = QComboBox::tr("Mission") + ": " + map;
}
else
caption = map;
// we know everything there is about the map, let's get am item for it
QStandardItem * item = infoToItem(
QIcon(), caption, type, map, theme, limit, scheme, weapons);
// append item to the list
if (isMission)
missionMaps.append(item);
else
staticMaps.append(item);
}
}
// define a separator item
QStandardItem separator("---");
separator.setData(QLatin1String("separator"), Qt::AccessibleDescriptionRole);
separator.setFlags(separator.flags() & ~( Qt::ItemIsEnabled | Qt::ItemIsSelectable ) );
// create list:
// generated+handdrawn maps, 2 saperators, missions, 1 separator, static maps
QList<QStandardItem * > items;
items.append(genMaps);
items.append(separator.clone());
items.append(separator.clone());
items.append(missionMaps);
items.append(separator.clone());
items.append(staticMaps);
// create row-index lookup table
m_mapIndexes.clear();
int count = items.size();
for (int i = 0; i < count; i++)
{
QStandardItem * si = items.at(i);
QVariant v = si->data(Qt::UserRole + 1);
if (v.canConvert<MapInfo>())
m_mapIndexes.insert(v.value<MapInfo>().name, i);
}
// store start-index and count of relevant types
m_typeLoc.insert(GeneratedMap, QPair<int,int>(0, 1));
m_typeLoc.insert(GeneratedMaze, QPair<int,int>(1, 1));
m_typeLoc.insert(HandDrawnMap, QPair<int,int>(2, 1));
// mission maps
int startIdx = genMaps.size() + 2; // start after genMaps and 2 separators
count = missionMaps.size();
m_typeLoc.insert(MissionMap, QPair<int,int>(startIdx, count));
// static maps
startIdx += count + 1; // start after missions and 2 separators
count = staticMaps.size();
m_typeLoc.insert(StaticMap, QPair<int,int>(startIdx, count));
// store list contents in the item model
QStandardItemModel::appendColumn(items);
endResetModel();
}
int MapModel::randomMap(MapType type) const
{
// return a random index for this type or -1 if none available
QPair<int,int> loc = m_typeLoc.value(type, QPair<int,int>(-1,0));
int startIdx = loc.first;
int count = loc.second;
if (count < 1)
return -1;
else
return startIdx + (rand() % count);
}
QStandardItem * MapModel::infoToItem(
const QIcon & icon,
const QString caption,
MapType type,
QString name,
QString theme,
quint32 limit,
QString scheme,
QString weapons)
const
{
QStandardItem * item = new QStandardItem(icon, caption);
MapInfo mapInfo;
QVariant qvar(QVariant::UserType);
mapInfo.type = type;
mapInfo.name = name;
mapInfo.theme = theme;
mapInfo.limit = limit;
mapInfo.scheme = scheme;
mapInfo.weapons = weapons;
qvar.setValue(mapInfo);
item->setData(qvar, Qt::UserRole + 1);
return item;
}
int MapModel::indexOf(const QString & map) const
{
return m_mapIndexes.value(map, -1);
}