|
From: <cn...@us...> - 2024-08-21 19:58:55
|
Revision: 1527
http://sourceforge.net/p/seq/svn/1527
Author: cn187
Date: 2024-08-21 19:58:52 +0000 (Wed, 21 Aug 2024)
Log Message:
-----------
Enable using info/equipment fields in spawn filter matches
Modified Paths:
--------------
showeq/trunk/src/filtermgr.cpp
showeq/trunk/src/filtermgr.h
showeq/trunk/src/spawn.cpp
Modified: showeq/trunk/src/filtermgr.cpp
===================================================================
--- showeq/trunk/src/filtermgr.cpp 2024-08-21 19:58:44 UTC (rev 1526)
+++ showeq/trunk/src/filtermgr.cpp 2024-08-21 19:58:52 UTC (rev 1527)
@@ -55,6 +55,11 @@
};
#undef X
+#define X(a, b) b,
+const QString InfoFilterStringFieldName[] = {
+ INFOFILTERSTRINGFIELD_TABLE
+};
+
//----------------------------------------------------------------------
// FilterMgr
FilterMgr::FilterMgr(const DataLocationMgr* dataLocMgr,
@@ -427,9 +432,17 @@
//init m_spawnFilterMap
for (int field = FSF_Name; field < FSF_Max; ++field)
{
+ if (field == FSF_Info) continue;
+
QString name = FilterStringFieldName[field];
m_spawnFilterMap[name] = "";
}
+ //starting with Head since Light is handled above
+ for (int field = IFSF_Head; field < IFSF_Max; ++field)
+ {
+ QString name = InfoFilterStringFieldName[field];
+ m_spawnFilterMap[name] = "";
+ }
m_spawnFilterMap[FSF_MINLEVEL_NAME] = "";
m_spawnFilterMap[FSF_MAXLEVEL_NAME] = "";
@@ -479,10 +492,12 @@
const QString labels[] = {
"Name", "Level", "Race", "Class", "NPC", "X", "Y", "Z", "Light", "Deity",
- "Race Team", "Deity Team", "Type", "Last Name", "Guild", "Spawn Time", "GM" };
+ "Race Team", "Deity Team", "Type", "Last Name", "Guild", "Spawn Time", "Info", "GM" };
for (int field = FSF_Name; field < FSF_Max; ++field)
{
+ if (field == FSF_Info) continue;
+
QString name = FilterStringFieldName[field];
QString label = labels[field];
m_filterFields[name] = new FilterFormField(name, label);
@@ -490,6 +505,19 @@
}
+ const QString info_labels[] = {
+ "Light", "Head", "Chest", "Arms", "Waist", "Gloves", "Legs", "Feet",
+ "Primary", "Secondary" };
+
+ // Starting with head, since Light is already created above.
+ for (int field = IFSF_Head; field < IFSF_Max; ++field)
+ {
+ QString name = InfoFilterStringFieldName[field];
+ QString label = info_labels[field];
+ m_filterFields[name] = new FilterFormField(name, label);
+ m_fieldCount++;
+ }
+
//not part of normal regex string, but still part of filter
m_filterFields[FSF_MINLEVEL_NAME] = new FilterFormField(FSF_MINLEVEL_NAME, FSF_MINLEVEL_LABEL);
m_filterFields[FSF_MAXLEVEL_NAME] = new FilterFormField(FSF_MAXLEVEL_NAME, FSF_MAXLEVEL_LABEL);
@@ -497,7 +525,9 @@
const QString formFieldOrder[] = { "Name", "LastName", "Guild", "Race", "Class",
"Deity", "Level", FSF_MINLEVEL_NAME, FSF_MAXLEVEL_NAME, "X", "Y", "Z", "NPC", "Type",
- "GM", "RTeam", "DTeam", "Spawn", "Light" };
+ "GM", "RTeam", "DTeam", "Spawn", "Light",
+ //Info fields
+ "H", "C", "A", "W", "G", "L", "F", "1", "2" };
int row = 1; //toggle all is row 0
int col = 0;
@@ -510,7 +540,9 @@
if (fieldname == "Guild" || fieldname == "Deity" ||
fieldname == FSF_MAXLEVEL_NAME || fieldname == "Z" ||
- fieldname == "GM" || fieldname == "Spawn")
+ fieldname == "GM" || fieldname == "Spawn" ||
+ fieldname == "Light" ||
+ fieldname == "A" || fieldname == "L")
{
row++;
col = 0;
@@ -557,7 +589,10 @@
m_fieldsCheckedCount = 0;
for (int field = FSF_Name; field < FSF_Max; ++field)
{
+ if (field == FSF_Info) continue;
+
QString name = FilterStringFieldName[field];
+
m_filterFields[name]->m_edit->setText(m_spawnFilterMap[name]);
if (m_filterFields[name]->m_edit->text().length())
@@ -570,6 +605,24 @@
m_filterFields[name]->stateChanged(Qt::Unchecked);
}
}
+
+ //starting with Head, since Light was handled above
+ for (int field = IFSF_Head; field < IFSF_Max; ++field)
+ {
+ QString name = InfoFilterStringFieldName[field];
+ m_filterFields[name]->m_edit->setText(m_spawnFilterMap[name]);
+
+ if (m_filterFields[name]->m_edit->text().length())
+ {
+ m_filterFields[name]->stateChanged(Qt::Checked);
+ m_fieldsCheckedCount++;
+ }
+ else
+ {
+ m_filterFields[name]->stateChanged(Qt::Unchecked);
+ }
+ }
+
//not part of normal regex string, but still part of filter
m_filterFields[FSF_MINLEVEL_NAME]->m_edit->setText(m_spawnFilterMap[FSF_MINLEVEL_NAME]);
if (m_filterFields[FSF_MINLEVEL_NAME]->m_edit->text().length())
@@ -610,10 +663,19 @@
//if enabled, add to map
for (int field = FSF_Name; field < FSF_Max; ++field)
{
+ if (field == FSF_Info) continue;
+
QString name = FilterStringFieldName[field];
if (m_filterFields[name]->m_edit->isEnabled())
map[name] = m_filterFields[name]->m_edit->text();
}
+ //starting with Head since Light is handled above
+ for (int field = IFSF_Head; field < IFSF_Max; ++field)
+ {
+ QString name = InfoFilterStringFieldName[field];
+ if (m_filterFields[name]->m_edit->isEnabled())
+ map[name] = m_filterFields[name]->m_edit->text();
+ }
//not part of normal regex string, but still part of filter
if (m_filterFields[FSF_MINLEVEL_NAME]->m_edit->isEnabled())
map[FSF_MINLEVEL_NAME] = m_filterFields[FSF_MINLEVEL_NAME]->m_edit->text();
@@ -768,17 +830,8 @@
//process filter string and set form fields
QStringList tokens = regex.split(":");
- //fields should be key:value, but split will create an extra item in the
- //list after the last :, so for a well-formed filterString, there should
- //always be an odd number of elements
- if (tokens.length() % 2 != 1)
- {
- seqWarn("Malformed filterString regex: %s", regex.toLatin1().data());
- return;
- }
-
QStringList::const_iterator itr = tokens.begin();
- for (;itr < tokens.end(); ++itr)
+ for (; itr < tokens.end(); ++itr)
{
QString name = *itr;
if (!map->contains(name))
@@ -789,29 +842,84 @@
continue;
}
- seqWarn("Ignoring unknown filter string field: %s", name.toLatin1().data());
- ++itr; // skip this field's data
- continue;
+ // Info isn't in the map, but we need to process it
+ // otherwise, skip any unknown fields
+ if (name != "Info")
+ {
+ seqWarn("Ignoring unknown filter string field: %s", name.toLatin1().data());
+ ++itr; // skip this field's data
+ continue;
+ }
}
+ // get field data
if (++itr == tokens.end())
+ break;
+ QString value = *itr;
+ if (!value.trimmed().length())
continue;
- QString value = *itr;
if (name == "Name" && (value == "Door" || value == "Drop"))
{
- //infuriatingly, we add a colon to door and drop names.
- //TODO try to find out how many people's filters this will break
- //if we remove the : from door and drop names (maybe replace it with
- //a - or something. Or save it for 7.x and do it anyway.
- //TODO also, check on adding trailing : to Item spawn filterstring
- //to make it consistent with the Spawn filterstring
+ //we add a colon to door and drop names, so it makes
+ //parsing a little more complicated.
value += ":";
if (++itr == tokens.end())
+ break;
+ value += *itr;
+ if (value.trimmed().length() <= 1)
continue;
- value += *itr;
}
- (*map)[name] = value.trimmed();
+ if (name == "Info")
+ {
+ //Info field contains space-separated slot:item pairs, and the
+ //items themselves can also contain spaces. So special parsing
+ //is needed.
+ bool info_done = false;
+ QString subfield_name = value;
+ while (itr != tokens.end() && !info_done)
+ {
+ // Check the name against valid sub-fields, because we could
+ // be past the Info field and into the next main field
+ bool is_info_field = false;
+ for (int field = IFSF_Light; field < IFSF_Max; ++field)
+ {
+ if (subfield_name == InfoFilterStringFieldName[field])
+ {
+ is_info_field = true;
+ break;
+ }
+ }
+
+ if (!is_info_field)
+ {
+ info_done = true;
+ continue;
+ }
+
+ // get value
+ if (++itr == tokens.end())
+ break;
+ value = *itr;
+ if (!value.trimmed().length())
+ continue;
+
+ QString next_subfield_name = value.section(" ", -1);
+ value = value.section(" ", 0, -2);
+
+ (*map)[subfield_name] = value.trimmed();
+
+ subfield_name = next_subfield_name;
+
+ }
+
+ if (itr == tokens.end())
+ break;
+ }
+ else
+ {
+ (*map)[name] = value.trimmed();
+ }
}
if (minLevel > -1)
@@ -835,30 +943,109 @@
{
QString name = FilterStringFieldName[field];
- if (!map->contains(name) || !(*map)[name].trimmed().length())
+ if (name == "Info")
{
- if (has_first_match && !wildcard)
+ //info subfields need special handling
+ bool info_added = false;
+ bool info_wildcard = false;
+ for (int info_field = IFSF_Light; info_field < IFSF_Max; ++info_field)
{
- wildcard = true;
+ QString subfield_name = InfoFilterStringFieldName[info_field];
+ if (!map->contains(subfield_name) || !(*map)[subfield_name].trimmed().length())
+ {
+ if (!info_wildcard)
+ {
+ info_wildcard = true;
+ }
+ continue;
+ }
+
+ QString value = (*map)[subfield_name];
+ value = value.trimmed();
+
+ if (!info_added)
+ {
+ if (wildcard)
+ {
+ wildcard = false;
+ filterString += ".*:Info:";
+ }
+ else
+ {
+ filterString += "Info:";
+ }
+ info_added = true;
+ }
+
+ if (info_wildcard)
+ {
+ info_wildcard = false;
+ // we need to handle 2 cases here
+ // 1. match-field ignore-field match-field
+ // 2. match-field matchfield
+ // If we naively insert .* like we do elsewhere, we'll
+ // wind up with " .* " which will never match case 2.
+ // But we also don't want to just not include spaces
+ // in the match, because we don't want to accidentally
+ // match a different field/value (especially with short
+ // field names like C or A.
+ if (filterString.length() && filterString.endsWith(" "))
+ {
+ filterString.chop(1);
+ filterString += "( | .* )";
+ }
+ else
+ {
+ filterString += ".*";
+ }
+ }
+
+ filterString += subfield_name;
+ filterString += ":";
+ filterString += value;
+ filterString += " ";
}
- continue;
+ //end of Info loop, tidy up
+ if (info_added)
+ {
+ if (info_wildcard)
+ {
+ info_wildcard = false;
+ filterString += ".*:";
+ }
+ else
+ {
+ filterString += ":";
+ }
+ }
}
+ else
+ {
+ if (!map->contains(name) || !(*map)[name].trimmed().length())
+ {
+ if (has_first_match && !wildcard)
+ {
+ wildcard = true;
+ }
+ continue;
+ }
- QString value = (*map)[name];
- value = value.trimmed();
+ QString value = (*map)[name];
+ value = value.trimmed();
- has_first_match = true;
+ has_first_match = true;
- if (wildcard)
- {
- wildcard = false;
- filterString += ".*:";
+ if (wildcard)
+ {
+ wildcard = false;
+ filterString += ".*:";
+ }
+ filterString += name;
+ filterString += ":";
+ filterString += value;
+ filterString += ":";
+
}
- filterString += name;
- filterString += ":";
- filterString += value;
- filterString += ":";
-
}
//min/max level are not part of normal regex string, but still part of filter
Modified: showeq/trunk/src/filtermgr.h
===================================================================
--- showeq/trunk/src/filtermgr.h 2024-08-21 19:58:44 UTC (rev 1526)
+++ showeq/trunk/src/filtermgr.h 2024-08-21 19:58:52 UTC (rev 1527)
@@ -83,25 +83,39 @@
#define FILTER_FLAG_TRACER (1 << TRACER_FILTER)
-#define FILTERSTRINGFIELD_TABLE \
- X(FSF_Name, "Name") \
- X(FSF_Level, "Level") \
- X(FSF_Race, "Race") \
- X(FSF_Class, "Class") \
- X(FSF_NPC, "NPC") \
- X(FSF_X, "X") \
- X(FSF_Y, "Y") \
- X(FSF_Z, "Z") \
- X(FSF_Light, "Light") \
- X(FSF_Deity, "Deity") \
- X(FSF_RTeam, "RTeam") \
- X(FSF_DTeam, "DTeam") \
- X(FSF_Type, "Type") \
- X(FSF_LastName, "LastName") \
- X(FSF_Guild, "Guild") \
- X(FSF_Spawn, "Spawn") \
+#define FILTERSTRINGFIELD_TABLE \
+ X(FSF_Name, "Name") \
+ X(FSF_Level, "Level") \
+ X(FSF_Race, "Race") \
+ X(FSF_Class, "Class") \
+ X(FSF_NPC, "NPC") \
+ X(FSF_X, "X") \
+ X(FSF_Y, "Y") \
+ X(FSF_Z, "Z") \
+ X(FSF_Light, "Light") \
+ X(FSF_Deity, "Deity") \
+ X(FSF_RTeam, "RTeam") \
+ X(FSF_DTeam, "DTeam") \
+ X(FSF_Type, "Type") \
+ X(FSF_LastName, "LastName") \
+ X(FSF_Guild, "Guild") \
+ X(FSF_Spawn, "Spawn") \
+ X(FSF_Info, "Info") \
X(FSF_GM, "GM")
+#define INFOFILTERSTRINGFIELD_TABLE \
+ X(IFSF_Light, "Light") \
+ X(IFSF_Head, "H") \
+ X(IFSF_Chest, "C") \
+ X(IFSF_Arms, "A") \
+ X(IFSF_Waist, "W") \
+ X(IFSF_Gloves, "G") \
+ X(IFSF_Legs, "L") \
+ X(IFSF_Feet, "F") \
+ X(IFSF_Primary, "1") \
+ X(IFSF_Secondary, "2")
+
+
#define X(a, b) a,
enum FilterStringField
{
@@ -110,7 +124,15 @@
};
#undef X
+#define X(a, b) a,
+enum InfoFilterStringField
+{
+ INFOFILTERSTRINGFIELD_TABLE
+ IFSF_Max
+};
+#undef X
+
// special handling for min/max level, which aren't part of regex filter string
#define FSF_MINLEVEL_NAME "MinLevel"
#define FSF_MINLEVEL_LABEL "Min Level"
Modified: showeq/trunk/src/spawn.cpp
===================================================================
--- showeq/trunk/src/spawn.cpp 2024-08-21 19:58:44 UTC (rev 1526)
+++ showeq/trunk/src/spawn.cpp 2024-08-21 19:58:52 UTC (rev 1527)
@@ -301,13 +301,13 @@
{
QString buff;
#if (QT_VERSION >= QT_VERSION_CHECK(5,5,0))
- buff = QString::asprintf("Name:%s:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d:Z:%d",
+ buff = QString::asprintf("Name:%s:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d:Z:%d:",
transformedName().toUtf8().data(),
raceString().toUtf8().data(),
classString().toUtf8().data(),
NPC(), x(), y(), z());
#else
- buff.sprintf("Name:%s:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d:Z:%d",
+ buff.sprintf("Name:%s:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d:Z:%d:",
transformedName().toUtf8().data(),
raceString().toUtf8().data(),
classString().toUtf8().data(),
@@ -960,7 +960,8 @@
QString buff;
#if (QT_VERSION >= QT_VERSION_CHECK(5,5,0))
buff = QString::asprintf("Name:%s:Level:%d:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d:Z:%d:"
- "Light:%s:Deity:%s:RTeam:%d:DTeam:%d:Type:%s:LastName:%s:Guild:%s:Spawn:%s:",
+ "Light:%s:Deity:%s:RTeam:%d:DTeam:%d:Type:%s:LastName:%s:Guild:%s:Spawn:%s:"
+ "Info:%s:",
name.toUtf8().data(),
level(),
raceString().toUtf8().data(),
@@ -974,11 +975,13 @@
typeString().toUtf8().data(),
lastName().toUtf8().data(),
guildTag().toUtf8().data(),
- spawnTimeStr ().replace (":", ".").toUtf8 ().data ()
+ spawnTimeStr ().replace (":", ".").toUtf8 ().data (),
+ info().toUtf8().data()
);
#else
buff.sprintf("Name:%s:Level:%d:Race:%s:Class:%s:NPC:%d:X:%d:Y:%d:Z:%d:"
- "Light:%s:Deity:%s:RTeam:%d:DTeam:%d:Type:%s:LastName:%s:Guild:%s:Spawn:%s:",
+ "Light:%s:Deity:%s:RTeam:%d:DTeam:%d:Type:%s:LastName:%s:Guild:%s:Spawn:%s:"
+ "Info:%s:",
name.toUtf8().data(),
level(),
raceString().toUtf8().data(),
@@ -992,7 +995,8 @@
typeString().toUtf8().data(),
lastName().toUtf8().data(),
guildTag().toUtf8().data(),
- spawnTimeStr ().replace (":", ".").toUtf8 ().data ()
+ spawnTimeStr ().replace (":", ".").toUtf8 ().data (),
+ info().toUtf8().data()
);
#endif
@@ -1021,6 +1025,7 @@
+ ":DTeam:" + QString::number(deityTeam())
+ ":Type:" + typeString()
+ ":Guild:" + guildTag()
+ + ":Info:" + info()
+ ":FilterFlags:" + QString::number(filterFlags())
+ ":";
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|