You can subscribe to this list here.
2004 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(18) |
Oct
(11) |
Nov
(9) |
Dec
|
---|---|---|---|---|---|---|---|---|---|---|---|---|
2005 |
Jan
|
Feb
(6) |
Mar
|
Apr
(10) |
May
(38) |
Jun
(15) |
Jul
(32) |
Aug
|
Sep
(17) |
Oct
(11) |
Nov
|
Dec
(14) |
2006 |
Jan
(2) |
Feb
(5) |
Mar
(3) |
Apr
(2) |
May
(3) |
Jun
(7) |
Jul
|
Aug
|
Sep
(3) |
Oct
(2) |
Nov
(6) |
Dec
(3) |
2007 |
Jan
|
Feb
(17) |
Mar
(5) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2008 |
Jan
(11) |
Feb
|
Mar
|
Apr
(4) |
May
|
Jun
(6) |
Jul
|
Aug
|
Sep
(6) |
Oct
(4) |
Nov
(1) |
Dec
|
2009 |
Jan
(3) |
Feb
(2) |
Mar
(4) |
Apr
|
May
(4) |
Jun
(3) |
Jul
|
Aug
(5) |
Sep
(3) |
Oct
(2) |
Nov
|
Dec
(6) |
2010 |
Jan
|
Feb
(6) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2011 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2012 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
|
Jun
|
Jul
(8) |
Aug
|
Sep
(2) |
Oct
(2) |
Nov
(4) |
Dec
(5) |
2013 |
Jan
(2) |
Feb
|
Mar
(2) |
Apr
(2) |
May
(1) |
Jun
(2) |
Jul
(2) |
Aug
(2) |
Sep
|
Oct
(2) |
Nov
(2) |
Dec
(2) |
2014 |
Jan
(3) |
Feb
(2) |
Mar
(3) |
Apr
(4) |
May
(4) |
Jun
(3) |
Jul
(4) |
Aug
(5) |
Sep
|
Oct
(2) |
Nov
(5) |
Dec
(2) |
2015 |
Jan
|
Feb
(2) |
Mar
|
Apr
|
May
(2) |
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
(10) |
Dec
|
2016 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(4) |
Aug
(2) |
Sep
(2) |
Oct
(3) |
Nov
(4) |
Dec
(2) |
2017 |
Jan
(2) |
Feb
|
Mar
(2) |
Apr
(4) |
May
(2) |
Jun
(2) |
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(2) |
2018 |
Jan
(4) |
Feb
(2) |
Mar
(2) |
Apr
(2) |
May
(2) |
Jun
(2) |
Jul
(8) |
Aug
(2) |
Sep
(2) |
Oct
(2) |
Nov
(4) |
Dec
(6) |
2019 |
Jan
(2) |
Feb
(2) |
Mar
(2) |
Apr
(4) |
May
(2) |
Jun
(3) |
Jul
(3) |
Aug
(2) |
Sep
(2) |
Oct
(13) |
Nov
(6) |
Dec
(4) |
2020 |
Jan
(7) |
Feb
(7) |
Mar
(7) |
Apr
(8) |
May
(5) |
Jun
(3) |
Jul
(10) |
Aug
(4) |
Sep
|
Oct
(37) |
Nov
(30) |
Dec
(8) |
2021 |
Jan
(14) |
Feb
(9) |
Mar
(7) |
Apr
(17) |
May
(3) |
Jun
(10) |
Jul
(7) |
Aug
(3) |
Sep
(3) |
Oct
(4) |
Nov
(15) |
Dec
(22) |
2022 |
Jan
(3) |
Feb
(3) |
Mar
(3) |
Apr
(3) |
May
(3) |
Jun
(3) |
Jul
(3) |
Aug
(5) |
Sep
(6) |
Oct
(4) |
Nov
(34) |
Dec
(17) |
2023 |
Jan
(3) |
Feb
(3) |
Mar
(29) |
Apr
(2) |
May
(18) |
Jun
(12) |
Jul
(12) |
Aug
(2) |
Sep
(7) |
Oct
(2) |
Nov
(2) |
Dec
(2) |
2024 |
Jan
(2) |
Feb
(10) |
Mar
(17) |
Apr
(6) |
May
(3) |
Jun
(9) |
Jul
(22) |
Aug
(48) |
Sep
(3) |
Oct
(2) |
Nov
(2) |
Dec
(8) |
2025 |
Jan
(3) |
Feb
(2) |
Mar
(9) |
Apr
(7) |
May
(3) |
Jun
(3) |
Jul
(2) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: <cn...@us...> - 2024-08-21 19:57:29
|
Revision: 1518 http://sourceforge.net/p/seq/svn/1518 Author: cn187 Date: 2024-08-21 19:57:26 +0000 (Wed, 21 Aug 2024) Log Message: ----------- Enable menu options for renaming/deleting spawn points Modified Paths: -------------- showeq/trunk/src/spawnpointlist.cpp Modified: showeq/trunk/src/spawnpointlist.cpp =================================================================== --- showeq/trunk/src/spawnpointlist.cpp 2024-08-21 19:57:12 UTC (rev 1517) +++ showeq/trunk/src/spawnpointlist.cpp 2024-08-21 19:57:26 UTC (rev 1518) @@ -242,8 +242,10 @@ // the list is limited to one selection at a time, so we can take the first SEQListViewItem* item = selected.first(); + m_menu->setCurrentItem((SpawnPointListItem*)item); if (item == NULL) return; + const SpawnPoint* sp = NULL; if ( item ) @@ -527,6 +529,8 @@ void SpawnPointListMenu::setCurrentItem(const SpawnPointListItem* item) { m_currentItem = item; + m_action_rename->setEnabled(m_currentItem != NULL); + m_action_delete->setEnabled(m_currentItem != NULL); } void SpawnPointListMenu::init_menu() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-21 19:57:15
|
Revision: 1517 http://sourceforge.net/p/seq/svn/1517 Author: cn187 Date: 2024-08-21 19:57:12 +0000 (Wed, 21 Aug 2024) Log Message: ----------- Update OP_Consider logic to correctly display con colors and level Modified Paths: -------------- showeq/trunk/src/messageshell.cpp Modified: showeq/trunk/src/messageshell.cpp =================================================================== --- showeq/trunk/src/messageshell.cpp 2024-08-21 19:57:04 UTC (rev 1516) +++ showeq/trunk/src/messageshell.cpp 2024-08-21 19:57:12 UTC (rev 1517) @@ -1150,7 +1150,9 @@ // yes deity = spawn->deityName(); - msg += item->name(); + lvl = QString::number(spawn->level()); + + msg += item->name() + " (Lvl: " + lvl + ")"; } // end if spawn found else msg += "Spawn:" + QString::number(con->targetid, 16); @@ -1159,9 +1161,13 @@ switch (con->level) { case 0: + case 5: case 20: msg += " (even)"; break; + case 1: + msg += " (grey)"; + break; case 2: msg += " (green)"; break; @@ -1168,12 +1174,15 @@ case 4: msg += " (blue)"; break; + case 7: case 13: msg += " (red)"; break; + case 6: case 15: msg += " (yellow)"; break; + case 3: case 18: msg += " (cyan)"; break; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-21 19:57:07
|
Revision: 1516 http://sourceforge.net/p/seq/svn/1516 Author: cn187 Date: 2024-08-21 19:57:04 +0000 (Wed, 21 Aug 2024) Log Message: ----------- Rework packet capture logic to improve reliability of session detection and fix misc issues Modified Paths: -------------- showeq/trunk/src/Makefile.am showeq/trunk/src/interface.cpp showeq/trunk/src/packet.cpp showeq/trunk/src/packet.h showeq/trunk/src/packetcapture.cpp showeq/trunk/src/packetcapture.h showeq/trunk/src/packetcommon.h showeq/trunk/src/packetstream.cpp showeq/trunk/src/packetstream.h showeq/trunk/src/util.cpp showeq/trunk/src/util.h Added Paths: ----------- showeq/trunk/src/packetcaptureprovider.cpp showeq/trunk/src/packetcaptureprovider.h Modified: showeq/trunk/src/Makefile.am =================================================================== --- showeq/trunk/src/Makefile.am 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/Makefile.am 2024-08-21 19:57:04 UTC (rev 1516) @@ -15,7 +15,7 @@ datalocationmgr.cpp eqstr.cpp messages.cpp message.cpp messagefilter.cpp messagewindow.cpp \ messageshell.cpp terminal.cpp filteredspawnlog.cpp messagefilterdialog.cpp \ diagnosticmessages.cpp mapicon.cpp filternotifications.cpp netstream.cpp guildshell.cpp \ - guildlist.cpp bazaarlog.cpp mapicondialog.cpp + guildlist.cpp bazaarlog.cpp mapicondialog.cpp packetcaptureprovider.cpp showeq_moc_SRCS = bazaarlog.moc category.moc combatlog.moc compass.moc \ compassframe.moc datetimemgr.moc editor.moc experiencelog.moc \ @@ -113,7 +113,7 @@ EXTRA_DIST = h2info.pl -noinst_HEADERS = classes.h compass.h everquest.h interface.h main.h map.h filter.h vpacket.h editor.h packet.h packetcapture.h packetcommon.h packetformat.h packetstream.h packetfragment.h packetinfo.h races.h skills.h spells.h util.h experiencelog.h combatlog.h spawn.h spawnshell.h spawnlist.h spellshell.h spelllist.h languages.h weapons.h weapons1.h weapons27.h weapons28.h weapons29.h weapons2a.h weapons2b.h weapons2c.h weapons2d.h weapons2e.h weapons2f.h weapons30.h weapons4e.h decode.h cgiconv.h skilllist.h statlist.h deity.h player.h crctab.h filtermgr.h point.h pointarray.h mapcore.h category.h compassframe.h group.h guild.h fixpt.h netdiag.h zones.h logger.h xmlconv.h xmlpreferences.h seqwindow.h seqlistview.h zonemgr.h spawnmonitor.h spawnpointlist.h typenames.h spawnlistcommon.h spawnlist2.h datetimemgr.h spawnlog.h packetlog.h datalocationmgr.h eqstr.h messages.h messagefilter.h messagewindow.h messageshell.h terminal.h filteredspawnlog.h messagefilterdialog.h diagnosticmessages.h mapicon.h mapicondialog.h mapicondialog.ui filternotifications.h netstream.h guildshell.h guildlist.h bazaarlog.h message.h s_everquest.h staticspells.h +noinst_HEADERS = classes.h compass.h everquest.h interface.h main.h map.h filter.h vpacket.h editor.h packet.h packetcapture.h packetcommon.h packetformat.h packetstream.h packetfragment.h packetinfo.h races.h skills.h spells.h util.h experiencelog.h combatlog.h spawn.h spawnshell.h spawnlist.h spellshell.h spelllist.h languages.h weapons.h weapons1.h weapons27.h weapons28.h weapons29.h weapons2a.h weapons2b.h weapons2c.h weapons2d.h weapons2e.h weapons2f.h weapons30.h weapons4e.h decode.h cgiconv.h skilllist.h statlist.h deity.h player.h crctab.h filtermgr.h point.h pointarray.h mapcore.h category.h compassframe.h group.h guild.h fixpt.h netdiag.h zones.h logger.h xmlconv.h xmlpreferences.h seqwindow.h seqlistview.h zonemgr.h spawnmonitor.h spawnpointlist.h typenames.h spawnlistcommon.h spawnlist2.h datetimemgr.h spawnlog.h packetlog.h datalocationmgr.h eqstr.h messages.h messagefilter.h messagewindow.h messageshell.h terminal.h filteredspawnlog.h messagefilterdialog.h diagnosticmessages.h mapicon.h mapicondialog.h mapicondialog.ui filternotifications.h netstream.h guildshell.h guildlist.h bazaarlog.h message.h s_everquest.h staticspells.h packetcaptureprovider.h CLEANFILES = $(nodist_showeq_SOURCES) Modified: showeq/trunk/src/interface.cpp =================================================================== --- showeq/trunk/src/interface.cpp 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/interface.cpp 2024-08-21 19:57:04 UTC (rev 1516) @@ -71,7 +71,6 @@ #include <unistd.h> #include <cstdlib> #include <cstdio> -#include <ifaddrs.h> #include <QFont> #include <QApplication> @@ -150,7 +149,7 @@ m_netDiag(0), m_messageFilterDialog(0), m_guildListWindow(0), - m_deviceList(enumerateDevices()) + m_deviceList(enumerateNetworkDevices()) { setObjectName(name); setWindowFlags(Qt::Window); @@ -5230,7 +5229,7 @@ maclst, 0, true, &ok); if (ok) { - if (address.length() != 17) + if (address.length() != 17 && !address.isEmpty()) { seqWarn("Invalid MAC Address (%s)! Ignoring!", address.toLatin1().data()); return; @@ -5246,35 +5245,10 @@ } } -QStringList EQInterface::enumerateDevices() -{ - struct ifaddrs *ifaddr, *ifa; - int n; - QStringList devices; - if (getifaddrs(&ifaddr) == -1) - { - seqWarn("Could not enumerate network devices"); - return QStringList(); - } - - for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) - { - if (ifa->ifa_addr == NULL) - continue; - - if (ifa->ifa_addr->sa_family == AF_INET) - devices.append(ifa->ifa_name); - } - - freeifaddrs(ifaddr); - - return devices; -} - QString EQInterface::promptForNetDevice() { - m_deviceList = enumerateDevices(); + m_deviceList = enumerateNetworkDevices(); int current = 0; if (m_packet) Modified: showeq/trunk/src/packet.cpp =================================================================== --- showeq/trunk/src/packet.cpp 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/packet.cpp 2024-08-21 19:57:04 UTC (rev 1516) @@ -1,6 +1,6 @@ /* * packet.cpp - * Copyright 2000-2008, 2016, 2019 by the respective ShowEQ Developers + * Copyright 2000-2024 by the respective ShowEQ Developers * Portions Copyright 2001-2004,2007 Zaphod (do...@us...). * * This file is part of ShowEQ. @@ -36,6 +36,7 @@ #include "everquest.h" #include "packet.h" +#include "packetcommon.h" #include "packetcapture.h" #include "packetformat.h" #include "packetstream.h" @@ -73,14 +74,6 @@ //---------------------------------------------------------------------- // constants -const in_port_t WorldServerGeneralMinPort = 9000; -const in_port_t WorldServerGeneralMaxPort = 9013; -const in_port_t WorldServerChatPort = 9876; -const in_port_t WorldServerChat2Port = 9875; // xgame tells, mail -const in_port_t LoginServerMinPort = 15900; -const in_port_t LoginServerMaxPort = 15910; -const in_port_t ChatServerPort = 5998; - //---------------------------------------------------------------------- // Here begins the code @@ -188,54 +181,38 @@ // no client/server ports yet m_clientPort = 0; m_serverPort = 0; - - struct hostent *he; - struct in_addr ia; + if (m_ip.isEmpty() && m_mac.isEmpty()) - seqFatal("No address specified"); - - if (!m_ip.isEmpty()) { - /* Substitute "special" IP which is interpreted - to set up a different filter for picking up new sessions */ - - if (m_ip == "auto") - inet_aton (AUTOMATIC_CLIENT_IP, &ia); - else if (inet_aton (m_ip.toLatin1().data(), &ia) == 0) - { - he = gethostbyname(m_ip.toLatin1().data()); - if (!he) - seqFatal("Invalid address; %s", m_ip.toLatin1().data()); - - memcpy (&ia, he->h_addr_list[0], he->h_length); - } - m_client_addr = ia.s_addr; - m_ip = inet_ntoa(ia); - - if (m_ip == AUTOMATIC_CLIENT_IP) - { - m_detectingClient = true; - seqInfo("Listening for first client seen."); - } - else - { - m_detectingClient = false; - seqInfo("Listening for client: %s", m_ip.toLatin1().data()); - } + seqInfo("No address specified. Defaulting to client auto-detect"); + m_ip = AUTOMATIC_CLIENT_IP; } + validateIP(); + if (m_playbackPackets == PLAYBACK_OFF) { // create the pcap object and initialize, either with MAC or IP m_packetCapture = new PacketCaptureThread(); if (m_mac.length() == 17) + { + seqInfo("Listening for client MAC: %s", m_mac.toLatin1().data()); + m_packetCapture->start(m_device.toLatin1().data(), m_mac.toLatin1().data(), m_realtime, MAC_ADDRESS_TYPE ); + } else + { + if (m_detectingClient) + seqInfo("Listening for next client seen. (you must zone for this to work!)"); + else + seqInfo("Listening for client: %s", m_ip.toLatin1().data()); + m_packetCapture->start(m_device.toLatin1().data(), m_ip.toLatin1().data(), m_realtime, IP_ADDRESS_TYPE ); + } emit filterChanged(); } else if (m_playbackPackets == PLAYBACK_FORMAT_TCPDUMP) @@ -310,6 +287,43 @@ } } +//helper function to verify specified IP is a valid IP or hostname, and/or +//to set up auto detection. +void EQPacket::validateIP() +{ + struct in_addr ia; + struct hostent *he; + + if (m_ip.isEmpty() || m_ip == AUTOMATIC_CLIENT_IP) + { + /* Substitute "special" IP which is interpreted + to set up a different filter for picking up new sessions */ + inet_aton (AUTOMATIC_CLIENT_IP, &ia); + } + else if (inet_aton (m_ip.toLatin1().data(), &ia) == 0) + { + he = gethostbyname(m_ip.toLatin1().data()); + if (he) + { + memcpy (&ia, he->h_addr_list[0], he->h_length); + } + else + { + // If the IP or host is invalid, default to auto-detect, rather + // than immediately exiting (the previous behavior) + seqWarn("Invalid address or hostname: %s", m_ip.toLatin1().data()); + seqWarn("Defaulting to client auto-detect"); + m_ip = AUTOMATIC_CLIENT_IP; + inet_aton (AUTOMATIC_CLIENT_IP, &ia); + } + } + m_client_addr = ia.s_addr; + m_ip = inet_ntoa(ia); + + m_detectingClient = (m_ip == AUTOMATIC_CLIENT_IP); + +} + //////////////////////////////////////////////////// // Destructor EQPacket::~EQPacket() @@ -564,9 +578,9 @@ this, SIGNAL(sessionTrackingChanged(uint8_t))); connect(stream, - SIGNAL(lockOnClient(in_port_t, in_port_t)), + SIGNAL(lockOnClient(in_port_t, in_port_t, in_addr_t)), this, - SLOT(lockOnClient(in_port_t, in_port_t))); + SLOT(lockOnClient(in_port_t, in_port_t, in_addr_t))); connect(stream, SIGNAL(closing(uint32_t, EQStreamID)), this, @@ -704,23 +718,32 @@ // If we just closed the zone server session, unlatch the client port if (streamId == zone2client || streamId == client2zone) { - m_clientPort = 0; - m_serverPort = 0; + unlatchClientPort(); - emit clientPortLatched(m_clientPort); - seqInfo("EQPacket: SessionDisconnect detected, awaiting next zone session, pcap filter: EQ Client %s", - m_ip.toLatin1().data()); + (m_ip == AUTOMATIC_CLIENT_IP) ? "auto-detect" : m_ip.toLatin1().data()); } } +// Unlatch a locked-on client port, so the next client is detected correctly +void EQPacket::unlatchClientPort() +{ + m_clientPort = 0; + m_serverPort = 0; + emit clientPortLatched(m_clientPort); +} + + //////////////////////////////////////////////////// // Locks onto a specific client port (for session tracking) -void EQPacket::lockOnClient(in_port_t serverPort, in_port_t clientPort) +void EQPacket::lockOnClient(in_port_t serverPort, in_port_t clientPort, in_addr_t clientAddr) { m_serverPort = serverPort; m_clientPort = clientPort; + m_client_addr = clientAddr; + in_addr ia = inet_makeaddr(ntohl(m_client_addr), ntohl(m_client_addr)); + if (m_playbackPackets == PLAYBACK_OFF || m_playbackPackets == PLAYBACK_FORMAT_TCPDUMP) { @@ -753,7 +776,7 @@ else { seqInfo("EQPacket: SessionRequest detected, pcap filter: EQ Client %s, Client port %d. Server port %d", - m_ip.toLatin1().data(), m_clientPort, m_serverPort); + inet_ntoa(ia), m_clientPort, m_serverPort); } emit clientPortLatched(m_clientPort); @@ -928,14 +951,14 @@ void EQPacket::monitorIPClient(const QString& ip) { m_ip = ip; - struct in_addr ia; - inet_aton (m_ip.toLatin1().data(), &ia); - m_client_addr = ia.s_addr; + + validateIP(); + emit clientChanged(m_client_addr); resetEQPacket(); - seqInfo("Listening for IP client: %s", m_ip.toLatin1().data()); + seqInfo("Listening for IP client: %s", (m_ip == AUTOMATIC_CLIENT_IP) ? "auto-detect" : m_ip.toLatin1().data()); if (m_playbackPackets == PLAYBACK_OFF || m_playbackPackets == PLAYBACK_FORMAT_TCPDUMP) { @@ -952,24 +975,32 @@ void EQPacket::monitorMACClient(const QString& mac) { m_mac = mac; - m_detectingClient = true; struct in_addr ia; inet_aton (AUTOMATIC_CLIENT_IP, &ia); + m_detectingClient = true; m_client_addr = ia.s_addr; emit clientChanged(m_client_addr); resetEQPacket(); - seqInfo("Listening for MAC client: %s", m_mac.toLatin1().data()); + if (!m_mac.isEmpty() && m_mac.length() == 17) + { + seqInfo("Listening for MAC client: %s", m_mac.toLatin1().data()); - if (m_playbackPackets == PLAYBACK_OFF || - m_playbackPackets == PLAYBACK_FORMAT_TCPDUMP) + if (m_playbackPackets == PLAYBACK_OFF || + m_playbackPackets == PLAYBACK_FORMAT_TCPDUMP) + { + m_packetCapture->setFilter(m_device.toLatin1().data(), + m_mac.toLatin1().data(), + m_realtime, + MAC_ADDRESS_TYPE, 0, 0); + emit filterChanged(); + } + } + else { - m_packetCapture->setFilter(m_device.toLatin1().data(), - m_ip.toLatin1().data(), - m_realtime, - IP_ADDRESS_TYPE, 0, 0); - emit filterChanged(); + seqWarn("Invalid MAC specified. Defaulting to auto-detect of next client."); + monitorNextClient(); } } @@ -1012,50 +1043,31 @@ // stop the current packet capture m_packetCapture->stop(); - // setup for capture on new device - if (!m_ip.isEmpty()) - { - struct hostent *he; - struct in_addr ia; + validateIP(); - /* Substitute "special" IP which is interpreted - to set up a different filter for picking up new sessions */ - - if (m_ip == "auto") - inet_aton (AUTOMATIC_CLIENT_IP, &ia); - else if (inet_aton (m_ip.toLatin1().data(), &ia) == 0) - { - he = gethostbyname(m_ip.toLatin1().data()); - if (!he) - seqFatal("Invalid address; %s", m_ip.toLatin1().data()); - - memcpy (&ia, he->h_addr_list[0], he->h_length); - } - m_client_addr = ia.s_addr; - m_ip = inet_ntoa(ia); - - if (m_ip == AUTOMATIC_CLIENT_IP) - { - m_detectingClient = true; - seqInfo("Listening for first client seen."); - } - else - { - m_detectingClient = false; - seqInfo("Listening for client: %s", m_ip.toLatin1().data()); - } - } - resetEQPacket(); // restart packet capture if (m_mac.length() == 17) + { + seqInfo("Listening for client MAC: %s", m_mac.toLatin1().data()); + m_packetCapture->start(m_device.toLatin1().data(), m_mac.toLatin1().data(), m_realtime, MAC_ADDRESS_TYPE ); + } else - m_packetCapture->start(m_device.toLatin1().data(), m_ip.toLatin1().data(), - m_realtime, IP_ADDRESS_TYPE ); + { + if (m_detectingClient) + seqInfo("Listening for next client seen. (you must zone for this to work!)"); + else + seqInfo("Listening for client: %s", m_ip.toLatin1().data()); + + m_packetCapture->start(m_device.toLatin1().data(), + m_ip.toLatin1().data(), + m_realtime, IP_ADDRESS_TYPE ); + } + emit filterChanged(); } @@ -1134,10 +1146,7 @@ m_zone2ClientStream->reset(); m_zone2ClientStream->setSessionTracking(m_session_tracking); - m_clientPort = 0; - m_serverPort = 0; - - emit clientPortLatched(m_clientPort); + unlatchClientPort(); } /////////////////////////////////////////// Modified: showeq/trunk/src/packet.h =================================================================== --- showeq/trunk/src/packet.h 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/packet.h 2024-08-21 19:57:04 UTC (rev 1516) @@ -1,6 +1,6 @@ /* * packet.h - * Copyright 2000-2008, 2019 by the respective ShowEQ Developers + * Copyright 2000-2024 by the respective ShowEQ Developers * Portions Copyright 2001-2003 Zaphod (do...@us...). * * This file is part of ShowEQ. @@ -51,7 +51,7 @@ //---------------------------------------------------------------------- // forward declarations class VPacket; -class PacketCaptureThread; +class PacketCaptureProviderThread; class EQPacketStream; class EQUDPIPPacketFormat; class EQPacketTypeDB; @@ -121,7 +121,8 @@ protected slots: void closeStream(uint32_t sessionId, EQStreamID streamId); - void lockOnClient(in_port_t serverPort, in_port_t clientPort); + void unlatchClientPort(); + void lockOnClient(in_port_t serverPort, in_port_t clientPort, in_addr_t clientAddr); signals: // used for net_stats display @@ -158,8 +159,9 @@ bool unknown); private: + void validateIP(); - PacketCaptureThread* m_packetCapture; + PacketCaptureProviderThread* m_packetCapture; VPacket* m_vPacket; QTimer* m_timer; Modified: showeq/trunk/src/packetcapture.cpp =================================================================== --- showeq/trunk/src/packetcapture.cpp 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/packetcapture.cpp 2024-08-21 19:57:04 UTC (rev 1516) @@ -1,6 +1,6 @@ /* * packetcapture.cpp - * Copyright 2000-2008, 2019 by the respective ShowEQ Developers + * Copyright 2000-2024 by the respective ShowEQ Developers * Portions Copyright 2001-2003 Zaphod (do...@us...). * * This file is part of ShowEQ. @@ -31,6 +31,7 @@ #include <arpa/inet.h> #include "packetcapture.h" +#include "packetcommon.h" #include "diagnosticmessages.h" //#define PCAP_DEBUG 1 @@ -39,7 +40,8 @@ // PacketCaptureThread // start and stop the thread // get packets to the processing engine(dispatchPacket) -PacketCaptureThread::PacketCaptureThread() : +PacketCaptureThread::PacketCaptureThread() : PacketCaptureProviderThread(), + m_pcache_pcap(NULL), m_playbackSpeed(0) { } @@ -52,25 +54,6 @@ pcap_close(m_pcache_pcap); } - // Drop the packets we have lying around - pthread_mutex_lock (&m_pcache_mutex); - - struct packetCache *pc = m_pcache_first; - struct packetCache* freeMe = NULL; - - while (pc) - { - freeMe = pc; - pc = pc->next; - - free(freeMe); - } - - m_pcache_first = NULL; - m_pcache_last = NULL; - m_pcache_closed = true; - - pthread_mutex_unlock (&m_pcache_mutex); } void PacketCaptureThread::setPlaybackSpeed(int playbackSpeed) @@ -99,69 +82,55 @@ { char ebuf[PCAP_ERRBUF_SIZE]; // pcap error buffer char filter_buf[256]; // pcap filter buffer - struct bpf_program bpp; - struct sched_param sp; - bpf_u_int32 mask; // sniff device netmask - bpf_u_int32 net; // sniff device ip seqInfo("Initializing Packet Capture Thread: "); m_pcache_closed = false; - // Fetch the netmask for the device to use later with the filter. - if (pcap_lookupnet(device, &net, &mask, ebuf) == -1) - { - // Couldn't find net mask. Just leave it open. - seqWarn("Couldn't determine netmask of device %s. Using 0.0.0.0. Error was %s", - device, ebuf); - } + /* We've replaced pcap_open_live() with pcap_create/pcap_activate. + * This allows us to use immedate mode, rather than approximating it with + * a 1ms timeout value. + * + * NOTE: a race condition exists between this thread and the main thread + * - any artificial delay in getting packets can cause filtering problems + * and cause us to miss new stream when the player zones. + */ - // create pcap style filter expressions - if (address_type == IP_ADDRESS_TYPE) + // initialize the pcap object + m_pcache_pcap = pcap_create((const char*)device, ebuf); + + if (!m_pcache_pcap) { - if (strcmp(host, AUTOMATIC_CLIENT_IP) == 0) + seqFatal("pcap_error:pcap_create(%s): %s", device, ebuf); + if ((getuid() != 0) && (geteuid() != 0)) { - seqInfo("Filtering packets on device %s, searching for EQ client...", device); - sprintf (filter_buf, "udp[0:2] > 1024 and udp[2:2] > 1024 and ether proto 0x0800 and not broadcast and not multicast"); + seqWarn("Make sure you are running ShowEQ as root."); } - else - { - seqInfo("Filtering packets on device %s, IP host %s", device, host); - sprintf (filter_buf, "udp[0:2] > 1024 and udp[2:2] > 1024 and host %s and ether proto 0x0800 and not broadcast and not multicast", host); - } + exit(1); } - else if (address_type == MAC_ADDRESS_TYPE) + + pcap_set_promisc(m_pcache_pcap, 1); + //PCAP docs say 64K snaplen should be enough for most networks. + pcap_set_snaplen(m_pcache_pcap, UINT16_MAX); + // default buffer size is 2M: 2*1024*1024 + // but we can increase it in the future if needed + //pcap_set_buffer_size(m_pcache_pcap, 4*1024*1024); + +#ifndef __FreeBSD__ + pcap_set_immediate_mode(m_pcache_pcap, 1); +#endif + + int act = pcap_activate(m_pcache_pcap); + if (act > 0) { - seqInfo("Filtering packets on device %s, MAC host %s", device, host); - sprintf (filter_buf, "udp[0:2] > 1024 and udp[2:2] > 1024 and ether host %s and ether proto 0x0800 and not broadcast and not multicast", host); + seqWarn("pcap_warning:pcap_activate:%s", pcap_statustostr(act)); } - else + else if (act < 0) { - seqFatal("pcap_error:filter_string: unknown address_type (%d)", address_type); - exit(0); + seqFatal("pcap_error:pcap_activate:%s", pcap_statustostr(act)); + pcap_close(m_pcache_pcap); + exit(1); } - /* A word about pcap_open_live() from the docs - ** to_ms specifies the read timeout in milliseconds. The - ** read timeout is used to arrange that the read not necessarily - ** return immediately when a packet is seen, but that it wait - ** for some amount of time to allow more packets to arrive and - ** to read multiple packets from the OS kernel in one operation. - ** Not all platforms support a read timeout; on platforms that - ** don't, the read timeout is ignored. - ** - ** In Linux 2.4.x with the to_ms set to 0 we got packets immediatly, - ** and thats what we need in this application. However, as of libpcap - ** 1.9.1, a timeout of 0 means infinity, so that no longer works. A - ** negative timeout will use the default kernal timeout, which can - ** vary. So the most prudent option is to set the timeout as low - ** as we can, to 1 ms. - ** - ** a race condition exists between this thread and the main thread - ** any artificial delay in getting packets can cause filtering problems - ** and cause us to miss new stream when the player zones. - */ - // initialize the pcap object - m_pcache_pcap = pcap_open_live((char *) device, BUFSIZ, true, 1, ebuf); #ifdef __FreeBSD__ // if we're on FreeBSD, we need to call ioctl on the file descriptor // with BIOCIMMEDIATE to get the kernel Berkeley Packet Filter device @@ -171,7 +140,7 @@ // knows a less hacky way of doing this, I'd love to hear about it. // the problem here is that libpcap doesn't expose an API to do this // in any way - int fd = *((int*)m_pcache_pcap); + int fd = pcap_fileno(m_pcache_pcap); int temp = 1; if ( ioctl( fd, BIOCIMMEDIATE, &temp ) < 0 ) { @@ -178,44 +147,13 @@ seqWarn("PCAP couldn't set immediate mode on BSD" ); } #endif - if (!m_pcache_pcap) - { - seqWarn("pcap_error:pcap_open_live(%s): %s", device, ebuf); - if ((getuid() != 0) && (geteuid() != 0)) - { - seqWarn("Make sure you are running ShowEQ as root."); - } - exit(0); - } - if (pcap_compile(m_pcache_pcap, &bpp, filter_buf, 1, net) == -1) - { - pcap_perror (m_pcache_pcap, (char*)"pcap_error:pcap_compile"); - exit(0); - } - - if (pcap_setfilter (m_pcache_pcap, &bpp) == -1) - { - pcap_perror (m_pcache_pcap, (char*)"pcap_error:pcap_setfilter"); - exit(0); - } - - pcap_freecode(&bpp); - m_pcache_first = m_pcache_last = NULL; - pthread_mutex_init (&m_pcache_mutex, NULL); pthread_create (&m_tid, NULL, loop, (void*)this); - if (realtime) - { - memset (&sp, 0, sizeof (sp)); - sp.sched_priority = 1; - if (pthread_setschedparam (m_tid, SCHED_RR, &sp) != 0) - { - seqWarn("Failed to set capture thread realtime."); - } - } + this->setFilter(device, host, realtime, address_type, 0, 0); + } //------------------------------------------------------------------------ @@ -247,7 +185,6 @@ m_pcache_first = m_pcache_last = NULL; - pthread_mutex_init(&m_pcache_mutex, NULL); pthread_create(&m_tid, NULL, loop, (void*)this); } @@ -254,8 +191,11 @@ void PacketCaptureThread::stop() { // close the pcap session - pcap_close(m_pcache_pcap); - m_pcache_pcap = NULL; + if (m_pcache_pcap) + { + pcap_close(m_pcache_pcap); + m_pcache_pcap = NULL; + } } void* PacketCaptureThread::loop (void *param) @@ -399,37 +339,6 @@ pthread_mutex_unlock (&myThis->m_pcache_mutex); } -uint16_t PacketCaptureThread::getPacket(unsigned char *buff) -{ - uint16_t ret; - struct packetCache *pc = NULL; - - pthread_mutex_lock (&m_pcache_mutex); - - ret = 0; - - pc = m_pcache_first; - - if (pc) - { - m_pcache_first = pc->next; - - if (!m_pcache_first) - m_pcache_last = NULL; - } - - pthread_mutex_unlock (&m_pcache_mutex); - - if (pc) - { - ret = pc->len; - memcpy (buff, pc->data, ret); - free (pc); - } - - return ret; -} - void PacketCaptureThread::setFilter (const char *device, const char *hostname, bool realtime, @@ -437,12 +346,13 @@ uint16_t zone_port, uint16_t client_port) { - char filter_buf[256]; // pcap filter buffer + char filter_buf[256]; // pcap filter buffer + char* pfb = filter_buf; char ebuf[PCAP_ERRBUF_SIZE]; struct bpf_program bpp; struct sched_param sp; - bpf_u_int32 mask; // sniff device netmask - bpf_u_int32 net; // sniff device ip + bpf_u_int32 mask = 0; // sniff device netmask + bpf_u_int32 net = 0 ; // sniff device ip // Fetch the netmask for the device to use later with the filter if (pcap_lookupnet(device, &net, &mask, ebuf) == -1) @@ -452,51 +362,47 @@ device, ebuf); } - /* Listen to World Server or the specified Zone Server */ - if (address_type == IP_ADDRESS_TYPE && client_port) + if (!client_port && !zone_port) { - // Restrict to client port and ip, plus world streams. - sprintf(filter_buf, - "udp and (portrange 9000-9007 or port 9876 or port %d) and host %s and ether proto 0x0800 and not broadcast and not multicast", - client_port, hostname); + //no client/zone port detected, so leave it open + pfb += sprintf(pfb, "udp[0:2] > 1024 and udp[2:2] > 1024"); } - else if (address_type == IP_ADDRESS_TYPE && zone_port) + else { - // Restrict to zone port and world streams. - sprintf(filter_buf, - "udp and (portrange 9000-9007 or port 9876 or port %d) and host %s and ether proto 0x0800 and not broadcast and not multicast", - zone_port, hostname); + // restrict to client/zone port and world server ports + pfb += sprintf(pfb, "udp"); + pfb += sprintf(pfb, " and (portrange %d-%d or port %d or port %d)", + WorldServerGeneralMinPort, WorldServerGeneralMaxPort, + WorldServerChatPort, (client_port) ? client_port : zone_port); } - else if (address_type == MAC_ADDRESS_TYPE && client_port) + + if (address_type == IP_ADDRESS_TYPE) { - // Restrict to client port and world streams. - sprintf(filter_buf, - "udp and (portrange 9000-9007 or port 9876 or port %d) and ether host %s and ether proto 0x0800 and not broadcast and not multicast", - client_port, hostname); + if (hostname && strlen(hostname) && strcmp(hostname, AUTOMATIC_CLIENT_IP) != 0) + // host was specified/detected + pfb += sprintf(pfb, " and host %s", hostname); } - else if (address_type == MAC_ADDRESS_TYPE && zone_port) + else if (address_type == MAC_ADDRESS_TYPE) { - // Restrict to zone port and world streams. - sprintf(filter_buf, - "udp and (portrange 9000-9007 or port 9876 or port %d) and ether host %s and ether proto 0x0800 and not broadcast and not multicast", - zone_port, hostname); + if (hostname && strlen(hostname) && strcmp(hostname, AUTOMATIC_CLIENT_IP) != 0) + // mac was specified + pfb += sprintf(pfb, " and ether host %s", hostname); } - else if (hostname != NULL && !client_port && !zone_port) + else if (address_type == DEFAULT_ADDRESS_TYPE) { - // Leave wide open. - sprintf(filter_buf, - "udp[0:2] > 1024 and udp[2:2] > 1024 and ether proto 0x0800 and host %s and not broadcast and not multicast", - hostname); + //don't specify IP or MAC address in filter string } else { - // Not even a hostname. Leave really wide open! - seqInfo("Filtering packets on device %s, searching for EQ client...", - device); - sprintf(filter_buf, - "udp[0:2] > 1024 and udp[2:2] > 1024 and ether proto 0x0800 and not broadcast and not multicast"); + seqFatal("pcap_error:filter_string: unknown address_type (%d)", address_type); + exit(0); } + //restrict to ipv4, and ignore broad/multi-cast packets + pfb += sprintf(pfb, " and ether proto 0x800 and not broadcast and not multicast"); + + seqInfo("Filtering packets on device %s", device); + if (pcap_compile (m_pcache_pcap, &bpp, filter_buf, 1, net) == -1) { seqWarn("%s",filter_buf); Modified: showeq/trunk/src/packetcapture.h =================================================================== --- showeq/trunk/src/packetcapture.h 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/packetcapture.h 2024-08-21 19:57:04 UTC (rev 1516) @@ -1,6 +1,6 @@ /* * packetcapture.h - * Copyright 2000-2006, 2019 by the respective ShowEQ Developers + * Copyright 2000-2024 by the respective ShowEQ Developers * Portions Copyright 2001-2003 Zaphod (do...@us...). * * This file is part of ShowEQ. @@ -36,6 +36,7 @@ #include <QString> +#include "packetcaptureprovider.h" #include "packetcommon.h" @@ -50,51 +51,43 @@ //---------------------------------------------------------------------- // PacketCaptureThread -class PacketCaptureThread +class PacketCaptureThread : public PacketCaptureProviderThread { - public: - PacketCaptureThread(); - ~PacketCaptureThread(); + public: + PacketCaptureThread(); + ~PacketCaptureThread(); - // Set the playback speed for offline packet capture. Valid values - // are -1-9, 1 is 1x, 2 is 2x, etc. -1 is paused. 0 is as fast as - // possible (no throttle) - void setPlaybackSpeed(int playbackSpeed); - int getPlaybackSpeed() { return (m_playbackSpeed == 100 ? 0 : m_playbackSpeed); } + bool offlinePlaybackSupported() { return true; } - void start (const char *device, const char *host, bool realtime, uint8_t address_type); - void startOffline(const char* filename, int playbackSpeed); - void stop (); - uint16_t getPacket (unsigned char *buff); - void setFilter (const char *device, const char *hostname, bool realtime, - uint8_t address_type, uint16_t zone_server_port, uint16_t client_port); - const QString getFilter(); - - private: - static void* loop(void *param); - static void packetCallBack(u_char * param, const struct pcap_pkthdr *ph, const u_char *data); + // Set the playback speed for offline packet capture. Valid values + // are -1-9, 1 is 1x, 2 is 2x, etc. -1 is paused. 0 is as fast as + // possible (no throttle) + void setPlaybackSpeed(int playbackSpeed); + int getPlaybackSpeed() { return (m_playbackSpeed == 100 ? 0 : m_playbackSpeed); } - struct packetCache - { - struct packetCache *next; - ssize_t len; - unsigned char data[0]; - }; - struct packetCache *m_pcache_first; - struct packetCache *m_pcache_last; - bool m_pcache_closed; + void start (const char *device, const char *host, bool realtime, uint8_t address_type); + void startOffline(const char* filename, int playbackSpeed); + void stop (); - pthread_t m_tid; - pthread_mutex_t m_pcache_mutex; + //moved to base class + //uint16_t getPacket (unsigned char *buff); - pcap_t *m_pcache_pcap; + void setFilter (const char *device, const char *hostname, bool realtime, + uint8_t address_type, uint16_t zone_server_port, uint16_t client_port); + const QString getFilter(); - QString m_pcapFilter; + private: + static void* loop(void *param); + static void packetCallBack(u_char * param, const struct pcap_pkthdr *ph, const u_char *data); - // Playback controls for offline file processing - int m_playbackSpeed; // -1=paused, 0=max, 1=1x speed, 2=2x speed, up to 9 - timeval m_tvLastProcessedActual; - timeval m_tvLastProcessedOriginal; + pcap_t *m_pcache_pcap; + + QString m_pcapFilter; + + // Playback controls for offline file processing + int m_playbackSpeed; // -1=paused, 0=max, 1=1x speed, 2=2x speed, up to 9 + timeval m_tvLastProcessedActual; + timeval m_tvLastProcessedOriginal; }; #endif // _PACKETCAPTURE_H_ Added: showeq/trunk/src/packetcaptureprovider.cpp =================================================================== --- showeq/trunk/src/packetcaptureprovider.cpp (rev 0) +++ showeq/trunk/src/packetcaptureprovider.cpp 2024-08-21 19:57:04 UTC (rev 1516) @@ -0,0 +1,89 @@ +/* + * packetcaptureprovider.cpp + * Copyright 2000-2024 by the respective ShowEQ Developers + * + * This file is part of ShowEQ. + * http://www.sourceforge.net/projects/seq + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#include "packetcaptureprovider.h" + + +PacketCaptureProviderThread::PacketCaptureProviderThread() : + m_pcache_first(NULL), + m_pcache_last(NULL), + m_pcache_closed(true) +{ + pthread_mutex_init(&m_pcache_mutex, NULL); +} + +PacketCaptureProviderThread::~PacketCaptureProviderThread() +{ + // Drop the packets we have lying around + pthread_mutex_lock (&m_pcache_mutex); + + struct packetCache *pc = m_pcache_first; + struct packetCache* freeMe = NULL; + + while (pc) + { + freeMe = pc; + pc = pc->next; + + free(freeMe); + } + + m_pcache_first = NULL; + m_pcache_last = NULL; + m_pcache_closed = true; + + pthread_mutex_unlock (&m_pcache_mutex); + + pthread_mutex_destroy(&m_pcache_mutex); + +} + +uint16_t PacketCaptureProviderThread::getPacket (unsigned char *buf) +{ + uint16_t ret; + struct packetCache *pc = NULL; + + pthread_mutex_lock (&m_pcache_mutex); + + ret = 0; + + pc = m_pcache_first; + + if (pc) + { + m_pcache_first = pc->next; + + if (!m_pcache_first) + m_pcache_last = NULL; + } + + pthread_mutex_unlock (&m_pcache_mutex); + + if (pc) + { + ret = pc->len; + memcpy (buf, pc->data, ret); + free (pc); + } + + return ret; +} Added: showeq/trunk/src/packetcaptureprovider.h =================================================================== --- showeq/trunk/src/packetcaptureprovider.h (rev 0) +++ showeq/trunk/src/packetcaptureprovider.h 2024-08-21 19:57:04 UTC (rev 1516) @@ -0,0 +1,68 @@ +/* + * packetcaptureprovider.h + * Copyright 2000-2024 by the respective ShowEQ Developers + * + * This file is part of ShowEQ. + * http://www.sourceforge.net/projects/seq + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#ifndef _PACKETCAPTUREPROVIDERTHREAD_H_ +#define _PACKETCAPTUREPROVIDERTHREAD_H_ + +#include <cstdint> +#include <QString> + +class PacketCaptureProviderThread +{ + public: + PacketCaptureProviderThread(); + virtual ~PacketCaptureProviderThread(); + + virtual bool offlinePlaybackSupported() = 0; + virtual void startOffline(const char* filename, int playbackSpeed) = 0; + virtual void setPlaybackSpeed(int playbackSpeed) = 0; + virtual int getPlaybackSpeed() = 0; + + virtual void start (const char *device, const char *host, bool realtime, uint8_t address_type) = 0; + virtual void stop () = 0; + + virtual uint16_t getPacket (unsigned char *buf); + + virtual void setFilter (const char *device, const char *hostname, bool realtime, + uint8_t address_type, uint16_t zone_server_port, uint16_t client_port) = 0; + virtual const QString getFilter() = 0; + + + protected: + + struct packetCache + { + struct packetCache *next; + ssize_t len; + unsigned char data[0]; + }; + struct packetCache *m_pcache_first; + struct packetCache *m_pcache_last; + bool m_pcache_closed; + + pthread_t m_tid; + pthread_mutex_t m_pcache_mutex; + +}; + +#endif + Modified: showeq/trunk/src/packetcommon.h =================================================================== --- showeq/trunk/src/packetcommon.h 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/packetcommon.h 2024-08-21 19:57:04 UTC (rev 1516) @@ -46,11 +46,20 @@ #include <endian.h> #endif +#include <netdb.h> //---------------------------------------------------------------------- // Constants const char* const AUTOMATIC_CLIENT_IP = "127.0.0.0"; +const in_port_t WorldServerGeneralMinPort = 9000; +const in_port_t WorldServerGeneralMaxPort = 9015; +const in_port_t WorldServerChatPort = 9876; +const in_port_t WorldServerChat2Port = 9875; // xgame tells, mail +const in_port_t LoginServerMinPort = 15900; +const in_port_t LoginServerMaxPort = 15910; +const in_port_t ChatServerPort = 5998; + // Preference constants for VPacket.Playback. #define PLAYBACK_OFF 0 #define PLAYBACK_FORMAT_SEQ 1 Modified: showeq/trunk/src/packetstream.cpp =================================================================== --- showeq/trunk/src/packetstream.cpp 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/packetstream.cpp 2024-08-21 19:57:04 UTC (rev 1516) @@ -92,6 +92,7 @@ m_sessionId(0), m_sessionKey(0), m_sessionClientPort(0), + m_sessionClientIP(0), m_maxLength(0), m_decodeKey(0), m_validKey(true) @@ -196,6 +197,7 @@ m_arqSeqExp = 0; m_arqSeqFound = false; m_sessionClientPort = 0; + m_sessionClientIP = 0; m_sessionId = 0; m_sessionKey = 0; } @@ -543,9 +545,11 @@ // Only accept packets that correspond to our latched client port, if // it is set. This helps filter out multiple sessions on the same physical // host when two eq clients zone at the same time. The first one will win. - if (m_sessionClientPort != 0 && + if (m_sessionClientPort != 0 && m_sessionClientIP != 0 && ((dir() == DIR_Server && m_sessionClientPort != packet.getDestPort()) || - (dir() == DIR_Client && m_sessionClientPort != packet.getSourcePort()))) + (dir() == DIR_Client && m_sessionClientPort != packet.getSourcePort()) || + (dir() == DIR_Server && m_sessionClientIP != packet.getIPv4DestN()) || + (dir() == DIR_Client && m_sessionClientIP != packet.getIPv4SourceN()))) { #if (defined(PACKET_PROCESS_DIAG) && (PACKET_PROCESS_DIAG > 1)) || (defined(PACKET_SESSION_DIAG) && PACKET_SESSION_DIAG > 1) seqDebug("discarding packet %s:%d ==>%s:%d netopcode=%04x size=%d. Multiple sessions on the same box? Ignoring all but one of them. Latched client port %d. Session tracking %s.", @@ -1038,6 +1042,7 @@ // later. SessionRequest should always be an outer protocol packet // so we can cast it to EQUDPIPPacketFormat to get the ip headers. m_sessionClientPort = ((EQUDPIPPacketFormat&) packet).getSourcePort(); + m_sessionClientIP = ((EQUDPIPPacketFormat&) packet).getIPv4SourceN(); } } break; @@ -1132,6 +1137,7 @@ // later. SessionRequest should always be an outer protocol packet // so we can cast it to EQUDPIPPacketFormat to get the ip headers. m_sessionClientPort = ((EQUDPIPPacketFormat&) packet).getDestPort(); + m_sessionClientIP = ((EQUDPIPPacketFormat&) packet).getIPv4DestN(); // If this is the world server talking to us, reset session tracking if // it is on so we unlatch the client in case of getting kicked. @@ -1149,8 +1155,9 @@ // headers! m_session_tracking_enabled = 2; - emit lockOnClient(((EQUDPIPPacketFormat&) packet).getSourcePort(), - ((EQUDPIPPacketFormat&) packet).getDestPort()); + emit lockOnClient(((EQUDPIPPacketFormat&) packet).getSourcePort(), + ((EQUDPIPPacketFormat&) packet).getDestPort(), + ((EQUDPIPPacketFormat&) packet).getIPv4DestN()); emit sessionTrackingChanged(m_session_tracking_enabled); } } @@ -1200,6 +1207,7 @@ emit sessionTrackingChanged(m_session_tracking_enabled); m_sessionClientPort = 0; + m_sessionClientIP = 0; } emit closing(m_sessionId, m_streamid); Modified: showeq/trunk/src/packetstream.h =================================================================== --- showeq/trunk/src/packetstream.h 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/packetstream.h 2024-08-21 19:57:04 UTC (rev 1516) @@ -112,7 +112,7 @@ // this signals a change in the session tracking state void sessionTrackingChanged(uint8_t); - void lockOnClient(in_port_t serverPort, in_port_t clientPort); + void lockOnClient(in_port_t serverPort, in_port_t clientPort, in_addr_t clientAddr); // Signal a new session key being received void sessionKey(uint32_t sessionId, EQStreamID streadid, uint32_t sessionKey); @@ -155,6 +155,7 @@ uint32_t m_sessionId; uint32_t m_sessionKey; in_port_t m_sessionClientPort; + in_addr_t m_sessionClientIP; uint32_t m_maxLength; // encryption Modified: showeq/trunk/src/util.cpp =================================================================== --- showeq/trunk/src/util.cpp 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/util.cpp 2024-08-21 19:57:04 UTC (rev 1516) @@ -29,6 +29,7 @@ #include <cstdio> #include <cstring> #include <sys/time.h> +#include <ifaddrs.h> #include <QColor> #include <QFileInfo> @@ -1044,3 +1045,32 @@ return crc ^ 0xffffffffL; } + +QStringList enumerateNetworkDevices() +{ + struct ifaddrs *ifaddr, *ifa; + int n; + QStringList devices; + + if (getifaddrs(&ifaddr) == -1) + { + seqWarn("Could not enumerate network devices"); + return QStringList(); + } + + for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) + { + if (ifa->ifa_addr == NULL) + continue; + + if (ifa->ifa_addr->sa_family == AF_INET) + devices.append(ifa->ifa_name); + } + + freeifaddrs(ifaddr); + + return devices; +} + + + Modified: showeq/trunk/src/util.h =================================================================== --- showeq/trunk/src/util.h 2024-08-21 19:56:56 UTC (rev 1515) +++ showeq/trunk/src/util.h 2024-08-21 19:57:04 UTC (rev 1516) @@ -82,6 +82,8 @@ uint32_t calcCRC32(const uint8_t* p, uint32_t length); uint16_t calcCRC16(uint8_t* p, uint32_t length, uint32_t seed); +QStringList enumerateNetworkDevices(); + // Templatized function to generate a string representing the bit pattern // of the passed in value. // Note: For use with integral data types. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-21 19:56:59
|
Revision: 1515 http://sourceforge.net/p/seq/svn/1515 Author: cn187 Date: 2024-08-21 19:56:56 +0000 (Wed, 21 Aug 2024) Log Message: ----------- Fixes for player-controlled external entity detection and updates, and related crash Modified Paths: -------------- showeq/trunk/src/player.cpp showeq/trunk/src/player.h showeq/trunk/src/spawnshell.cpp showeq/trunk/src/spawnshell.h Modified: showeq/trunk/src/player.cpp =================================================================== --- showeq/trunk/src/player.cpp 2024-08-21 19:56:50 UTC (rev 1514) +++ showeq/trunk/src/player.cpp 2024-08-21 19:56:56 UTC (rev 1515) @@ -833,15 +833,27 @@ clear(); } -void Player::playerUpdateSelf(const uint8_t* data, size_t, uint8_t dir) +void Player::playerUpdateSelf(const uint8_t* data, size_t len, uint8_t dir) { const playerSelfPosStruct *pupdate = (const playerSelfPosStruct*)data; if ((dir != DIR_Client) && (pupdate->spawnId != id())) return; - else if (dir == DIR_Client) - setPlayerID(pupdate->spawnId); + if (dir == DIR_Client && id() == 0) + setPlayerID(pupdate->spawnId); + // When casting Eye of Zomm, using a row boat, or doing something else + // where you're controlling another spawn, the client will send multiple + // update packets, one for with your player spawn ID, and the other + // with the ID of the other object. So we can't assume that if the + // id changes, we can automatically update the player's ID like we used to. + // Instead, we'll pass the other ID to spawnshell for handling + if (pupdate->spawnId != id()) + { + emit playerUpdate(data, len, dir); + return; + } + int16_t py = int16_t(pupdate->y); int16_t px = int16_t(pupdate->x); int16_t pz = int16_t(pupdate->z); @@ -968,9 +980,10 @@ { if (id() != playerID) { + uint16_t old_id = id(); seqInfo("Your player's id is %i", playerID); setID(playerID); - emit changedID(id()); + emit changedID(old_id, id()); updateLastChanged(); emit changeItem(this, tSpawnChangedALL); } Modified: showeq/trunk/src/player.h =================================================================== --- showeq/trunk/src/player.h 2024-08-21 19:56:50 UTC (rev 1514) +++ showeq/trunk/src/player.h 2024-08-21 19:56:56 UTC (rev 1515) @@ -200,7 +200,7 @@ void stamChanged ( int, int, int, int); void hpChanged(int16_t, int16_t); - void changedID(uint16_t playerID); + void changedID(uint16_t oldPlayerID, uint16_t newPlayerID); void posChanged(int16_t x, int16_t y, int16_t z, int16_t deltaX, int16_t deltaY, int16_t deltaZ, int32_t heading); @@ -208,6 +208,7 @@ void headingChanged(int32_t heading); void levelChanged(uint8_t level); void guildChanged(); + void playerUpdate(const uint8_t* data, size_t len, uint8_t dir); protected: void fillConTable(); Modified: showeq/trunk/src/spawnshell.cpp =================================================================== --- showeq/trunk/src/spawnshell.cpp 2024-08-21 19:56:50 UTC (rev 1514) +++ showeq/trunk/src/spawnshell.cpp 2024-08-21 19:56:56 UTC (rev 1515) @@ -145,10 +145,12 @@ // connect Player signals to SpawnShell signals connect(m_player, SIGNAL(changeItem(const Item*, uint32_t)), this, SIGNAL(changeItem(const Item*, uint32_t))); + connect(m_player, SIGNAL(playerUpdate(const uint8_t*, size_t, uint8_t)), + this, SLOT(playerUpdate2(const uint8_t*, size_t, uint8_t))); // connect Player signals to SpawnShell slots - connect(m_player, SIGNAL(changedID(uint16_t)), - this, SLOT(playerChangedID(uint16_t))); + connect(m_player, SIGNAL(changedID(uint16_t, uint16_t)), + this, SLOT(playerChangedID(uint16_t, uint16_t))); // connect to guildmgr to receive notifications of guild tag updates connect(m_guildMgr, SIGNAL(guildTagUpdated(uint32_t)), @@ -862,6 +864,7 @@ if(!strcmp(spawn->name,m_player->realName().toLatin1().data())) { // Multiple zoneEntry packets are received for your spawn after you zone + m_player->setPlayerID(spawn->spawnId); m_player->update(spawn); emit changeItem(m_player, tSpawnChangedALL); } @@ -964,6 +967,29 @@ } } +void SpawnShell::playerUpdate2(const uint8_t* data, size_t len, uint8_t dir) +{ + if (m_zoneMgr->isZoning()) + return; + + //This payload is normally handled by Player::playerUpdateSelf, + //but sometimes it contains an update for a different spawn, such as + //an Eye of Zomm cast by the player, a rowboat being controlled by the + //player, etc. So in that case, we'll handle it. + const playerSelfPosStruct *pupdate = (const playerSelfPosStruct *)data; + + int16_t py = int16_t(pupdate->y); + int16_t px = int16_t(pupdate->x); + int16_t pz = int16_t(pupdate->z); + int16_t pdeltaX = int16_t(pupdate->deltaX); + int16_t pdeltaY = int16_t(pupdate->deltaY); + int16_t pdeltaZ = int16_t(pupdate->deltaZ); + + + updateSpawn(pupdate->spawnId, px, py, pz, pdeltaX, pdeltaY, pdeltaZ, + pupdate->heading, pupdate->deltaHeading, pupdate->animation); +} + void SpawnShell::playerUpdate(const uint8_t* data, size_t len, uint8_t dir) { // if zoning, then don't do anything @@ -1667,14 +1693,23 @@ } } -void SpawnShell::playerChangedID(uint16_t playerID) +void SpawnShell::playerChangedID(uint16_t oldPlayerID, uint16_t newPlayerID) { // remove the player from the list (if it had a 0 id) - m_players.take(0); + deleteItem(tPlayer, 0); + if (oldPlayerID == newPlayerID) + return; + + //remove the old player + deleteItem(tPlayer, oldPlayerID); + + + //if the new ID already exists an unknown spawn + deleteItem(tSpawn, newPlayerID); + // re-insert the player into the list - delete m_players.take(playerID); - m_players.insert(playerID, m_player); + m_players.insert(newPlayerID, m_player); emit changeItem(m_player, tSpawnChangedALL); } Modified: showeq/trunk/src/spawnshell.h =================================================================== --- showeq/trunk/src/spawnshell.h 2024-08-21 19:56:50 UTC (rev 1514) +++ showeq/trunk/src/spawnshell.h 2024-08-21 19:56:56 UTC (rev 1515) @@ -122,6 +122,7 @@ void zoneEntry(const uint8_t* spawn, size_t len); void newSpawn(const uint8_t* spawn); void newSpawn(const spawnStruct& s); + void playerUpdate2(const uint8_t*pupdate, size_t, uint8_t); void playerUpdate(const uint8_t*pupdate, size_t, uint8_t); void npcMoveUpdate(const uint8_t*npcupdate, size_t, uint8_t); void updateSpawn(uint16_t id, @@ -144,7 +145,7 @@ void respawnFromHover(const uint8_t* respawn, size_t len, uint8_t dir); void corpseLoc(const uint8_t* corpseLoc); - void playerChangedID(uint16_t playerID); + void playerChangedID(uint16_t oldPlayerID, uint16_t newPlayerID); void refilterSpawns(); void refilterSpawnsRuntime(); void saveSpawns(void); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-21 19:56:51
|
Revision: 1514 http://sourceforge.net/p/seq/svn/1514 Author: cn187 Date: 2024-08-21 19:56:50 +0000 (Wed, 21 Aug 2024) Log Message: ----------- Improvements to column sort/reorder/hide behavior Modified Paths: -------------- showeq/trunk/src/seqlistview.cpp showeq/trunk/src/seqlistview.h Modified: showeq/trunk/src/seqlistview.cpp =================================================================== --- showeq/trunk/src/seqlistview.cpp 2024-08-19 01:31:27 UTC (rev 1513) +++ showeq/trunk/src/seqlistview.cpp 2024-08-21 19:56:50 UTC (rev 1514) @@ -51,8 +51,11 @@ setSelectionMode(QAbstractItemView::SingleSelection); setSelectionBehavior(QAbstractItemView::SelectRows); - // don't stretch the last column, otherwise we can't hide it - header()->setStretchLastSection(false); +#if (QT_VERSION >= QT_VERSION_CHECK(5,11,0)) + header()->setFirstSectionMovable(true); + connect(header(), SIGNAL(sortIndicatorChanged(int, Qt::SortOrder)), this, SLOT(setSorting(int, Qt::SortOrder))); +#endif + } SEQListView::~SEQListView() @@ -119,6 +122,13 @@ sortByColumn(column, increasing ? Qt::AscendingOrder : Qt::DescendingOrder); } +void SEQListView::setSorting(int column, Qt::SortOrder order) +{ + m_sortColumn = column; + m_sortIncreasing = (order == Qt::AscendingOrder) ? true : false; + sortByColumn(column, order); +} + void SEQListView::savePrefs() { // only save the preferences if visible @@ -134,7 +144,7 @@ { columnName = columnPreferenceName(i); width = columnWidth(i); - if (width != 0) + if (!header()->isSectionHidden(i) && width != 0) { pSEQPrefs->setPrefInt(columnName + "Width", preferenceName(), width); pSEQPrefs->setPrefBool(show + columnName, preferenceName(), true); @@ -202,6 +212,7 @@ #endif header()->resizeSection(i, width); setColumnWidth(i, width); + header()->setSectionHidden(i, false); } else { @@ -213,6 +224,7 @@ #endif header()->resizeSection(i, 0); setColumnWidth(i, 0); + header()->setSectionHidden(i, true); } } @@ -274,6 +286,9 @@ header()->resizeSection(column, width); setColumnWidth(column, width); + header()->setSectionHidden(column, !visible); + + // set the the preferences as to if the column is shown pSEQPrefs->setPrefBool(QString("Show") + columnName, preferenceName(), (width != 0)); Modified: showeq/trunk/src/seqlistview.h =================================================================== --- showeq/trunk/src/seqlistview.h 2024-08-19 01:31:27 UTC (rev 1513) +++ showeq/trunk/src/seqlistview.h 2024-08-21 19:56:50 UTC (rev 1514) @@ -69,6 +69,7 @@ virtual void restoreColumns(void); virtual void savePrefs(void); void setColumnVisible(int column, bool visible); + virtual void setSorting(int column, Qt::SortOrder order); void mousePressEvent(QMouseEvent* event); signals: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-19 01:31:29
|
Revision: 1513 http://sourceforge.net/p/seq/svn/1513 Author: cn187 Date: 2024-08-19 01:31:27 +0000 (Mon, 19 Aug 2024) Log Message: ----------- Increase max level to 125 for Character menu Modified Paths: -------------- showeq/branches/cn187_devel/src/interface.cpp Modified: showeq/branches/cn187_devel/src/interface.cpp =================================================================== --- showeq/branches/cn187_devel/src/interface.cpp 2024-08-19 01:31:19 UTC (rev 1512) +++ showeq/branches/cn187_devel/src/interface.cpp 2024-08-19 01:31:27 UTC (rev 1513) @@ -2137,7 +2137,7 @@ m_levelSpinBox = new QSpinBox(this); m_levelSpinBox->setObjectName("m_levelSpinBox"); m_levelSpinBox->setMinimum(1); - m_levelSpinBox->setMaximum(115); + m_levelSpinBox->setMaximum(125); m_levelSpinBox->setSingleStep(1); QWidgetAction* levelSpinBoxAction = new QWidgetAction(m_charLevelMenu); levelSpinBoxAction->setDefaultWidget(m_levelSpinBox); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-19 01:31:22
|
Revision: 1512 http://sourceforge.net/p/seq/svn/1512 Author: cn187 Date: 2024-08-19 01:31:19 +0000 (Mon, 19 Aug 2024) Log Message: ----------- Fix miscellaneous compiler warnings Modified Paths: -------------- showeq/branches/cn187_devel/src/combatlog.cpp showeq/branches/cn187_devel/src/editor.cpp showeq/branches/cn187_devel/src/experiencelog.cpp showeq/branches/cn187_devel/src/interface.cpp showeq/branches/cn187_devel/src/map.cpp showeq/branches/cn187_devel/src/mapcore.cpp showeq/branches/cn187_devel/src/mapicondialog.ui showeq/branches/cn187_devel/src/messagewindow.cpp showeq/branches/cn187_devel/src/spawnlistcommon.cpp showeq/branches/cn187_devel/src/spawnpointlist.cpp showeq/branches/cn187_devel/src/xmlconv.cpp Modified: showeq/branches/cn187_devel/src/combatlog.cpp =================================================================== --- showeq/branches/cn187_devel/src/combatlog.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/combatlog.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -1074,6 +1074,21 @@ void CombatWindow::clearMob() { +#if (QT_VERSION >= QT_VERSION_CHECK(4,2,0)) + switch( QMessageBox::information( this, "ShowEQ", + "This function will clear all data listed on the mob " + "tab. Do you want to continue?", + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel)) + { + case QMessageBox::Ok: + qDeleteAll(m_combat_mob_list); + m_combat_mob_list.clear(); + updateMob(); + break; + default: + break; + } +#else switch( QMessageBox::information( this, "ShowEQ", "This function will clear all data listed on the mob " "tab. Do you want to continue?", @@ -1087,10 +1102,26 @@ default: break; } +#endif } void CombatWindow::clearOffense() { +#if (QT_VERSION >= QT_VERSION_CHECK(4,2,0)) + switch( QMessageBox::information( this, "ShowEQ", + "This function will clear all data listed on the offense " + "tab. Do you want to continue?", + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel)) + { + case QMessageBox::Ok: + qDeleteAll(m_combat_offense_list); + m_combat_offense_list.clear(); + updateOffense(); + break; + default: + break; + } +#else switch( QMessageBox::information( this, "ShowEQ", "This function will clear all data listed on the offense " "tab. Do you want to continue?", @@ -1104,6 +1135,7 @@ default: break; } +#endif } void CombatWindow::clear(void) Modified: showeq/branches/cn187_devel/src/editor.cpp =================================================================== --- showeq/branches/cn187_devel/src/editor.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/editor.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -173,9 +173,30 @@ return; } +#if (QT_VERSION >= QT_VERSION_CHECK(4, 2, 0)) switch( QMessageBox::information( this, "ShowEQ Editor", "The document has been changed since " "the last save.", + QMessageBox::Save | + QMessageBox::Cancel | + QMessageBox::Discard, + QMessageBox::Save)) { + case QMessageBox::Save: + save(); + ce->accept(); + break; + case QMessageBox::Cancel: + default: // just for sanity + ce->ignore(); + break; + case QMessageBox::Discard: + ce->accept(); + break; + } +#else + switch( QMessageBox::information( this, "ShowEQ Editor", + "The document has been changed since " + "the last save.", "Save Now", "Cancel", "Lose Changes", 0, 1 ) ) { case 0: @@ -187,9 +208,10 @@ ce->ignore(); break; case 2: - ce->accept(); - break; - } + ce->accept(); + break; + } +#endif } #ifndef QMAKEBUILD Modified: showeq/branches/cn187_devel/src/experiencelog.cpp =================================================================== --- showeq/branches/cn187_devel/src/experiencelog.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/experiencelog.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -670,6 +670,15 @@ void ExperienceWindow::viewClear() { +#if (QT_VERSION >= QT_VERSION_CHECK(4,2,0)) + if (QMessageBox::information(this, "ShowEQ", + "This function will clear all data listed in the experience " + "log. Do you want to continue?", + QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel) == QMessageBox::Ok) + { + clear(); + } +#else if (QMessageBox::information( this, "ShowEQ", "This function will clear all data listed in the experience " "log. Do you want to continue?", @@ -677,6 +686,7 @@ { clear(); } +#endif } void ExperienceWindow::clear(void) Modified: showeq/branches/cn187_devel/src/interface.cpp =================================================================== --- showeq/branches/cn187_devel/src/interface.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/interface.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -1254,8 +1254,28 @@ // File Menu QMenu* pFileMenu = new QMenu("&File"); menuBar()->addMenu(pFileMenu); - pFileMenu->addAction("&Save Preferences", this, SLOT(savePrefs()), - Qt::CTRL|Qt::Key_S); +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + pFileMenu->addAction("&Save Preferences", Qt::CTRL|Qt::Key_S, this, SLOT(savePrefs())); + pFileMenu->addAction("Open &Map", Qt::Key_F1, m_mapMgr, SLOT(loadMap())); + pFileMenu->addAction("&Import &Map", m_mapMgr, SLOT(importMap())); + pFileMenu->addAction("Sa&ve Map", Qt::Key_F2, m_mapMgr, SLOT(saveMap())); + pFileMenu->addAction("Save SOE Map", m_mapMgr, SLOT(saveSOEMap())); + pFileMenu->addAction("Reload Guilds File", m_guildmgr, SLOT(readGuildList())); + pFileMenu->addAction("Save Guilds File", m_guildmgr, SLOT(writeGuildList())); + pFileMenu->addAction("Add Spawn Category", Qt::ALT|Qt::Key_C, this, SLOT(addCategory())); + pFileMenu->addAction("Rebuild SpawnList", Qt::ALT|Qt::Key_R, this, SLOT(rebuildSpawnList())); + pFileMenu->addAction("Reload Categories", Qt::CTRL|Qt::Key_R, this, SLOT(reloadCategories())); + pFileMenu->addAction("Select Next", Qt::CTRL|Qt::Key_Right, this, SLOT(selectNext())); + pFileMenu->addAction("Select Prev", Qt::CTRL|Qt::Key_Left, this, SLOT(selectPrev())); + pFileMenu->addAction("Save Selected Spawns Path", this, SLOT(saveSelectedSpawnPath(void))); + pFileMenu->addAction("Save NPC Spawn Paths", this, SLOT(saveSpawnPaths(void))); + if (m_packet->playbackPackets() != PLAYBACK_OFF) + { + pFileMenu->addAction("Inc Playback Speed", Qt::CTRL|Qt::Key_X, m_packet, SLOT(incPlayback())); + pFileMenu->addAction("Dec Playback Speed", Qt::CTRL|Qt::Key_Z, m_packet, SLOT(decPlayback())); + } +#else + pFileMenu->addAction("&Save Preferences", this, SLOT(savePrefs()), Qt::CTRL|Qt::Key_S); pFileMenu->addAction("Open &Map", m_mapMgr, SLOT(loadMap()), Qt::Key_F1); pFileMenu->addAction("&Import &Map", m_mapMgr, SLOT(importMap())); pFileMenu->addAction("Sa&ve Map", m_mapMgr, SLOT(saveMap()), Qt::Key_F2); @@ -1282,6 +1302,7 @@ pFileMenu->addAction("Dec Playback Speed", m_packet, SLOT(decPlayback()), Qt::CTRL|Qt::Key_Z); } +#endif pFileMenu->addAction("&Quit", qApp, SLOT(quit())); } @@ -1960,6 +1981,39 @@ QMenu* pLogMenu = new QMenu("Lo&g"); m_netMenu->addMenu(pLogMenu); +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + m_action_log_AllPackets = pLogMenu->addAction("All Packets", Qt::Key_F5, + this, SLOT(toggle_log_AllPackets())); + m_action_log_AllPackets->setCheckable(true); + m_action_log_AllPackets->setChecked(m_globalLog != 0); + + m_action_log_WorldData = pLogMenu->addAction("World Data", Qt::Key_F6, + this, SLOT(toggle_log_WorldData())); + m_action_log_WorldData->setCheckable(true); + m_action_log_WorldData->setChecked(m_worldLog != 0); + + m_action_log_ZoneData = pLogMenu->addAction("Zone Data", Qt::Key_F7, + this, SLOT(toggle_log_ZoneData())); + m_action_log_ZoneData->setCheckable(true); + m_action_log_ZoneData->setChecked(m_zoneLog != 0); + + m_action_log_UnknownData = pLogMenu->addAction("Unknown Data", Qt::Key_F8, + this, SLOT(toggle_log_UnknownData())); + m_action_log_UnknownData->setCheckable(true); + m_action_log_UnknownData->setChecked(m_unknownZoneLog != 0); + + m_action_view_UnknownData = pLogMenu->addAction("View Unknown Data", Qt::Key_F9, + this, SLOT(toggle_view_UnknownData())); + m_action_view_UnknownData->setCheckable(true); + m_action_view_UnknownData->setChecked(pSEQPrefs->getPrefBool("ViewUnknown", + "PacketLogging", false)); + + m_action_log_RawData = pLogMenu->addAction("Raw Data", Qt::Key_F10, + this, SLOT(toggle_log_RawData())); + m_action_log_RawData->setCheckable(true); + m_action_log_RawData->setChecked(pSEQPrefs->getPrefBool("LogRawPackets", + "PacketLogging", false)); +#else m_action_log_AllPackets = pLogMenu->addAction("All Packets", this, SLOT(toggle_log_AllPackets()), Qt::Key_F5); m_action_log_AllPackets->setCheckable(true); @@ -1991,6 +2045,7 @@ m_action_log_RawData->setCheckable(true); m_action_log_RawData->setChecked(pSEQPrefs->getPrefBool("LogRawPackets", "PacketLogging", false)); +#endif m_filterZoneDataMenu = new QMenu("Filter Zone Data"); pLogMenu->addMenu(m_filterZoneDataMenu); @@ -2008,6 +2063,18 @@ QMenu* pOpCodeMenu = new QMenu("OpCode Monitor"); m_netMenu->addMenu(pOpCodeMenu); +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + m_action_opcode_monitor = pOpCodeMenu->addAction("&OpCode Monitoring", + Qt::CTRL|Qt::ALT|Qt::Key_O, + this, SLOT(toggle_opcode_monitoring())); + m_action_opcode_monitor->setCheckable(true); + m_action_opcode_monitor->setChecked(m_opcodeMonitorLog != 0); + + pOpCodeMenu->addAction("&Reload Monitored OpCode List...", + Qt::CTRL|Qt::ALT|Qt::Key_R, + this, + SLOT(set_opcode_monitored_list())); +#else m_action_opcode_monitor = pOpCodeMenu->addAction("&OpCode Monitoring", this, SLOT(toggle_opcode_monitoring()), Qt::CTRL|Qt::ALT|Qt::Key_O); m_action_opcode_monitor->setCheckable(true); @@ -2015,6 +2082,7 @@ pOpCodeMenu->addAction("&Reload Monitored OpCode List...", this, SLOT(set_opcode_monitored_list()), Qt::CTRL|Qt::ALT|Qt::Key_R); +#endif QString section = "OpCodeMonitoring"; @@ -2133,6 +2201,22 @@ QMenu* filterMenu = new QMenu("Fi<ers"); menuBar()->addMenu(filterMenu); +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + filterMenu->addAction("&Reload Filters", Qt::Key_F3, m_filterMgr, SLOT(loadFilters())); + filterMenu->addAction("&Save Filters", Qt::Key_F4, m_filterMgr, SLOT(saveFilters())); + filterMenu->addAction("&Edit Filters", this, SLOT(launch_editor_filters())); + filterMenu->addAction("&Edit Filters XML", this, SLOT(launch_editor_filters())); + filterMenu->addAction("Select Fil&ter File", this, SLOT(select_filter_file())); + + filterMenu->addAction("Reload &Zone Filters", Qt::SHIFT|Qt::Key_F3, + m_filterMgr, SLOT(loadZoneFilters())); + filterMenu->addAction("S&ave Zone Filters", Qt::SHIFT|Qt::Key_F4, + m_filterMgr, SLOT(saveZoneFilters())); + filterMenu->addAction("Edit Zone Filters", this, + SLOT(launch_filterlistwindow_zoneFilters())); + filterMenu->addAction("Edit Zone Fi<ers XML", this, + SLOT(launch_editor_zoneFilters())); +#else filterMenu->addAction("&Reload Filters", m_filterMgr, SLOT(loadFilters()), Qt::Key_F3); filterMenu->addAction("&Save Filters", m_filterMgr, SLOT(saveFilters()), @@ -2149,6 +2233,7 @@ SLOT(launch_filterlistwindow_zoneFilters())); filterMenu->addAction("Edit Zone Fi<ers XML", this, SLOT(launch_editor_zoneFilters())); +#endif filterMenu->addAction("Re&filter Spawns", m_spawnShell, SLOT(refilterSpawns())); @@ -2621,7 +2706,25 @@ // Debug menu QMenu* pDebugMenu = new QMenu("&Debug"); menuBar()->addMenu(pDebugMenu); +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) pDebugMenu->addAction("List I&nterface", this, SLOT(listInterfaceInfo())); + pDebugMenu->addAction("List S&pawns", Qt::ALT|Qt::CTRL|Qt::Key_P, this, SLOT(listSpawns())); + pDebugMenu->addAction("List &Drops", Qt::ALT|Qt::CTRL|Qt::Key_D, this, SLOT(listDrops())); + pDebugMenu->addAction("List &Map Info", Qt::ALT|Qt::CTRL|Qt::Key_M, this, SLOT(listMapInfo())); + pDebugMenu->addAction("List G&uild Info", m_guildmgr, SLOT(listGuildInfo())); + pDebugMenu->addAction("List &Group", Qt::ALT|Qt::CTRL|Qt::Key_G, this, SLOT(listGroup())); + pDebugMenu->addAction("List Guild M&embers", Qt::ALT|Qt::CTRL|Qt::Key_E, this, SLOT(listGuild())); + pDebugMenu->addAction("Dump Spawns", Qt::ALT|Qt::SHIFT|Qt::CTRL|Qt::Key_P, this, SLOT(dumpSpawns())); + pDebugMenu->addAction("Dump Drops", Qt::ALT|Qt::SHIFT|Qt::CTRL|Qt::Key_D, this, SLOT(dumpDrops())); + pDebugMenu->addAction("Dump Map Info", Qt::ALT|Qt::SHIFT|Qt::CTRL|Qt::Key_M, this, SLOT(dumpMapInfo())); + pDebugMenu->addAction("Dump Guild Info", this , SLOT(dumpGuildInfo())); + pDebugMenu->addAction("Dump SpellBook Info", this , SLOT(dumpSpellBook())); + pDebugMenu->addAction("Dump Group", Qt::ALT|Qt::CTRL|Qt::SHIFT|Qt::Key_G, this, SLOT(dumpGroup())); + pDebugMenu->addAction("Dump Guild Members", Qt::ALT|Qt::CTRL|Qt::SHIFT|Qt::Key_E, this, SLOT(dumpGuild())); + pDebugMenu->addAction("List &Filters", Qt::ALT|Qt::CTRL|Qt::Key_F, m_filterMgr, SLOT(listFilters())); + pDebugMenu->addAction("List &Zone Filters", m_filterMgr, SLOT(listZoneFilters())); +#else + pDebugMenu->addAction("List I&nterface", this, SLOT(listInterfaceInfo())); pDebugMenu->addAction("List S&pawns", this, SLOT(listSpawns()), Qt::ALT|Qt::CTRL|Qt::Key_P); pDebugMenu->addAction("List &Drops", this, SLOT(listDrops()), Qt::ALT|Qt::CTRL|Qt::Key_D); pDebugMenu->addAction("List &Map Info", this, SLOT(listMapInfo()), Qt::ALT|Qt::CTRL|Qt::Key_M); @@ -2637,8 +2740,7 @@ pDebugMenu->addAction("Dump Guild Members", this, SLOT(dumpGuild()), Qt::ALT|Qt::CTRL|Qt::SHIFT|Qt::Key_E); pDebugMenu->addAction("List &Filters", m_filterMgr, SLOT(listFilters()), Qt::ALT|Qt::CTRL|Qt::Key_F); pDebugMenu->addAction("List &Zone Filters", m_filterMgr, SLOT(listZoneFilters())); - - +#endif } void EQInterface::createStatusBar() { @@ -3941,6 +4043,7 @@ EQInterface::launch_filterlistwindow_filters(void) { FilterListWindow * ew = new FilterListWindow(m_filterMgr->filterFile(), this); + ew->show(); } void @@ -3955,6 +4058,7 @@ EQInterface::launch_filterlistwindow_zoneFilters(void) { FilterListWindow * ew = new FilterListWindow(m_filterMgr->zoneFilterFile(), this); + ew->show(); } void Modified: showeq/branches/cn187_devel/src/map.cpp =================================================================== --- showeq/branches/cn187_devel/src/map.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/map.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -2155,7 +2155,11 @@ if (m_mapMgr->mapData().waypointActive()) { +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + QPoint clickpoint(m_param.invertXOffset(me->position().x()), m_param.invertYOffset(me->position().y())); +#else QPoint clickpoint(m_param.invertXOffset(me->x()), m_param.invertYOffset(me->y())); +#endif const MapPoint* closest_wp = m_mapMgr->mapData().closestWaypointToPoint2D(clickpoint, dist); if (closest_wp) { Modified: showeq/branches/cn187_devel/src/mapcore.cpp =================================================================== --- showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -1723,7 +1723,7 @@ if (wp_dist < closest_dist) { closest_dist = wp_dist; - closest_wp = wp_itr; + closest_wp = &(*wp_itr); } } return closest_wp; @@ -1741,7 +1741,7 @@ if (wp_dist < closest_dist) { closest_dist = wp_dist; - closest_wp = wp_itr; + closest_wp = &(*wp_itr); } } return closest_wp; Modified: showeq/branches/cn187_devel/src/mapicondialog.ui =================================================================== (Binary files differ) Modified: showeq/branches/cn187_devel/src/messagewindow.cpp =================================================================== --- showeq/branches/cn187_devel/src/messagewindow.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/messagewindow.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -659,6 +659,17 @@ SLOT(messageFilterDialog())); m_menu->addSeparator(); +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + m_menu->addAction("&Find...", Qt::CTRL|Qt::Key_F, this, SLOT(findDialog())); + m_menu->addSeparator(); + + m_action_lockText = m_menu->addAction("&Lock Text", Qt::CTRL|Qt::Key_L, + this, SLOT(toggleLockedText())); + m_action_lockText->setCheckable(true); + m_action_lockText->setChecked(m_lockedText); + m_menu->addAction("Refresh Messages...", Qt::CTRL|Qt::Key_R, this, SLOT(refreshMessages())); + m_menu->addAction("Save Message Text...", Qt::CTRL|Qt::Key_S, this, SLOT(saveText())); +#else m_menu->addAction("&Find...", this, SLOT(findDialog()), Qt::CTRL|Qt::Key_F); m_menu->addSeparator(); @@ -670,6 +681,8 @@ SLOT(refreshMessages()), Qt::CTRL|Qt::Key_R); m_menu->addAction("Save Message Text...", this, SLOT(saveText()), Qt::CTRL|Qt::Key_S); +#endif + m_menu->addSeparator(); tmpAction = m_menu->addAction("&Display Type", this, Modified: showeq/branches/cn187_devel/src/spawnlistcommon.cpp =================================================================== --- showeq/branches/cn187_devel/src/spawnlistcommon.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/spawnlistcommon.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -708,6 +708,13 @@ void SpawnListMenu::delete_category() { +#if (QT_VERSION >= QT_VERSION_CHECK(4,2,0)) + QMessageBox mb(QMessageBox::NoIcon, "Are you sure?", + "Are you sure you wish to delete category " + + m_currentCategory->name() + "?", + QMessageBox::Yes | QMessageBox::No, + m_spawnlist); +#else // confirm that the user wants to delete the category QMessageBox mb("Are you sure?", "Are you sure you wish to delete category " @@ -717,7 +724,8 @@ QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, m_spawnlist); - +#endif + // if user chose yes, then delete the category if (mb.exec() == QMessageBox::Yes) m_categoryMgr->remCategory(m_currentCategory); Modified: showeq/branches/cn187_devel/src/spawnpointlist.cpp =================================================================== --- showeq/branches/cn187_devel/src/spawnpointlist.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/spawnpointlist.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -366,7 +366,13 @@ sp->x(), sp->y(), sp->z(), def.toLatin1().data()); #endif - // confirm that the user wants to delete the category +#if (QT_VERSION >= QT_VERSION_CHECK(4,2,0)) + QMessageBox mb(QMessageBox::NoIcon, "Are you sure?", + "Are you sure you wish to delete spawn point " + + def + "?", + QMessageBox::Yes | QMessageBox::No, + this); +#else QMessageBox mb("Are you sure?", "Are you sure you wish to delete spawn point " + def + "?", @@ -375,6 +381,7 @@ QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this); +#endif // if user chose eys, then delete the spawn point if (mb.exec() == QMessageBox::Yes) @@ -389,7 +396,12 @@ void SpawnPointList::clearItems(void) { - // confirm that the user wants to delete the category +#if (QT_VERSION >= QT_VERSION_CHECK(4,2,0)) + QMessageBox mb(QMessageBox::NoIcon, "Are you sure?", + "Are you sure you wish to clear all the spawn points?", + QMessageBox::Yes | QMessageBox::No, + this); +#else QMessageBox mb("Are you sure?", "Are you sure you wish to clear all the spawn points?", QMessageBox::NoIcon, @@ -397,7 +409,8 @@ QMessageBox::No | QMessageBox::Default | QMessageBox::Escape, QMessageBox::NoButton, this); - +#endif + // if user chose eys, then clear the spawn points if (mb.exec() == QMessageBox::Yes) m_spawnMonitor->clear(); Modified: showeq/branches/cn187_devel/src/xmlconv.cpp =================================================================== --- showeq/branches/cn187_devel/src/xmlconv.cpp 2024-08-19 01:31:12 UTC (rev 1511) +++ showeq/branches/cn187_devel/src/xmlconv.cpp 2024-08-19 01:31:19 UTC (rev 1512) @@ -268,11 +268,7 @@ QStringList stringList; QDomElement stringElement; -#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0)) - for (int i = 0; i < stringNodeList.length(); i++) -#else - for (unsigned int i = 0; i < stringNodeList.length(); i++) -#endif + for (int i = 0; i < stringNodeList.count(); i++) { stringElement = stringNodeList.item(i).toElement(); if (!stringElement.hasAttribute("value")) @@ -464,11 +460,7 @@ case QMetaType::QStringList: { e.setTagName("stringlist"); -#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0)) int j; -#else - unsigned int j; -#endif QDomNode n; QDomNodeList stringNodeList = e.elementsByTagName("string"); @@ -477,7 +469,7 @@ QStringList::Iterator it = stringList.begin(); for (j = 0; - ((j < stringNodeList.length()) && (it != stringList.end())); + ((j < stringNodeList.count()) && (it != stringList.end())); j++) { // get the current string element This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-19 01:31:14
|
Revision: 1511 http://sourceforge.net/p/seq/svn/1511 Author: cn187 Date: 2024-08-19 01:31:12 +0000 (Mon, 19 Aug 2024) Log Message: ----------- Break out main menu and status bar creation Break main menu and status bar creation into separate functions in order to reduce the size and increase readability of the EQInterface constructor. Modified Paths: -------------- showeq/branches/cn187_devel/src/interface.cpp showeq/branches/cn187_devel/src/interface.h Modified: showeq/branches/cn187_devel/src/interface.cpp =================================================================== --- showeq/branches/cn187_devel/src/interface.cpp 2024-08-18 14:58:29 UTC (rev 1510) +++ showeq/branches/cn187_devel/src/interface.cpp 2024-08-19 01:31:12 UTC (rev 1511) @@ -110,6 +110,16 @@ // this define is used to diagnose the order with which zone packets are rcvd #define ZONE_ORDER_DIAG +const char* player_classes[] = {"Warrior", "Cleric", "Paladin", + "Ranger", "Shadow Knight", "Druid", "Monk", "Bard", "Rogue", "Shaman", + "Necromancer", "Wizard", "Magician", "Enchanter", "Beastlord", "Berserker" +}; + +const char* player_races[] = {"Human", "Barbarian", "Erudite", + "Wood elf", "High Elf", "Dark Elf", "Half Elf", "Dwarf", "Troll", "Ogre", + "Halfling", "Gnome", "Iksar", "Vah Shir", "Froglok" }; + + /* The main interface widget */ EQInterface::EQInterface(DataLocationMgr* dlm, QWidget * parent, const char *name) @@ -181,18 +191,6 @@ m_selectOnTarget = pSEQPrefs->getPrefBool("SelectOnTarget", section, false); m_deselectOnUntarget = pSEQPrefs->getPrefBool("DeselectOnUntarget", section, false); - const char* player_classes[] = {"Warrior", "Cleric", "Paladin", "Ranger", - "Shadow Knight", "Druid", "Monk", "Bard", - "Rogue", "Shaman", "Necromancer", "Wizard", - "Magician", "Enchanter", "Beastlord", - "Berserker" - }; - const char* player_races[] = {"Human", "Barbarian", "Erudite", "Wood elf", - "High Elf", "Dark Elf", "Half Elf", "Dwarf", - "Troll", "Ogre", "Halfling", "Gnome", "Iksar", - "Vah Shir", "Froglok" - }; - // set the applications default font if (pSEQPrefs->isPreference("Font", section)) { @@ -543,6 +541,716 @@ // The first call to menuBar() makes it exist menuBar()->addSeparator(); + createFileMenu(); + createViewMenu(); + createOptionsMenu(); + createNetworkMenu(); + createCharacterMenu(); + createFiltersMenu(); + createInterfaceMenu(); + createWindowMenu(); + createDebugMenu(); + +//////////////////// +// QStatusBar creation + createStatusBar(); + +///////////////// +// interface connections + // connect EQInterface slots to its own signals + connect(this, SIGNAL(restoreFonts(void)), + this, SLOT(restoreStatusFont(void))); + + // connect MapMgr slots to interface signals + connect(this, SIGNAL(saveAllPrefs(void)), + m_mapMgr, SLOT(savePrefs(void))); + + // connect CategoryMgr slots to interface signals + connect(this, SIGNAL(saveAllPrefs(void)), + m_categoryMgr, SLOT(savePrefs(void))); + + if (m_mapMgr) + { + m_packet->connect2("OP_WaypointResponse", SP_Zone, DIR_Server, + "waypointStruct", SZC_Modulus, + m_mapMgr, SLOT(setWaypoints(const uint8_t*, size_t, uint8_t))); + } + + if (m_zoneMgr) + { + m_packet->connect2("OP_ZoneEntry", SP_Zone, DIR_Client, + "ClientZoneEntryStruct", SZC_Match, + m_zoneMgr, SLOT(zoneEntryClient(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_PlayerProfile", SP_Zone, DIR_Server, + "uint8_t", SZC_None, + m_zoneMgr, SLOT(zonePlayer(const uint8_t*, size_t))); + m_packet->connect2("OP_ZoneChange", SP_Zone, DIR_Client|DIR_Server, + "zoneChangeStruct", SZC_Match, + m_zoneMgr, SLOT(zoneChange(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_NewZone", SP_Zone, DIR_Server, + "uint8_t", SZC_None, + m_zoneMgr, SLOT(zoneNew(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_SendZonePoints", SP_Zone, DIR_Server, + "zonePointsStruct", SZC_None, + m_zoneMgr, SLOT(zonePoints(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_DzSwitchInfo", SP_Zone, DIR_Server, + "dzSwitchInfo", SZC_None, + m_zoneMgr, SLOT(dynamicZonePoints(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_DzInfo", SP_Zone, DIR_Server, + "dzInfo", SZC_Match, + m_zoneMgr, SLOT(dynamicZoneInfo(const uint8_t*, size_t, uint8_t))); + } + + if (m_groupMgr != 0) + { + connect(m_zoneMgr, SIGNAL(playerProfile(const charProfileStruct*)), + m_groupMgr, SLOT(player(const charProfileStruct*))); + m_packet->connect2("OP_GroupUpdate", SP_Zone, DIR_Server, + "uint8_t", SZC_None, + m_groupMgr, SLOT(groupUpdate(const uint8_t*, size_t))); + m_packet->connect2("OP_GroupFollow", SP_Zone, DIR_Server, + "groupFollowStruct", SZC_Match, + m_groupMgr, SLOT(addGroupMember(const uint8_t*))); + m_packet->connect2("OP_GroupDisband", SP_Zone, DIR_Server, + "groupDisbandStruct", SZC_Match, + m_groupMgr, SLOT(removeGroupMember(const uint8_t*))); + m_packet->connect2("OP_GroupDisband2", SP_Zone, DIR_Server, + "groupDisbandStruct", SZC_Match, + m_groupMgr, SLOT(removeGroupMember(const uint8_t*))); + // connect GroupMgr slots to SpawnShell signals + connect(m_spawnShell, SIGNAL(addItem(const Item*)), + m_groupMgr, SLOT(addItem(const Item*))); + // connect GroupMgr slots to SpawnShell signals + connect(m_spawnShell, SIGNAL(delItem(const Item*)), + m_groupMgr, SLOT(delItem(const Item*))); + // connect GroupMgr slots to SpawnShell signals + connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), + m_groupMgr, SLOT(killSpawn(const Item*))); + } + + if (m_dateTimeMgr) + { + // connect DateTimeMgr slots to EQPacket signals + m_packet->connect2("OP_TimeOfDay", SP_Zone, DIR_Server, + "timeOfDayStruct", SZC_Match, + m_dateTimeMgr, SLOT(timeOfDay(const uint8_t*))); + + // connect interface slots to DateTimeMgr signals + connect(m_dateTimeMgr, SIGNAL(updatedDateTime(const QDateTime&)), + this, SLOT(updatedDateTime(const QDateTime&))); + + connect(m_dateTimeMgr, SIGNAL(syncDateTime(const QDateTime&)), + this, SLOT(syncDateTime(const QDateTime&))); + } + + if (m_filterMgr) + { + connect(m_zoneMgr, SIGNAL(zoneBegin(const QString&)), + m_filterMgr, SLOT(loadZone(const QString&))); + connect(m_zoneMgr, SIGNAL(zoneEnd(const QString&, const QString&)), + m_filterMgr, SLOT(loadZone(const QString&))); + connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), + m_filterMgr, SLOT(loadZone(const QString&))); + } + + if (m_guildmgr) + { + /* + m_packet->connect2("OP_GuildList", SP_World, DIR_Server, + "worldGuildListStruct", SZC_None, + m_guildmgr, + SLOT(worldGuildList(const uint8_t*, size_t))); + */ + + m_packet->connect2("OP_GuildsInZoneList", SP_Zone, DIR_Server, + "guildsInZoneListStruct", SZC_None, m_guildmgr, + SLOT(guildsInZoneList(const uint8_t*, size_t))); + + m_packet->connect2("OP_NewGuildInZone", SP_Zone, DIR_Server, + "newGuildInZoneStruct", SZC_None, m_guildmgr, + SLOT(newGuildInZone(const uint8_t*, size_t))); + + connect(this, SIGNAL(guildList2text(QString)), + m_guildmgr, SLOT(guildList2text(QString))); + + } + + if (m_guildShell) + { + m_packet->connect2("OP_GuildMemberList", SP_Zone, DIR_Server, + "uint8_t", SZC_None, + m_guildShell, + SLOT(guildMemberList(const uint8_t*, size_t))); + m_packet->connect2("OP_GuildMemberUpdate", SP_Zone, DIR_Server, + "GuildMemberUpdate", SZC_Match, + m_guildShell, + SLOT(guildMemberUpdate(const uint8_t*, size_t))); + } + + if (m_messageShell) + { + m_packet->connect2("OP_CommonMessage", SP_Zone, DIR_Client|DIR_Server, + "channelMessageStruct", SZC_None, + m_messageShell, + SLOT(channelMessage(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_FormattedMessage", SP_Zone, DIR_Server, + "formattedMessageStruct", SZC_None, + m_messageShell, + SLOT(formattedMessage(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_SimpleMessage", SP_Zone, DIR_Server, + "simpleMessageStruct", SZC_Match, + m_messageShell, + SLOT(simpleMessage(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_SpecialMesg", SP_Zone, DIR_Server, + "specialMessageStruct", SZC_None, + m_messageShell, + SLOT(specialMessage(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_GuildMOTD", SP_Zone, DIR_Server, + "guildMOTDStruct", SZC_None, + m_messageShell, + SLOT(guildMOTD(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_RandomReq", SP_Zone, DIR_Client, + "randomReqStruct", SZC_Match, + m_messageShell, SLOT(randomRequest(const uint8_t*))); + m_packet->connect2("OP_RandomReply", SP_Zone, DIR_Server, + "randomStruct", SZC_Match, + m_messageShell, SLOT(random(const uint8_t*))); + m_packet->connect2("OP_ConsentResponse", SP_Zone, DIR_Server, + "consentResponseStruct", SZC_Match, + m_messageShell, SLOT(consent(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_DenyResponse", SP_Zone, DIR_Server, + "consentResponseStruct", SZC_Match, + m_messageShell, SLOT(consent(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_Emote", SP_Zone, DIR_Server|DIR_Client, + "emoteTextStruct", SZC_None, + m_messageShell, SLOT(emoteText(const uint8_t*))); + m_packet->connect2("OP_InspectAnswer", SP_Zone, DIR_Server, + "inspectDataStruct", SZC_Match, + m_messageShell, SLOT(inspectData(const uint8_t*))); + m_packet->connect2("OP_MoneyOnCorpse", SP_Zone, DIR_Server, + "moneyOnCorpseStruct", SZC_Match, + m_messageShell, SLOT(moneyOnCorpse(const uint8_t*))); + m_packet->connect2("OP_Logout", SP_Zone, DIR_Server, + "none", SZC_Match, + m_messageShell, SLOT(logOut(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_NewZone", SP_Zone, DIR_Server, + "uint8_t", SZC_None, + m_messageShell, SLOT(zoneNew(const uint8_t*, size_t, uint8_t))); + connect(m_zoneMgr, SIGNAL(zoneBegin(const ClientZoneEntryStruct*, size_t, uint8_t)), + m_messageShell, SLOT(zoneEntryClient(const ClientZoneEntryStruct*))); + connect(m_zoneMgr, SIGNAL(zoneChanged(const zoneChangeStruct*, size_t, uint8_t)), + m_messageShell, SLOT(zoneChanged(const zoneChangeStruct*, size_t, uint8_t))); + connect(m_zoneMgr, SIGNAL(zoneBegin(const QString&)), + m_messageShell, SLOT(zoneBegin(const QString&))); + connect(m_zoneMgr, SIGNAL(zoneEnd(const QString&, const QString&)), + m_messageShell, SLOT(zoneEnd(const QString&, const QString&))); + connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), + m_messageShell, SLOT(zoneChanged(const QString&))); + + m_packet->connect2("OP_MOTD", SP_World, DIR_Server, + "worldMOTDStruct", SZC_None, + m_messageShell, SLOT(worldMOTD(const uint8_t*))); + m_packet->connect2("OP_MemorizeSpell", SP_Zone, DIR_Server|DIR_Client, + "memSpellStruct", SZC_Match, + m_messageShell, SLOT(handleSpell(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_BeginCast", SP_Zone, DIR_Server|DIR_Client, + "beginCastStruct", SZC_Match, + m_messageShell, SLOT(beginCast(const uint8_t*))); + m_packet->connect2("OP_BuffFadeMsg", SP_Zone, DIR_Server|DIR_Client, + "spellFadedStruct", SZC_None, + m_messageShell, SLOT(spellFaded(const uint8_t*))); + m_packet->connect2("OP_CastSpell", SP_Zone, DIR_Server|DIR_Client, + "startCastStruct", SZC_Match, + m_messageShell, SLOT(startCast(const uint8_t*))); + connect(m_zoneMgr, SIGNAL(playerProfile(const charProfileStruct*)), + m_messageShell, SLOT(player(const charProfileStruct*))); + m_packet->connect2("OP_SkillUpdate", SP_Zone, DIR_Server, + "skillIncStruct", SZC_Match, + m_messageShell, SLOT(increaseSkill(const uint8_t*))); + m_packet->connect2("OP_LevelUpdate", SP_Zone, DIR_Server, + "levelUpUpdateStruct", SZC_Match, + m_messageShell, SLOT(updateLevel(const uint8_t*))); + + m_packet->connect2("OP_Consider", SP_Zone, DIR_Server, + "considerStruct", SZC_Match, + m_messageShell, SLOT(consMessage(const uint8_t*, size_t, uint8_t))); + + connect(m_player, SIGNAL(setExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t)), + m_messageShell, SLOT(setExp(uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t))); + connect(m_player, SIGNAL(newExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t)), + m_messageShell, SLOT(newExp(uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t))); + connect(m_player, SIGNAL(setAltExp(uint32_t, uint32_t, uint32_t, uint32_t)), + m_messageShell, SLOT(setAltExp(uint32_t, uint32_t, uint32_t, uint32_t))); + connect(m_player, SIGNAL(newAltExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t)), + m_messageShell, SLOT(newAltExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t))); + + connect(m_spawnShell, SIGNAL(addItem(const Item*)), + m_messageShell, SLOT(addItem(const Item*))); + connect(m_spawnShell, SIGNAL(delItem(const Item*)), + m_messageShell, SLOT(delItem(const Item*))); + connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), + m_messageShell, SLOT(killSpawn(const Item*))); + + connect(m_dateTimeMgr, SIGNAL(syncDateTime(const QDateTime&)), + m_messageShell, SLOT(syncDateTime(const QDateTime&))); + +// 9/3/2008 - Removed. Serialized packet now. +// m_packet->connect2("OP_GroupUpdate", SP_Zone, DIR_Server, +// "groupUpdateStruct", SZC_None, +// m_messageShell, SLOT(groupUpdate(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_GroupInvite", SP_Zone, DIR_Client|DIR_Server, + "groupInviteStruct", SZC_None, + m_messageShell, SLOT(groupInvite(const uint8_t*, size_t, uint8_t))); +// m_packet->connect2("OP_GroupInvite", SP_Zone, DIR_Server, +// "groupAltInviteStruct", SZC_Match, +// m_messageShell, SLOT(groupInvite(const uint8_t*))); + m_packet->connect2("OP_GroupInvite2", SP_Zone, DIR_Client, + "groupInviteStruct", SZC_None, + m_messageShell, SLOT(groupInvite(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_GroupFollow", SP_Zone, DIR_Server, + "groupFollowStruct", SZC_Match, + m_messageShell, SLOT(groupFollow(const uint8_t*))); + m_packet->connect2("OP_GroupFollow2", SP_Zone, DIR_Server, + "groupFollowStruct", SZC_Match, + m_messageShell, SLOT(groupFollow(const uint8_t*))); + m_packet->connect2("OP_GroupDisband", SP_Zone, DIR_Server, + "groupDisbandStruct", SZC_Match, + m_messageShell, SLOT(groupDisband(const uint8_t*))); + m_packet->connect2("OP_GroupDisband2", SP_Zone, DIR_Server, + "groupDisbandStruct", SZC_Match, + m_messageShell, SLOT(groupDisband(const uint8_t*))); + m_packet->connect2("OP_GroupCancelInvite", SP_Zone, DIR_Server|DIR_Client, + "groupDeclineStruct", SZC_Match, + m_messageShell, SLOT(groupDecline(const uint8_t*))); + m_packet->connect2("OP_GroupLeader", SP_Zone, DIR_Server, + "groupLeaderChangeStruct", SZC_Match, + m_messageShell, SLOT(groupLeaderChange(const uint8_t*))); + } + + if (m_filterNotifications) + { + connect(m_spawnShell, SIGNAL(addItem(const Item*)), + m_filterNotifications, SLOT(addItem(const Item*))); + connect(m_spawnShell, SIGNAL(delItem(const Item*)), + m_filterNotifications, SLOT(delItem(const Item*))); + connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), + m_filterNotifications, SLOT(killSpawn(const Item*))); + connect(m_spawnShell, SIGNAL(changeItem(const Item*, uint32_t)), + m_filterNotifications, + SLOT(changeItem(const Item*, uint32_t))); + } + + // connect interface slots to Packet signals + m_packet->connect2("OP_TargetMouse", SP_Zone, DIR_Client|DIR_Server, + "clientTargetStruct", SZC_Match, + this, SLOT(clientTarget(const uint8_t*))); +#if 0 // ZBTEMP + connect(m_packet, SIGNAL(attack2Hand1(const uint8_t*, size_t, uint8_t)), + this, SLOT(attack2Hand1(const uint8_t*))); +#endif + m_packet->connect2("OP_Action2", SP_Zone, DIR_Client|DIR_Server, + "action2Struct", SZC_Match, + this, SLOT(action2Message(const uint8_t*))); + m_packet->connect2("OP_Death", SP_Zone, DIR_Server, + "newCorpseStruct", SZC_Match, + this, SLOT(combatKillSpawn(const uint8_t*))); +#if 0 // ZBTEMP + connect(m_packet, SIGNAL(interruptSpellCast(const uint8_t*, size_t, uint8_t)), + this, SLOT(interruptSpellCast(const uint8_t*))); + connect(m_packet, SIGNAL(moneyUpdate(const uint8_t*, size_t, uint8_t)), + this, SLOT(moneyUpdate(const uint8_t*))); + connect(m_packet, SIGNAL(moneyThing(const uint8_t*, size_t, uint8_t)), + this, SLOT(moneyThing(const uint8_t*))); +#endif // ZBTEMP + + connect(m_packet, SIGNAL(toggle_session_tracking(bool)), + this, SLOT(toggle_net_session_tracking(bool))); + + // connect EQInterface slots to ZoneMgr signals + connect(m_zoneMgr, SIGNAL(zoneBegin(const QString&)), + this, SLOT(zoneBegin(const QString&))); + connect(m_zoneMgr, SIGNAL(zoneEnd(const QString&, const QString&)), + this, SLOT(zoneEnd(const QString&, const QString&))); + connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), + this, SLOT(zoneChanged(const QString&))); + + // connect the SpellShell slots to EQInterface signals + connect(this, SIGNAL(spellMessage(QString&)), + m_spellShell, SLOT(spellMessage(QString&))); + + // connect EQInterface slots to SpawnShell signals + connect(m_spawnShell, SIGNAL(addItem(const Item*)), + this, SLOT(addItem(const Item*))); + connect(m_spawnShell, SIGNAL(delItem(const Item*)), + this, SLOT(delItem(const Item*))); + connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), + this, SLOT(killSpawn(const Item*))); + connect(m_spawnShell, SIGNAL(changeItem(const Item*, uint32_t)), + this, SLOT(changeItem(const Item*))); + connect(m_spawnShell, SIGNAL(spawnConsidered(const Item*)), + this, SLOT(spawnConsidered(const Item*))); + + // connect the SpawnShell slots to Packet signals + m_packet->connect2("OP_GroundSpawn", SP_Zone, DIR_Server, + "makeDropStruct", SZC_None, + m_spawnShell, SLOT(newGroundItem(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_ClickObject", SP_Zone, DIR_Server, + "remDropStruct", SZC_Match, + m_spawnShell, SLOT(removeGroundItem(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_SpawnDoor", SP_Zone, DIR_Server, + "doorStruct", SZC_Modulus, + m_spawnShell, SLOT(newDoorSpawns(const uint8_t*, size_t, uint8_t))); +// OP_NewSpawn is deprecated in the client +// m_packet->connect2("OP_NewSpawn", SP_Zone, DIR_Server, +// "spawnStruct", SZC_Match, +// m_spawnShell, SLOT(newSpawn(const uint8_t*))); + m_packet->connect2("OP_ZoneEntry", SP_Zone, DIR_Server, + "uint8_t", SZC_None, + m_spawnShell, SLOT(zoneEntry(const uint8_t*, size_t))); + m_packet->connect2("OP_MobUpdate", SP_Zone, DIR_Server|DIR_Client, + "spawnPositionUpdate", SZC_Match, + m_spawnShell, SLOT(updateSpawns(const uint8_t*))); + m_packet->connect2("OP_WearChange", SP_Zone, DIR_Server|DIR_Client, + "SpawnUpdateStruct", SZC_Match, + m_spawnShell, SLOT(updateSpawnInfo(const uint8_t*))); + m_packet->connect2("OP_HPUpdate", SP_Zone, DIR_Server|DIR_Client, + "hpNpcUpdateStruct", SZC_Match, + m_spawnShell, SLOT(updateNpcHP(const uint8_t*))); + m_packet->connect2("OP_DeleteSpawn", SP_Zone, DIR_Server|DIR_Client, + "deleteSpawnStruct", SZC_Match, + m_spawnShell, SLOT(deleteSpawn(const uint8_t*))); + m_packet->connect2("OP_SpawnRename", SP_Zone, DIR_Server, + "spawnRenameStruct", SZC_Match, + m_spawnShell, SLOT(renameSpawn(const uint8_t*))); + m_packet->connect2("OP_Illusion", SP_Zone, DIR_Server|DIR_Client, + "spawnIllusionStruct", SZC_Match, + m_spawnShell, SLOT(illusionSpawn(const uint8_t*))); + m_packet->connect2("OP_SpawnAppearance", SP_Zone, DIR_Server|DIR_Client, + "spawnAppearanceStruct", SZC_Match, + m_spawnShell, SLOT(updateSpawnAppearance(const uint8_t*))); + m_packet->connect2("OP_Death", SP_Zone, DIR_Server, + "newCorpseStruct", SZC_Match, + m_spawnShell, SLOT(killSpawn(const uint8_t*))); +// m_packet->connect2("OP_RespawnFromHover", SP_Zone, DIR_Server|DIR_Client, +// "uint8_t", SZC_None, +// m_spawnShell, SLOT(respawnFromHover(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_Shroud", SP_Zone, DIR_Server, + "spawnShroudSelf", SZC_None, + m_spawnShell, SLOT(shroudSpawn(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_RemoveSpawn", SP_Zone, DIR_Server|DIR_Client, + "removeSpawnStruct", SZC_None, + m_spawnShell, SLOT(removeSpawn(const uint8_t*, size_t, uint8_t))); +#if 0 // ZBTEMP + connect(m_packet, SIGNAL(spawnWearingUpdate(const uint8_t*, size_t, uint8_t)), + m_spawnShell, SLOT(spawnWearingUpdate(const uint8_t*))); +#endif + m_packet->connect2("OP_Consider", SP_Zone, DIR_Server|DIR_Client, + "considerStruct", SZC_Match, + m_spawnShell, SLOT(consMessage(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_NpcMoveUpdate", SP_Zone, DIR_Server, + "uint8_t", SZC_None, + m_spawnShell, SLOT(npcMoveUpdate(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_ClientUpdate", SP_Zone, DIR_Server, + "playerSpawnPosStruct", SZC_Match, + m_spawnShell, SLOT(playerUpdate(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_CorpseLocResponse", SP_Zone, DIR_Server, + "corpseLocStruct", SZC_Match, + m_spawnShell, SLOT(corpseLoc(const uint8_t*))); +#if 0 // No longer used as of 5-22-2008 + m_packet->connect2("OP_ZoneSpawns", SP_Zone, DIR_Server, + "spawnStruct", SZC_None, + m_spawnShell, SLOT(zoneSpawns(const uint8_t*, size_t))); +#endif + + // connect the SpellShell slots to ZoneMgr signals + connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), + m_spellShell, SLOT(zoneChanged())); + + // connect the SpellShell slots to SpawnShell signals + connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), + m_spellShell, SLOT(killSpawn(const Item*))); + + // connect the SpellShell slots to Player signals + connect(m_player, SIGNAL(newPlayer(void)), + m_spellShell, SLOT(clear())); + connect(m_player, SIGNAL(buffLoad(const spellBuff *)), + m_spellShell, SLOT(buffLoad(const spellBuff *))); + + // connect the SpellShell slots to EQPacket signals + m_packet->connect2("OP_CastSpell", SP_Zone, DIR_Server|DIR_Client, + "startCastStruct", SZC_Match, + m_spellShell, SLOT(selfStartSpellCast(const uint8_t*))); + m_packet->connect2("OP_Buff", SP_Zone, DIR_Server|DIR_Client, + "buffStruct", SZC_Match, + m_spellShell, SLOT(buff(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_Action", SP_Zone, DIR_Server|DIR_Client, + "actionStruct", SZC_Match, + m_spellShell, SLOT(action(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_Action", SP_Zone, DIR_Server|DIR_Client, + "actionAltStruct", SZC_Match, + m_spellShell, SLOT(action(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_SimpleMessage", SP_Zone, DIR_Server, + "simpleMessageStruct", SZC_Match, + m_spellShell, + SLOT(simpleMessage(const uint8_t*, size_t, uint8_t))); + + + // connect Player slots to EQPacket signals + connect(m_zoneMgr, SIGNAL(playerProfile(const charProfileStruct*)), + m_player, SLOT(player(const charProfileStruct*))); + m_packet->connect2("OP_SkillUpdate", SP_Zone, DIR_Server, + "skillIncStruct", SZC_Match, + m_player, SLOT(increaseSkill(const uint8_t*))); + m_packet->connect2("OP_ManaChange", SP_Zone, DIR_Server, + "manaDecrementStruct", SZC_Match, + m_player, SLOT(manaChange(const uint8_t*))); + m_packet->connect2("OP_ClientUpdate", SP_Zone, DIR_Server|DIR_Client, + "playerSelfPosStruct", SZC_Match, + m_player, SLOT(playerUpdateSelf(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_ExpUpdate", SP_Zone, DIR_Server, + "expUpdateStruct", SZC_Match, + m_player, SLOT(updateExp(const uint8_t*))); + m_packet->connect2("OP_AAExpUpdate", SP_Zone, DIR_Server, + "altExpUpdateStruct", SZC_Match, + m_player, SLOT(updateAltExp(const uint8_t*))); + m_packet->connect2("OP_LevelUpdate", SP_Zone, DIR_Server, + "levelUpUpdateStruct", SZC_Match, + m_player, SLOT(updateLevel(const uint8_t*))); + m_packet->connect2("OP_HPUpdate", SP_Zone, DIR_Server|DIR_Client, + "hpNpcUpdateStruct", SZC_Match, + m_player, SLOT(updateNpcHP(const uint8_t*))); + m_packet->connect2("OP_WearChange", SP_Zone, DIR_Server|DIR_Client, + "SpawnUpdateStruct", SZC_Match, + m_player, SLOT(updateSpawnInfo(const uint8_t*))); + m_packet->connect2("OP_Stamina", SP_Zone, DIR_Server, + "staminaStruct", SZC_Match, + m_player, SLOT(updateStamina(const uint8_t*))); + m_packet->connect2("OP_Consider", SP_Zone, DIR_Server|DIR_Client, + "considerStruct", SZC_Match, + m_player, SLOT(consMessage(const uint8_t*, size_t, uint8_t))); + m_packet->connect2("OP_SwapSpell", SP_Zone, DIR_Server, + "tradeSpellBookSlotsStruct", SZC_Match, + m_player, SLOT(tradeSpellBookSlots(const uint8_t*, size_t, uint8_t))); + + // interface statusbar slots + connect (this, SIGNAL(newZoneName(const QString&)), + m_stsbarZone, SLOT(setText(const QString&))); + connect (m_packet, SIGNAL(stsMessage(const QString &, int)), + this, SLOT(stsMessage(const QString &, int))); + connect (m_spawnShell, SIGNAL(numSpawns(int)), + this, SLOT(numSpawns(int))); + connect (m_packet, SIGNAL(numPacket(int, int)), + this, SLOT(numPacket(int, int))); + connect (m_packet, SIGNAL(resetPacket(int, int)), + this, SLOT(resetPacket(int, int))); + connect (m_player, SIGNAL(newSpeed(double)), + this, SLOT(newSpeed(double))); + connect(m_player, SIGNAL(setExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t)), + this, SLOT(setExp(uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t))); + connect(m_player, SIGNAL(newExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t)), + this, SLOT(newExp(uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t, uint32_t))); + connect(m_player, SIGNAL(setAltExp(uint32_t, uint32_t, uint32_t, uint32_t)), + this, SLOT(setAltExp(uint32_t, uint32_t, uint32_t, uint32_t))); + connect(m_player, SIGNAL(newAltExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t)), + this, SLOT(newAltExp(uint32_t, uint32_t, uint32_t, uint32_t, + uint32_t, uint32_t))); + connect(m_player, SIGNAL(levelChanged(uint8_t)), + this, SLOT(levelChanged(uint8_t))); + + + if (m_expWindow != 0) + { + // connect ExperienceWindow slots to Player signals + connect(m_player, SIGNAL(newPlayer(void)), + m_expWindow, SLOT(clear(void))); + connect(m_player, SIGNAL(expGained(const QString &, int, long, QString )), + m_expWindow, SLOT(addExpRecord(const QString &, int, long,QString ))); + + // connect ExperienceWindow slots to EQInterface signals + connect(this, SIGNAL(restoreFonts(void)), + m_expWindow, SLOT(restoreFont(void))); + connect(this, SIGNAL(saveAllPrefs(void)), + m_expWindow, SLOT(savePrefs(void))); + } + + if (m_combatWindow != 0) + { + // connect CombatWindow slots to the signals + connect(m_player, SIGNAL(newPlayer(void)), + m_combatWindow, SLOT(clear(void))); + connect (this, SIGNAL(combatSignal(int, int, int, int, int, QString, QString)), + m_combatWindow, SLOT(addCombatRecord(int, int, int, int, int, QString, QString))); + connect (m_spawnShell, SIGNAL(spawnConsidered(const Item*)), + m_combatWindow, SLOT(resetDPS())); + connect(this, SIGNAL(restoreFonts(void)), + m_combatWindow, SLOT(restoreFont(void))); + connect(this, SIGNAL(saveAllPrefs(void)), + m_combatWindow, SLOT(savePrefs(void))); + } + + + // + // Geometry Configuration + // + + + // interface components + + // set mainwindow Geometry + section = "Interface"; + + // The way window/dock state was saved with Qt3 won't work with Qt4+, so + // we use the Qt-provided functions instead. Unforunately, that means the + // size/position preferences saved in the Qt3 version won't be usable, and + // the users will have to redo their window/dock size/placement. + QString dockPrefsState = pSEQPrefs->getPrefString("DockingInfoState", + section, QString()); + QString dockPrefsGeometry = pSEQPrefs->getPrefString("DockingInfoGeometry", + section, QString()); + + bool usePos = pSEQPrefs->getPrefBool("UseWindowPos", section, true); + if (usePos) + { + if (!restoreGeometry(QByteArray::fromBase64(dockPrefsGeometry.toLatin1()))) + seqWarn("Could not restore dock/window geometry. Rearrange windows " + "as desired and then re-save preferences"); + else + // work around QTBUG-46620 + if (isMaximized()) +#if (QT_VERSION >= QT_VERSION_CHECK(6,0,0)) + setGeometry(window()->windowHandle()->screen()->availableGeometry()); +#else + setGeometry(QApplication::desktop()->availableGeometry(this)); +#endif + + if (!restoreState(QByteArray::fromBase64(dockPrefsState.toLatin1()))) + seqWarn("Could not restore dock/window state. Rearrange windows as" + " desired and then re-save prefrences"); + } + + new QShortcut(Qt::CTRL|Qt::ALT|Qt::Key_S, this, SLOT(toggle_view_statusbar())); + new QShortcut(Qt::CTRL|Qt::ALT|Qt::Key_T, this, SLOT(toggle_view_menubar())); + + // Set main window title + // TODO: Add % replacement values and a signal to update, for ip address currently + // TODO: being monitored. + + QMainWindow::setWindowTitle(pSEQPrefs->getPrefString("Caption", section, + "ShowEQ - Main (ctrl+alt+t to toggle menubar)")); + + show(); + + + // load the format strings for display + loadFormatStrings(); + + /* Start the packet capturing */ + m_packet->start (10); +}// end constructor +//////////////////// + +EQInterface::~EQInterface() +{ + if (m_netDiag != 0) + delete m_netDiag; + + if (m_spawnPointList != 0) + delete m_spawnPointList; + + if (m_statList != 0) + delete m_statList; + + if (m_guildListWindow != 0) + delete m_guildListWindow; + + if (m_skillList != 0) + delete m_skillList; + + if (m_spellList != 0) + delete m_spellList; + + if (m_spawnList2 != 0) + delete m_spawnList2; + + if (m_spawnList != 0) + delete m_spawnList; + + for (int i = 0; i < maxNumMaps; i++) + if (m_map[i] != 0) + delete m_map[i]; + + for (int i = 0; i < maxNumMessageWindows; i++) + if (m_messageWindow[i] != 0) + delete m_messageWindow[i]; + + if (m_combatWindow != 0) + delete m_combatWindow; + + if (m_expWindow != 0) + delete m_expWindow; + + if (m_spawnLogger != 0) + delete m_spawnLogger; + + if (m_spawnMonitor != 0) + delete m_spawnMonitor; + + if (m_groupMgr != 0) + delete m_groupMgr; + + if (m_spellShell != 0) + delete m_spellShell; + + if (m_spells != 0) + delete m_spells; + + if (m_mapMgr != 0) + delete m_mapMgr; + + if (m_spawnShell != 0) + delete m_spawnShell; + + if (m_categoryMgr != 0) + delete m_categoryMgr; + + if (m_filterMgr != 0) + delete m_filterMgr; + + if (m_dateTimeMgr != 0) + delete m_dateTimeMgr; + + if (m_eqStrings != 0) + delete m_eqStrings; + + if (m_player != 0) + delete m_player; + + if (m_guildShell != 0) + delete m_guildShell; + + if (m_guildmgr != 0) + delete m_guildmgr; + + if (m_zoneMgr != 0) + delete m_zoneMgr; + + if (m_packet != 0) + delete m_packet; +} + +void EQInterface::createFileMenu() { + // File Menu QMenu* pFileMenu = new QMenu("&File"); menuBar()->addMenu(pFileMenu); @@ -575,7 +1283,12 @@ Qt::CTRL|Qt::Key_Z); } pFileMenu->addAction("&Quit", qApp, SLOT(quit())); +} +void EQInterface::createViewMenu() { + + QString section = "Interface"; + // View menu QMenu* pViewMenu = new QMenu("&View"); menuBar()->addMenu(pViewMenu); @@ -1009,6 +1722,11 @@ // view menu checks are set by init_view_menu connect(pViewMenu, SIGNAL(aboutToShow()), this, SLOT(init_view_menu())); + +} + +void EQInterface::createOptionsMenu() { + // Options Menu QMenu* pOptMenu = new QMenu("&Options"); menuBar()->addMenu(pOptMenu); @@ -1062,6 +1780,7 @@ m_action_opt_PvPDeity->setCheckable(true); m_action_opt_PvPDeity->setChecked(showeq_params->deitypvp); + QAction* tmpAction; tmpAction = pOptMenu->addAction("Create Unknown Spawns", this, SLOT(toggle_opt_CreateUnknownSpawns(bool))); tmpAction->setCheckable(true); @@ -1082,7 +1801,7 @@ tmpAction->setCheckable(true); tmpAction->setChecked(showeq_params->walkpathrecord); - subMenu = new QMenu("Walk Path Length"); + QMenu* subMenu = new QMenu("Walk Path Length"); QSpinBox* walkPathLengthSpinBox = new QSpinBox(subMenu); walkPathLengthSpinBox->setMinimum(0); walkPathLengthSpinBox->setMaximum(8192); @@ -1173,6 +1892,10 @@ m_action_opt_UseUpdateRadius->setCheckable(true); m_action_opt_UseUpdateRadius->setChecked(showeq_params->useUpdateRadius); +} + +void EQInterface::createNetworkMenu() { + // Network Menu m_netMenu = new QMenu("&Network"); menuBar()->addMenu(m_netMenu); @@ -1190,6 +1913,7 @@ m_action_net_sessiontrack->setCheckable(true); m_action_net_sessiontrack->setChecked(m_packet->session_tracking()); + QAction* tmpAction; tmpAction = m_netMenu->addAction("&Real Time Thread", this, SLOT(toggle_net_real_time_thread(bool))); tmpAction->setCheckable(true); @@ -1292,7 +2016,7 @@ pOpCodeMenu->addAction("&Reload Monitored OpCode List...", this, SLOT(set_opcode_monitored_list()), Qt::CTRL|Qt::ALT|Qt::Key_R); - section = "OpCodeMonitoring"; + QString section = "OpCodeMonitoring"; m_action_opcode_view = pOpCodeMenu->addAction("&View Monitored OpCode Matches", this, SLOT(toggle_opcode_view())); @@ -1311,7 +2035,7 @@ section = "Interface"; // Advanced menu - subMenu = new QMenu("Advanced"); + QMenu* subMenu = new QMenu("Advanced"); QMenu* subSubMenu = new QMenu("Arq Seq Give Up"); QSpinBox* arqSeqGiveUpSpinBox = new QSpinBox(subSubMenu); arqSeqGiveUpSpinBox->setMinimum(32); @@ -1326,9 +2050,14 @@ subMenu->addMenu(subSubMenu); m_netMenu->addMenu(subMenu); +} + +void EQInterface::createCharacterMenu() { + // Character Menu m_charMenu = new QMenu("&Character"); menuBar()->addMenu(m_charMenu); + QAction* tmpAction; tmpAction = m_charMenu->addAction("Use Auto Detected Settings", this, SLOT(toggleAutoDetectPlayerSettings(bool))); tmpAction->setCheckable(true); @@ -1395,6 +2124,11 @@ connect (m_charRaceMenu, SIGNAL(triggered(QAction*)), this, SLOT(SetDefaultCharacterRace(QAction*))); + +} + +void EQInterface::createFiltersMenu() { + // Filters Menu QMenu* filterMenu = new QMenu("Fi<ers"); menuBar()->addMenu(filterMenu); @@ -1418,6 +2152,7 @@ filterMenu->addAction("Re&filter Spawns", m_spawnShell, SLOT(refilterSpawns())); + QAction* tmpAction; tmpAction = filterMenu->addAction("&Is Case Sensitive", this, SLOT(toggle_filter_Case(bool))); tmpAction->setCheckable(true); @@ -1442,6 +2177,10 @@ QMenu* filterLogMenu = new QMenu("&Log"); filterMenu->addMenu(filterLogMenu); + uint32_t filters = 0; + if (m_filteredSpawnLog) + filters = m_filteredSpawnLog->filters(); + tmpAction = filterLogMenu->addAction( "Alerts"); tmpAction->setCheckable(true); tmpAction->setData(FILTER_FLAG_ALERT); @@ -1498,6 +2237,10 @@ connect(filterCmdMenu, SIGNAL(triggered(QAction*)), this, SLOT(set_filter_AudioCommand(QAction*))); +} + +void EQInterface::createInterfaceMenu() { + // Interface Menu QMenu* pInterfaceMenu = new QMenu("&Interface"); menuBar()->addMenu(pInterfaceMenu); @@ -1520,6 +2263,7 @@ QStringList::Iterator styleItr = availableStyles.begin(); + QAction* tmpAction; while (styleItr != availableStyles.end()) { tmpAction = pStyleMenu->addAction(*styleItr); @@ -1526,7 +2270,7 @@ tmpAction->setCheckable(true); if (currentStyleName.toLower() == (*styleItr).toLower()) - tmpAction->setChecked(true); + tmpAction->setChecked(true); tmpAction->setData(*styleItr); ActionList_StyleMenu.append(tmpAction); @@ -1537,6 +2281,7 @@ connect (pStyleMenu, SIGNAL(triggered(QAction*)), this, SLOT(selectTheme(QAction*))); + QString section = "Interface"; QString themeName = pSEQPrefs->getPrefString("ThemeName", section, ""); //Use the text name if there is one. If not, fall back to old numeric id. If no @@ -1730,6 +2475,11 @@ pInterfaceMenu->addAction( "Spells File...", this, SLOT(select_main_SpellsFile())); + +} + +void EQInterface::createWindowMenu() { + // insert Window menu menuBar()->addMenu(m_windowMenu); @@ -1740,6 +2490,7 @@ m_windowCaptionMenu = new QMenu("Window &Caption"); m_windowMenu->insertMenu(m_windowMenu->actions()[0], m_windowCaptionMenu); + QAction* tmpAction; tmpAction = m_windowCaptionMenu->addAction("&Main Window..."); tmpAction->setData(5); @@ -1862,6 +2613,11 @@ m_windowMenu->insertSeparator(m_windowMenu->actions()[4]); + +} + +void EQInterface::createDebugMenu() { + // Debug menu QMenu* pDebugMenu = new QMenu("&Debug"); menuBar()->addMenu(pDebugMenu); @@ -1882,9 +2638,11 @@ pDebugMenu->addAction("List &Filters", m_filterMgr, SLOT(listFilters()), Qt::ALT|Qt::CTRL|Qt::Key_F); pDebugMenu->addAction("List &Zone Filters", m_filterMgr, SLOT(listZoneFilters())); -//////////////////// -// QStatusBar creation - + +} + +void EQInterface::createStatusBar() { + QString statusBarSection = "Interface_StatusBar"; int sts_widget_count = 0; // total number of widgets visible on status bar @@ -1997,702 +2755,9 @@ //hide the statusbar if no visible widgets if (!sts_widget_count || !pSEQPrefs->getPrefBool("StatusBarActive", statusBarSection, 1)) statusBar()->hide(); +} -///////////////// -// interface connections - // connect EQInterface slots to its own signals - connect(this, SIGNAL(restoreFonts(void)), - this, SLOT(restoreStatusFont(void))); - - // connect MapMgr slots to interface signals - connect(this, SIGNAL(saveAllPrefs(void)), - m_mapMgr, SLOT(savePrefs(void))); - - // connect CategoryMgr slots to interface signals - connect(this, SIGNAL(saveAllPrefs(void)), - m_categoryMgr, SLOT(savePrefs(void))); - - if (m_mapMgr) - { - m_packet->connect2("OP_WaypointResponse", SP_Zone, DIR_Server, - "waypointStruct", SZC_Modulus, - m_mapMgr, SLOT(setWaypoints(const uint8_t*, size_t, uint8_t))); - } - - if (m_zoneMgr) - { - m_packet->connect2("OP_ZoneEntry", SP_Zone, DIR_Client, - "ClientZoneEntryStruct", SZC_Match, - m_zoneMgr, SLOT(zoneEntryClient(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_PlayerProfile", SP_Zone, DIR_Server, - "uint8_t", SZC_None, - m_zoneMgr, SLOT(zonePlayer(const uint8_t*, size_t))); - m_packet->connect2("OP_ZoneChange", SP_Zone, DIR_Client|DIR_Server, - "zoneChangeStruct", SZC_Match, - m_zoneMgr, SLOT(zoneChange(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_NewZone", SP_Zone, DIR_Server, - "uint8_t", SZC_None, - m_zoneMgr, SLOT(zoneNew(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_SendZonePoints", SP_Zone, DIR_Server, - "zonePointsStruct", SZC_None, - m_zoneMgr, SLOT(zonePoints(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_DzSwitchInfo", SP_Zone, DIR_Server, - "dzSwitchInfo", SZC_None, - m_zoneMgr, SLOT(dynamicZonePoints(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_DzInfo", SP_Zone, DIR_Server, - "dzInfo", SZC_Match, - m_zoneMgr, SLOT(dynamicZoneInfo(const uint8_t*, size_t, uint8_t))); - } - - if (m_groupMgr != 0) - { - connect(m_zoneMgr, SIGNAL(playerProfile(const charProfileStruct*)), - m_groupMgr, SLOT(player(const charProfileStruct*))); - m_packet->connect2("OP_GroupUpdate", SP_Zone, DIR_Server, - "uint8_t", SZC_None, - m_groupMgr, SLOT(groupUpdate(const uint8_t*, size_t))); - m_packet->connect2("OP_GroupFollow", SP_Zone, DIR_Server, - "groupFollowStruct", SZC_Match, - m_groupMgr, SLOT(addGroupMember(const uint8_t*))); - m_packet->connect2("OP_GroupDisband", SP_Zone, DIR_Server, - "groupDisbandStruct", SZC_Match, - m_groupMgr, SLOT(removeGroupMember(const uint8_t*))); - m_packet->connect2("OP_GroupDisband2", SP_Zone, DIR_Server, - "groupDisbandStruct", SZC_Match, - m_groupMgr, SLOT(removeGroupMember(const uint8_t*))); - // connect GroupMgr slots to SpawnShell signals - connect(m_spawnShell, SIGNAL(addItem(const Item*)), - m_groupMgr, SLOT(addItem(const Item*))); - // connect GroupMgr slots to SpawnShell signals - connect(m_spawnShell, SIGNAL(delItem(const Item*)), - m_groupMgr, SLOT(delItem(const Item*))); - // connect GroupMgr slots to SpawnShell signals - connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), - m_groupMgr, SLOT(killSpawn(const Item*))); - } - - if (m_dateTimeMgr) - { - // connect DateTimeMgr slots to EQPacket signals - m_packet->connect2("OP_TimeOfDay", SP_Zone, DIR_Server, - "timeOfDayStruct", SZC_Match, - m_dateTimeMgr, SLOT(timeOfDay(const uint8_t*))); - - // connect interface slots to DateTimeMgr signals - connect(m_dateTimeMgr, SIGNAL(updatedDateTime(const QDateTime&)), - this, SLOT(updatedDateTime(const QDateTime&))); - - connect(m_dateTimeMgr, SIGNAL(syncDateTime(const QDateTime&)), - this, SLOT(syncDateTime(const QDateTime&))); - } - - if (m_filterMgr) - { - connect(m_zoneMgr, SIGNAL(zoneBegin(const QString&)), - m_filterMgr, SLOT(loadZone(const QString&))); - connect(m_zoneMgr, SIGNAL(zoneEnd(const QString&, const QString&)), - m_filterMgr, SLOT(loadZone(const QString&))); - connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), - m_filterMgr, SLOT(loadZone(const QString&))); - } - - if (m_guildmgr) - { - /* - m_packet->connect2("OP_GuildList", SP_World, DIR_Server, - "worldGuildListStruct", SZC_None, - m_guildmgr, - SLOT(worldGuildList(const uint8_t*, size_t))); - */ - - m_packet->connect2("OP_GuildsInZoneList", SP_Zone, DIR_Server, - "guildsInZoneListStruct", SZC_None, m_guildmgr, - SLOT(guildsInZoneList(const uint8_t*, size_t))); - - m_packet->connect2("OP_NewGuildInZone", SP_Zone, DIR_Server, - "newGuildInZoneStruct", SZC_None, m_guildmgr, - SLOT(newGuildInZone(const uint8_t*, size_t))); - - connect(this, SIGNAL(guildList2text(QString)), - m_guildmgr, SLOT(guildList2text(QString))); - - } - - if (m_guildShell) - { - m_packet->connect2("OP_GuildMemberList", SP_Zone, DIR_Server, - "uint8_t", SZC_None, - m_guildShell, - SLOT(guildMemberList(const uint8_t*, size_t))); - m_packet->connect2("OP_GuildMemberUpdate", SP_Zone, DIR_Server, - "GuildMemberUpdate", SZC_Match, - m_guildShell, - SLOT(guildMemberUpdate(const uint8_t*, size_t))); - } - - if (m_messageShell) - { - m_packet->connect2("OP_CommonMessage", SP_Zone, DIR_Client|DIR_Server, - "channelMessageStruct", SZC_None, - m_messageShell, - SLOT(channelMessage(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_FormattedMessage", SP_Zone, DIR_Server, - "formattedMessageStruct", SZC_None, - m_messageShell, - SLOT(formattedMessage(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_SimpleMessage", SP_Zone, DIR_Server, - "simpleMessageStruct", SZC_Match, - m_messageShell, - SLOT(simpleMessage(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_SpecialMesg", SP_Zone, DIR_Server, - "specialMessageStruct", SZC_None, - m_messageShell, - SLOT(specialMessage(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_GuildMOTD", SP_Zone, DIR_Server, - "guildMOTDStruct", SZC_None, - m_messageShell, - SLOT(guildMOTD(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_RandomReq", SP_Zone, DIR_Client, - "randomReqStruct", SZC_Match, - m_messageShell, SLOT(randomRequest(const uint8_t*))); - m_packet->connect2("OP_RandomReply", SP_Zone, DIR_Server, - "randomStruct", SZC_Match, - m_messageShell, SLOT(random(const uint8_t*))); - m_packet->connect2("OP_ConsentResponse", SP_Zone, DIR_Server, - "consentResponseStruct", SZC_Match, - m_messageShell, SLOT(consent(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_DenyResponse", SP_Zone, DIR_Server, - "consentResponseStruct", SZC_Match, - m_messageShell, SLOT(consent(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_Emote", SP_Zone, DIR_Server|DIR_Client, - "emoteTextStruct", SZC_None, - m_messageShell, SLOT(emoteText(const uint8_t*))); - m_packet->connect2("OP_InspectAnswer", SP_Zone, DIR_Server, - "inspectDataStruct", SZC_Match, - m_messageShell, SLOT(inspectData(const uint8_t*))); - m_packet->connect2("OP_MoneyOnCorpse", SP_Zone, DIR_Server, - "moneyOnCorpseStruct", SZC_Match, - m_messageShell, SLOT(moneyOnCorpse(const uint8_t*))); - m_packet->connect2("OP_Logout", SP_Zone, DIR_Server, - "none", SZC_Match, - m_messageShell, SLOT(logOut(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_NewZone", SP_Zone, DIR_Server, - "uint8_t", SZC_None, - m_messageShell, SLOT(zoneNew(const uint8_t*, size_t, uint8_t))); - connect(m_zoneMgr, SIGNAL(zoneBegin(const ClientZoneEntryStruct*, size_t, uint8_t)), - m_messageShell, SLOT(zoneEntryClient(const ClientZoneEntryStruct*))); - connect(m_zoneMgr, SIGNAL(zoneChanged(const zoneChangeStruct*, size_t, uint8_t)), - m_messageShell, SLOT(zoneChanged(const zoneChangeStruct*, size_t, uint8_t))); - connect(m_zoneMgr, SIGNAL(zoneBegin(const QString&)), - m_messageShell, SLOT(zoneBegin(const QString&))); - connect(m_zoneMgr, SIGNAL(zoneEnd(const QString&, const QString&)), - m_messageShell, SLOT(zoneEnd(const QString&, const QString&))); - connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), - m_messageShell, SLOT(zoneChanged(const QString&))); - - m_packet->connect2("OP_MOTD", SP_World, DIR_Server, - "worldMOTDStruct", SZC_None, - m_messageShell, SLOT(worldMOTD(const uint8_t*))); - m_packet->connect2("OP_MemorizeSpell", SP_Zone, DIR_Server|DIR_Client, - "memSpellStruct", SZC_Match, - m_messageShell, SLOT(handleSpell(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_BeginCast", SP_Zone, DIR_Server|DIR_Client, - "beginCastStruct", SZC_Match, - m_messageShell, SLOT(beginCast(const uint8_t*))); - m_packet->connect2("OP_BuffFadeMsg", SP_Zone, DIR_Server|DIR_Client, - "spellFadedStruct", SZC_None, - m_messageShell, SLOT(spellFaded(const uint8_t*))); - m_packet->connect2("OP_CastSpell", SP_Zone, DIR_Server|DIR_Client, - "startCastStruct", SZC_Match, - m_messageShell, SLOT(startCast(const uint8_t*))); - connect(m_zoneMgr, SIGNAL(playerProfile(const charProfileStruct*)), - m_messageShell, SLOT(player(const charProfileStruct*))); - m_packet->connect2("OP_SkillUpdate", SP_Zone, DIR_Server, - "skillIncStruct", SZC_Match, - m_messageShell, SLOT(increaseSkill(const uint8_t*))); - m_packet->connect2("OP_LevelUpdate", SP_Zone, DIR_Server, - "levelUpUpdateStruct", SZC_Match, - m_messageShell, SLOT(updateLevel(const uint8_t*))); - - m_packet->connect2("OP_Consider", SP_Zone, DIR_Server, - "considerStruct", SZC_Match, - m_messageShell, SLOT(consMessage(const uint8_t*, size_t, uint8_t))); - - connect(m_player, SIGNAL(setExp(uint32_t, uint32_t, uint32_t, uint32_t, - uint32_t)), - m_messageShell, SLOT(setExp(uint32_t, uint32_t, uint32_t, - uint32_t, uint32_t))); - connect(m_player, SIGNAL(newExp(uint32_t, uint32_t, uint32_t, uint32_t, - uint32_t, uint32_t)), - m_messageShell, SLOT(newExp(uint32_t, uint32_t, uint32_t, - uint32_t, uint32_t, uint32_t))); - connect(m_player, SIGNAL(setAltExp(uint32_t, uint32_t, uint32_t, uint32_t)), - m_messageShell, SLOT(setAltExp(uint32_t, uint32_t, uint32_t, uint32_t))); - connect(m_player, SIGNAL(newAltExp(uint32_t, uint32_t, uint32_t, uint32_t, - uint32_t, uint32_t)), - m_messageShell, SLOT(newAltExp(uint32_t, uint32_t, uint32_t, uint32_t, - uint32_t, uint32_t))); - - connect(m_spawnShell, SIGNAL(addItem(const Item*)), - m_messageShell, SLOT(addItem(const Item*))); - connect(m_spawnShell, SIGNAL(delItem(const Item*)), - m_messageShell, SLOT(delItem(const Item*))); - connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), - m_messageShell, SLOT(killSpawn(const Item*))); - - connect(m_dateTimeMgr, SIGNAL(syncDateTime(const QDateTime&)), - m_messageShell, SLOT(syncDateTime(const QDateTime&))); - -// 9/3/2008 - Removed. Serialized packet now. -// m_packet->connect2("OP_GroupUpdate", SP_Zone, DIR_Server, -// "groupUpdateStruct", SZC_None, -// m_messageShell, SLOT(groupUpdate(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_GroupInvite", SP_Zone, DIR_Client|DIR_Server, - "groupInviteStruct", SZC_None, - m_messageShell, SLOT(groupInvite(const uint8_t*, size_t, uint8_t))); -// m_packet->connect2("OP_GroupInvite", SP_Zone, DIR_Server, -// "groupAltInviteStruct", SZC_Match, -// m_messageShell, SLOT(groupInvite(const uint8_t*))); - m_packet->connect2("OP_GroupInvite2", SP_Zone, DIR_Client, - "groupInviteStruct", SZC_None, - m_messageShell, SLOT(groupInvite(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_GroupFollow", SP_Zone, DIR_Server, - "groupFollowStruct", SZC_Match, - m_messageShell, SLOT(groupFollow(const uint8_t*))); - m_packet->connect2("OP_GroupFollow2", SP_Zone, DIR_Server, - "groupFollowStruct", SZC_Match, - m_messageShell, SLOT(groupFollow(const uint8_t*))); - m_packet->connect2("OP_GroupDisband", SP_Zone, DIR_Server, - "groupDisbandStruct", SZC_Match, - m_messageShell, SLOT(groupDisband(const uint8_t*))); - m_packet->connect2("OP_GroupDisband2", SP_Zone, DIR_Server, - "groupDisbandStruct", SZC_Match, - m_messageShell, SLOT(groupDisband(const uint8_t*))); - m_packet->connect2("OP_GroupCancelInvite", SP_Zone, DIR_Server|DIR_Client, - "groupDeclineStruct", SZC_Match, - m_messageShell, SLOT(groupDecline(const uint8_t*))); - m_packet->connect2("OP_GroupLeader", SP_Zone, DIR_Server, - "groupLeaderChangeStruct", SZC_Match, - m_messageShell, SLOT(groupLeaderChange(const uint8_t*))); - } - - if (m_filterNotifications) - { - connect(m_spawnShell, SIGNAL(addItem(const Item*)), - m_filterNotifications, SLOT(addItem(const Item*))); - connect(m_spawnShell, SIGNAL(delItem(const Item*)), - m_filterNotifications, SLOT(delItem(const Item*))); - connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), - m_filterNotifications, SLOT(killSpawn(const Item*))); - connect(m_spawnShell, SIGNAL(changeItem(const Item*, uint32_t)), - m_filterNotifications, - SLOT(changeItem(const Item*, uint32_t))); - } - - // connect interface slots to Packet signals - m_packet->connect2("OP_TargetMouse", SP_Zone, DIR_Client|DIR_Server, - "clientTargetStruct", SZC_Match, - this, SLOT(clientTarget(const uint8_t*))); -#if 0 // ZBTEMP - connect(m_packet, SIGNAL(attack2Hand1(const uint8_t*, size_t, uint8_t)), - this, SLOT(attack2Hand1(const uint8_t*))); -#endif - m_packet->connect2("OP_Action2", SP_Zone, DIR_Client|DIR_Server, - "action2Struct", SZC_Match, - this, SLOT(action2Message(const uint8_t*))); - m_packet->connect2("OP_Death", SP_Zone, DIR_Server, - "newCorpseStruct", SZC_Match, - this, SLOT(combatKillSpawn(const uint8_t*))); -#if 0 // ZBTEMP - connect(m_packet, SIGNAL(interruptSpellCast(const uint8_t*, size_t, uint8_t)), - this, SLOT(interruptSpellCast(const uint8_t*))); - connect(m_packet, SIGNAL(moneyUpdate(const uint8_t*, size_t, uint8_t)), - this, SLOT(moneyUpdate(const uint8_t*))); - connect(m_packet, SIGNAL(moneyThing(const uint8_t*, size_t, uint8_t)), - this, SLOT(moneyThing(const uint8_t*))); -#endif // ZBTEMP - - connect(m_packet, SIGNAL(toggle_session_tracking(bool)), - this, SLOT(toggle_net_session_tracking(bool))); - - // connect EQInterface slots to ZoneMgr signals - connect(m_zoneMgr, SIGNAL(zoneBegin(const QString&)), - this, SLOT(zoneBegin(const QString&))); - connect(m_zoneMgr, SIGNAL(zoneEnd(const QString&, const QString&)), - this, SLOT(zoneEnd(const QString&, const QString&))); - connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), - this, SLOT(zoneChanged(const QString&))); - - // connect the SpellShell slots to EQInterface signals - connect(this, SIGNAL(spellMessage(QString&)), - m_spellShell, SLOT(spellMessage(QString&))); - - // connect EQInterface slots to SpawnShell signals - connect(m_spawnShell, SIGNAL(addItem(const Item*)), - this, SLOT(addItem(const Item*))); - connect(m_spawnShell, SIGNAL(delItem(const Item*)), - this, SLOT(delItem(const Item*))); - connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), - this, SLOT(killSpawn(const Item*))); - connect(m_spawnShell, SIGNAL(changeItem(const Item*, uint32_t)), - this, SLOT(changeItem(const Item*))); - connect(m_spawnShell, SIGNAL(spawnConsidered(const Item*)), - this, SLOT(spawnConsidered(const Item*))); - - // connect the SpawnShell slots to Packet signals - m_packet->connect2("OP_GroundSpawn", SP_Zone, DIR_Server, - "makeDropStruct", SZC_None, - m_spawnShell, SLOT(newGroundItem(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_ClickObject", SP_Zone, DIR_Server, - "remDropStruct", SZC_Match, - m_spawnShell, SLOT(removeGroundItem(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_SpawnDoor", SP_Zone, DIR_Server, - "doorStruct", SZC_Modulus, - m_spawnShell, SLOT(newDoorSpawns(const uint8_t*, size_t, uint8_t))); -// OP_NewSpawn is deprecated in the client -// m_packet->connect2("OP_NewSpawn", SP_Zone, DIR_Server, -// "spawnStruct", SZC_Match, -// m_spawnShell, SLOT(newSpawn(const uint8_t*))); - m_packet->connect2("OP_ZoneEntry", SP_Zone, DIR_Server, - "uint8_t", SZC_None, - m_spawnShell, SLOT(zoneEntry(const uint8_t*, size_t))); - m_packet->connect2("OP_MobUpdate", SP_Zone, DIR_Server|DIR_Client, - "spawnPositionUpdate", SZC_Match, - m_spawnShell, SLOT(updateSpawns(const uint8_t*))); - m_packet->connect2("OP_WearChange", SP_Zone, DIR_Server|DIR_Client, - "SpawnUpdateStruct", SZC_Match, - m_spawnShell, SLOT(updateSpawnInfo(const uint8_t*))); - m_packet->connect2("OP_HPUpdate", SP_Zone, DIR_Server|DIR_Client, - "hpNpcUpdateStruct", SZC_Match, - m_spawnShell, SLOT(updateNpcHP(const uint8_t*))); - m_packet->connect2("OP_DeleteSpawn", SP_Zone, DIR_Server|DIR_Client, - "deleteSpawnStruct", SZC_Match, - m_spawnShell, SLOT(deleteSpawn(const uint8_t*))); - m_packet->connect2("OP_SpawnRename", SP_Zone, DIR_Server, - "spawnRenameStruct", SZC_Match, - m_spawnShell, SLOT(renameSpawn(const uint8_t*))); - m_packet->connect2("OP_Illusion", SP_Zone, DIR_Server|DIR_Client, - "spawnIllusionStruct", SZC_Match, - m_spawnShell, SLOT(illusionSpawn(const uint8_t*))); - m_packet->connect2("OP_SpawnAppearance", SP_Zone, DIR_Server|DIR_Client, - "spawnAppearanceStruct", SZC_Match, - m_spawnShell, SLOT(updateSpawnAppearance(const uint8_t*))); - m_packet->connect2("OP_Death", SP_Zone, DIR_Server, - "newCorpseStruct", SZC_Match, - m_spawnShell, SLOT(killSpawn(const uint8_t*))); -// m_packet->connect2("OP_RespawnFromHover", SP_Zone, DIR_Server|DIR_Client, -// "uint8_t", SZC_None, -// m_spawnShell, SLOT(respawnFromHover(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_Shroud", SP_Zone, DIR_Server, - "spawnShroudSelf", SZC_None, - m_spawnShell, SLOT(shroudSpawn(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_RemoveSpawn", SP_Zone, DIR_Server|DIR_Client, - "removeSpawnStruct", SZC_None, - m_spawnShell, SLOT(removeSpawn(const uint8_t*, size_t, uint8_t))); -#if 0 // ZBTEMP - connect(m_packet, SIGNAL(spawnWearingUpdate(const uint8_t*, size_t, uint8_t)), - m_spawnShell, SLOT(spawnWearingUpdate(const uint8_t*))); -#endif - m_packet->connect2("OP_Consider", SP_Zone, DIR_Server|DIR_Client, - "considerStruct", SZC_Match, - m_spawnShell, SLOT(consMessage(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_NpcMoveUpdate", SP_Zone, DIR_Server, - "uint8_t", SZC_None, - m_spawnShell, SLOT(npcMoveUpdate(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_ClientUpdate", SP_Zone, DIR_Server, - "playerSpawnPosStruct", SZC_Match, - m_spawnShell, SLOT(playerUpdate(const uint8_t*, size_t, uint8_t))); - m_packet->connect2("OP_CorpseLocResponse", SP_Zone, DIR_Server, - "corpseLocStruct", SZC_Match, - m_spawnShell, SLOT(corpseLoc(const uint8_t*))); -#if 0 // No longer used as of 5-22-2008 - m_packet->connect2("OP_ZoneSpawns", SP_Zone, DIR_Server, - "spawnStruct", SZC_None, - m_spawnShell, SLOT(zoneSpawns(const uint8_t*, size_t))); -#endif - - // connect the SpellShell slots to ZoneMgr signals - connect(m_zoneMgr, SIGNAL(zoneChanged(const QString&)), - m_spellShell, SLOT(zoneChanged())); - - // connect the SpellShell slots to SpawnShell signals - connect(m_spawnShell, SIGNAL(killSpawn(const Item*, const Item*, uint16_t)), - m_spellShell, SLOT(killSpawn(const Item*))); - - // connect the SpellShell slots to Player signals - connect(m_player, SIGNAL(newPlayer(void)), - m_spellShell, SLOT(clear())); - connect(m_player, SIGNAL(buffLoad(const spellBuff *)), - m_spellShell, SLOT(buffLoad(const spellBuff *))); - - // connect the SpellShell slots to EQPacket ... [truncated message content] |
From: <cn...@us...> - 2024-08-18 14:58:31
|
Revision: 1510 http://sourceforge.net/p/seq/svn/1510 Author: cn187 Date: 2024-08-18 14:58:29 +0000 (Sun, 18 Aug 2024) Log Message: ----------- Add support for displaying waypoints on map Modified Paths: -------------- showeq/branches/cn187_devel/conf/zoneopcodes.xml showeq/branches/cn187_devel/src/everquest.h showeq/branches/cn187_devel/src/interface.cpp showeq/branches/cn187_devel/src/map.cpp showeq/branches/cn187_devel/src/map.h showeq/branches/cn187_devel/src/mapcore.cpp showeq/branches/cn187_devel/src/mapcore.h showeq/branches/cn187_devel/src/s_everquest.h Modified: showeq/branches/cn187_devel/conf/zoneopcodes.xml =================================================================== --- showeq/branches/cn187_devel/conf/zoneopcodes.xml 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/conf/zoneopcodes.xml 2024-08-18 14:58:29 UTC (rev 1510) @@ -285,8 +285,16 @@ <comment>ItemCode</comment> <payload dir="server" typename="itemPacketStruct" sizechecktype="none"/> </opcode> + <opcode id="29d8" name="OP_WaypointResponse" updated="07/17/24"> + <comment>Server sends waypoint path (for /waypoint, /find)</comment> + <payload dir="server" typename="waypointStruct" sizechecktype="modulus"/> + </opcode> <!-- Not necessary for SEQ to run but here to name packets in logs. --> + <opcode id="252f" name="OP_WaypointRequest" updated="07/17/24"> + <comment>Client requests waypoint path (/waypoint, /find)</comment> + <payload dir="client" typename="waypointRequestStruct" sizechecktype="match"/> + </opcode> <opcode id="ffff" name="OP_LeaderExpUpdate" updated="12/11/13"> <comment>Leadership AA Exp Update</comment> <payload dir="server" typename="leadExpUpdateStruct" sizechecktype="match"/> Modified: showeq/branches/cn187_devel/src/everquest.h =================================================================== --- showeq/branches/cn187_devel/src/everquest.h 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/src/everquest.h 2024-08-18 14:58:29 UTC (rev 1510) @@ -2752,6 +2752,53 @@ struct bazaarSearchResponseStruct response[0]; }; +/* +** Waypoint Request +** Length: 40 octets +** OpCode: WaypointRequest +** +** Used for requesting path from server, for use with +** /waypoint and /find +*/ +struct waypointRequestStruct +{ +/*0000*/ uint32_t unknown0000; // Might be sub-op switch. 1 for Find, 7 for waypoint +/*0004*/ uint16_t unknown0004; +/*0006*/ uint16_t unknown0006; +/*0008*/ uint32_t unknown0008; +/*0012*/ uint32_t unknown0012; +/*0016*/ float loc_y; +/*0020*/ float loc_x; +/*0024*/ float loc_z; +/*0028*/ float wp_y; +/*0032*/ float wp_x; +/*0036*/ float wp_z; +/*0040*/ +}; + + +/* +** Waypoint Response +** Length: variable, modulo sizeof(waypointStruct) +** OpCode: WaypointResponse +** +** Server sends as response to WaypointRequest. Used to give client +** pathfinding coordinates for /waypoint and /find. +** +** If the path is not available ("Mystical forces prevent you...") the +** the response will contain only 1 waypoint struct, with the correct +** y/x coords, but with the z coord being a very large magnitude negative +** value (-1e27). The client uses this to determine whether or not the path +** request succeeded. +*/ +struct waypointStruct +{ + float y; + float x; + float z; +}; + + /*******************************/ /* World Server Structs */ Modified: showeq/branches/cn187_devel/src/interface.cpp =================================================================== --- showeq/branches/cn187_devel/src/interface.cpp 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/src/interface.cpp 2024-08-18 14:58:29 UTC (rev 1510) @@ -2013,6 +2013,13 @@ connect(this, SIGNAL(saveAllPrefs(void)), m_categoryMgr, SLOT(savePrefs(void))); + if (m_mapMgr) + { + m_packet->connect2("OP_WaypointResponse", SP_Zone, DIR_Server, + "waypointStruct", SZC_Modulus, + m_mapMgr, SLOT(setWaypoints(const uint8_t*, size_t, uint8_t))); + } + if (m_zoneMgr) { m_packet->connect2("OP_ZoneEntry", SP_Zone, DIR_Client, Modified: showeq/branches/cn187_devel/src/map.cpp =================================================================== --- showeq/branches/cn187_devel/src/map.cpp 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/src/map.cpp 2024-08-18 14:58:29 UTC (rev 1510) @@ -680,6 +680,9 @@ // only need to deal with position changes if (changeType & tSpawnChangedPosition) { + if (m_mapData.waypointActive()) + m_mapData.checkWaypointComplete(MapPoint(m_player->x(), m_player->y(), m_player->z())); + // make sure it fits on the map display if ( m_mapData.checkPos(item->x(), item->y())) emit mapUpdated(); // signal if the map size has changed @@ -816,6 +819,40 @@ emit editLayerChanged(); } +void MapMgr::setWaypoints(const uint8_t* data, size_t len, uint8_t dir) +{ + const waypointStruct* waypoints = (const waypointStruct*) data; + + m_mapData.clearWaypoints(); + + /* + * First waypoint is destination + * Second waypoint is closest point to you, generally your /loc + * Third waypoint through N-1 gradually move toward your destination + * Final waypoint is destination again + */ + if (len <= sizeof(waypointStruct)) + return; + // NOTE: starting at index 1, so we don't draw a straight line between + // the player and the destination. + auto wp = waypoints[1]; + MapPoint start(wp.x, wp.y, wp.z); + m_mapData.startWaypointLine(start); + for (size_t i=1; i<(len/sizeof(waypointStruct)); ++i) + { + auto wp = waypoints[i]; + MapPoint point(wp.x, wp.y, wp.z); + m_mapData.addWaypoint(point); + } + emit mapUpdated(); +} + +void MapMgr::clearWaypoints() +{ + m_mapData.clearWaypoints(); + emit mapUpdated(); +} + void MapMgr::savePrefs(void) { #if 0 // ZBTEMP: Migrate to place where ever this is set @@ -1059,6 +1096,9 @@ m_action_gridTicks = subMenu->addAction("Grid Ticks", this, SLOT(toggle_gridTicks())); m_action_gridTicks->setCheckable(true); + m_action_waypoints = subMenu->addAction("Waypoints", this, SLOT(toggle_waypoints())); + m_action_waypoints->setCheckable(true); + m_action_locations = subMenu->addAction("Locations", this, SLOT(toggle_locations())); m_action_locations->setCheckable(true); @@ -1132,6 +1172,9 @@ m_action_gridLineColor = addAction("Grid Line Color...", this, SLOT(select_gridLineColor())); + m_action_waypointColor = addAction("Waypoint Color...", this, + SLOT(select_waypointColor())); + m_action_backgroundColor = addAction("Background Color...", this, SLOT(select_backgroundColor())); @@ -1283,6 +1326,8 @@ addAction("Save Map Image...", m_map, SLOT(saveMapImage())); + addAction("Clear Current Waypoint", m_map, SLOT(clearWaypoints())); + connect(this, SIGNAL(aboutToShow()), this, SLOT(init_Menu())); } @@ -1316,6 +1361,7 @@ m_action_playerView->setChecked(m_map->showPlayerView()); m_action_gridLines->setChecked(m_map->showGridLines()); m_action_gridTicks->setChecked(m_map->showGridTicks()); + m_action_waypoints->setChecked(m_map->showWaypoints()); m_action_locations->setChecked(m_map->showLocations()); m_action_spawns->setChecked(m_map->showSpawns()); m_action_spawnPoints->setChecked(m_map->showSpawnPoints()); @@ -1486,6 +1532,11 @@ m_map->setShowGridTicks(!m_map->showGridTicks()); } +void MapMenu::toggle_waypoints() +{ + m_map->setShowWaypoints(!m_map->showWaypoints()); +} + void MapMenu::toggle_locations() { m_map->setShowLocations(!m_map->showLocations()); @@ -1590,6 +1641,18 @@ m_map->setGridLineColor(newColor); } +void MapMenu::select_waypointColor() +{ + QString name = QString("ShowEQ - ") + m_map->preferenceName() + + " Waypoint Color"; + QColor newColor = QColorDialog::getColor(m_map->waypointColor(), + m_map, name); + + if (newColor.isValid()) + m_map->setWaypointColor(newColor); +} + + void MapMenu::select_backgroundColor() { QString name = QString("ShowEQ - ") + m_map->preferenceName() @@ -1817,6 +1880,9 @@ tmpPrefString = "ShowGridTicks"; m_param.setShowGridTicks(pSEQPrefs->getPrefBool(tmpPrefString, prefString, true)); + tmpPrefString = "ShowWaypoints"; + m_param.setShowWaypoints(pSEQPrefs->getPrefBool(tmpPrefString, prefString, true)); + tmpPrefString = "ShowBackgroundImage"; m_param.setShowBackgroundImage(pSEQPrefs->getPrefBool(tmpPrefString, prefString, true)); @@ -1832,6 +1898,9 @@ tmpPrefString = "GridLineColor"; m_param.setGridLineColor(pSEQPrefs->getPrefColor(tmpPrefString, prefString, QColor("#194819"))); + tmpPrefString = "WaypointColor"; + m_param.setWaypointColor(pSEQPrefs->getPrefColor(tmpPrefString, prefString, QColor("#ff007f"))); + tmpPrefString = "BackgroundColor"; m_param.setBackgroundColor(pSEQPrefs->getPrefColor(tmpPrefString, prefString, QColor("black"))); @@ -2079,11 +2148,24 @@ m_mapPanX = me->x(); m_mapPanY = me->y(); #endif - } - else + } + else { + uint32_t dist = 15; + + if (m_mapMgr->mapData().waypointActive()) + { + QPoint clickpoint(m_param.invertXOffset(me->x()), m_param.invertYOffset(me->y())); + const MapPoint* closest_wp = m_mapMgr->mapData().closestWaypointToPoint2D(clickpoint, dist); + if (closest_wp) + { + m_mapMgr->clearWaypoints(); + return; + } + } + + const Item* closestSpawn; - uint32_t dist = 15; // find the nearest spawn within a reasonable range closestSpawn = closestSpawnToPoint(me->pos(), dist); @@ -2934,6 +3016,17 @@ refreshMap (); } +void Map::setWaypointColor(const QColor& color) +{ + m_param.setWaypointColor(color); + + // set color preference + pSEQPrefs->setPrefColor("WaypointColor", preferenceName(), m_param.waypointColor()); + + if(!m_cacheChanges) + refreshMap (); +} + void Map::setBackgroundColor(const QColor& color) { m_param.setBackgroundColor(color); @@ -3041,6 +3134,22 @@ refreshMap (); } +void Map::clearWaypoints() +{ + m_mapMgr->clearWaypoints(); +} + +void Map::setShowWaypoints(bool val) +{ + m_param.setShowWaypoints(val); + + QString tmpPrefString = "ShowWaypoints"; + pSEQPrefs->setPrefBool(tmpPrefString, preferenceName(), m_param.showWaypoints()); + + if(!m_cacheChanges) + refreshMap (); +} + void Map::setCacheAlwaysRepaint(bool val) { m_mapCache.setAlwaysRepaint(val); @@ -3119,10 +3228,12 @@ out << "ShowMapLines: " << m_param.showLines() << ENDL; out << "ShowGridLines: " << m_param.showGridLines() << ENDL; out << "ShowGridTicks: " << m_param.showGridTicks() << ENDL; + out << "ShowWaypointss: " << m_param.showWaypoints() << ENDL; out << "ShowBackgroundImage: " << m_param.showBackgroundImage() << ENDL; out << "GridResolution: " << m_param.gridResolution() << ENDL; out << "GridTickColor: " << m_param.gridTickColor().name() << ENDL; out << "GridLineColor: " << m_param.gridLineColor().name() << ENDL; + out << "WaypointColor: " << m_param.waypointColor().name() << ENDL; out << "BackgroundColor: " << m_param.backgroundColor().name() << ENDL; out << "HeadRoom: " << m_param.headRoom() << ENDL; out << "FloorRoom: " << m_param.floorRoom() << ENDL; @@ -4671,7 +4782,7 @@ // only need to deal with position changes if (changeType & tSpawnChangedPosition) { - if (m_followMode == tFollowSpawn) + if (m_followMode == tFollowSpawn) { // follow mode is follow spawn, check if this is the selected spawn // and if so, reAdjust around it's position. Modified: showeq/branches/cn187_devel/src/map.h =================================================================== --- showeq/branches/cn187_devel/src/map.h 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/src/map.h 2024-08-18 14:58:29 UTC (rev 1510) @@ -202,9 +202,12 @@ void showLineDlg(QWidget* parent); void scaleDownZ(int16_t); void scaleUpZ(int16_t); - void setEditLayer(int layerNum); + // Waypoint handling + void setWaypoints(const uint8_t* data, size_t len, uint8_t dir); + void clearWaypoints(); + // Preference handling void savePrefs(void); @@ -229,6 +232,7 @@ QString m_curLineColor; QString m_curLineName; QString m_curLocationColor; + QString m_waypointColor; }; //---------------------------------------------------------------------- @@ -261,6 +265,7 @@ void toggle_playerView(); void toggle_gridLines(); void toggle_gridTicks(); + void toggle_waypoints(); void toggle_locations(); void toggle_spawns(); void toggle_spawnPnts(); @@ -282,6 +287,7 @@ void toggle_instanceLocationMarker(); void select_gridTickColor(); void select_gridLineColor(); + void select_waypointColor(); void select_backgroundColor(); void select_font(); void select_fovColor(); @@ -321,6 +327,7 @@ QAction* m_action_playerView; QAction* m_action_gridLines; QAction* m_action_gridTicks; + QAction* m_action_waypoints; QAction* m_action_locations; QAction* m_action_spawns; QAction* m_action_spawnPoints; @@ -342,6 +349,7 @@ #endif QAction* m_action_gridTickColor; QAction* m_action_gridLineColor; + QAction* m_action_waypointColor; QAction* m_action_backgroundColor; QAction* m_action_font; QAction* m_action_drawSizeMenu; @@ -442,6 +450,7 @@ int gridResolution() const { return m_param.gridResolution(); } const QColor& gridTickColor() const { return m_param.gridTickColor(); } const QColor& gridLineColor() const { return m_param.gridLineColor(); } + const QColor& waypointColor() const { return m_param.waypointColor(); } const QColor& backgroundColor() const { return m_param.backgroundColor(); } const QFont& font() const { return m_param.font(); } int headRoom() const { return m_param.headRoom(); } @@ -452,6 +461,7 @@ bool showLines() const { return m_param.showLines(); } bool showGridLines() const { return m_param.showGridLines(); } bool showGridTicks() const { return m_param.showGridTicks(); } + bool showWaypoints() const { return m_param.showWaypoints(); } bool cacheAlwaysRepaint() const { return m_mapCache.alwaysRepaint(); } bool isLayerVisible(uint8_t layerNum) const { return m_param.isLayerVisible(layerNum); } @@ -461,6 +471,7 @@ void saveMapImage(void); void selectSpawn(const Item* item); + void clearWaypoints(); // SpawnShell handling void delItem(const Item* item); @@ -542,6 +553,7 @@ void setGridResolution(int val); void setGridTickColor(const QColor& color); void setGridLineColor(const QColor& color); + void setWaypointColor(const QColor& color); void setBackgroundColor(const QColor& color); void setFont(const QFont& font); void setHeadRoom(int val); @@ -552,6 +564,7 @@ void setShowLines(bool val); void setShowGridLines(bool val); void setShowGridTicks(bool val); + void setShowWaypoints(bool val); void setCacheAlwaysRepaint(bool val); void setShowZoneSafePoint(bool val); void setShowInstanceLocationMarker(bool val); Modified: showeq/branches/cn187_devel/src/mapcore.cpp =================================================================== --- showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-18 14:58:29 UTC (rev 1510) @@ -92,6 +92,7 @@ m_showLines = true; m_showGridLines = true; m_showGridTicks = true; + m_showWaypoints = true; reset(); } @@ -452,7 +453,9 @@ //---------------------------------------------------------------------- // MapData -MapData::MapData() +MapData::MapData(): + m_waypointLayer(nullptr), + m_waypointActive(false) { // clear the structure clear(); @@ -482,6 +485,9 @@ qDeleteAll(m_mapLayers); m_mapLayers.clear(); + delete m_waypointLayer; + m_waypointLayer = NULL; + m_curWaypoints = NULL; qDeleteAll(m_aggros); m_aggros.clear(); @@ -503,6 +509,14 @@ return NULL; } +MapLayer* MapData::waypointLayer() +{ + if (!m_waypointLayer) + m_waypointLayer = new MapLayer(); + + return m_waypointLayer; +} + void MapData::loadMap(const QString& fileName, bool import) { int16_t mx, my, mz; @@ -1639,6 +1653,102 @@ m_editLineM->setColor(color); } +void MapData::startWaypointLine(const MapPoint& point) +{ + if (!m_waypointLayer) + m_waypointLayer = new MapLayer(); + + // create the new line, with just the first point. Color is a placeholder + // for api compatibility. MapParameters.m_waypointColor will be used instead + m_curWaypoints = new MapLineM("waypoints", "#ff007f", point); + + // calculate the XY bounds of the line + m_curWaypoints->calcBounds(); + + // add line to the line list + m_waypointLayer->mLines().append(m_curWaypoints); + + m_waypointActive = true; +} + + +void MapData::addWaypoint(const MapPoint& point) +{ + // make sure there is a line to add to + if (m_curWaypoints == NULL) + return; + + uint32_t pos = m_curWaypoints->size(); + + // increase the size of the line by one point + m_curWaypoints->resize(pos + 1); + + // set the point data + m_curWaypoints->setPoint(pos, point); + + // calculate the XY bounds of the line + m_curWaypoints->calcBounds(); +} + +void MapData::clearWaypoints() +{ + if (!m_curWaypoints || !m_waypointLayer) + return; + + m_waypointActive = false; + m_curWaypoints->clear(); + delete m_waypointLayer->mLines().takeAt(m_waypointLayer->mLines().indexOf(m_curWaypoints)); + m_curWaypoints = NULL; + delete m_waypointLayer; + m_waypointLayer = NULL; +} + +void MapData::checkWaypointComplete(const MapPoint& playerPos) +{ + if (! m_curWaypoints || !m_waypointActive || !m_waypointLayer) return; + + if (playerPos.calcDistInt(*(m_curWaypoints->end()-1)) < WAYPOINT_DONE_RADIUS) + clearWaypoints(); +} + +const MapPoint* MapData::closestWaypointToPoint3D(const MapPoint& point, const uint32_t& dist) const +{ + if (!m_curWaypoints) return NULL; + + MapPoint* closest_wp = NULL; + int closest_dist = dist; + for (auto wp_itr = m_curWaypoints->begin(); wp_itr != m_curWaypoints->end(); ++wp_itr) + { + int wp_dist = point.calcDistInt(*wp_itr); + if (wp_dist < closest_dist) + { + closest_dist = wp_dist; + closest_wp = wp_itr; + } + } + return closest_wp; +} + +const MapPoint* MapData::closestWaypointToPoint2D(const MapPoint& point, const uint32_t& dist) const +{ + if (!m_curWaypoints) return NULL; + + MapPoint* closest_wp = NULL; + int closest_dist = dist; + for (auto wp_itr = m_curWaypoints->begin(); wp_itr != m_curWaypoints->end(); ++wp_itr) + { + int wp_dist = point.calcDist2DInt(*wp_itr); + if (wp_dist < closest_dist) + { + closest_dist = wp_dist; + closest_wp = wp_itr; + } + } + return closest_wp; +} + + + void MapData::scaleDownZ(int16_t factor) { @@ -1938,9 +2048,95 @@ curY_1 = curY_2; } } + } + } +void MapData::paintWaypoints(MapParameters& param, QPainter& p) const +{ + const QRect& screenBounds = param.screenBounds(); + + bool lastInBounds; + bool curInBounds; + int16_t curX_1, curY_1; + int16_t curX_2, curY_2; + uint numPoints; + MapPoint* mData; + + MapLineM* currentLineM = NULL; + + if (m_waypointLayer && param.showWaypoints() && m_waypointActive) + { + const MapPoint* closest_wp = closestWaypointToPoint3D(param.player(), INT_MAX); + + // then paint the M lines that are between the closest wp and the destination + QList<MapLineM*>::const_iterator mmit = m_waypointLayer->mLines().begin(); + for (; mmit != m_waypointLayer->mLines().end(); ++mmit) + { + currentLineM = *mmit; + // if line is outside the currently visible region, skip it. + if (!currentLineM->boundingRect().intersects(screenBounds)) + continue; + + // get the number of points in the line + numPoints = currentLineM->size(); + + // get the underlying array + mData = currentLineM->data(); + + // set pen color + #ifdef DEBUGMAP + seqDebug("lineColor = '%s'", (char *) param.waypointColor()); + #endif + p.setPen(param.waypointColor()); + + // paint a line from the player to the closest waypoint + p.drawLine(param.calcXOffsetI(param.player().x()), + param.calcYOffsetI(param.player().y()), + param.calcXOffsetI(closest_wp->x()), + param.calcYOffsetI(closest_wp->y())); + + int closest_idx = m_curWaypoints->indexOf(*closest_wp); + + curX_1 = mData[closest_idx].x(); + curY_1 = mData[closest_idx].y(); + + // see if the starting position is in bounds + lastInBounds = inRect(screenBounds, curX_1, curY_1); + + // iterate over all the points in the line starting with the next closest + for (uint32_t i = closest_idx + 1; i < numPoints; i++) + { + curX_2 = mData[i].x(); + curY_2 = mData[i].y(); + + // determine if the current position is in bounds + curInBounds = inRect(screenBounds, curX_2, curY_2); + + // draw the line segment if either end is in bounds + if (lastInBounds || curInBounds) + { + p.drawEllipse(param.calcXOffsetI(curX_1) - 1, + param.calcYOffsetI(curY_1) - 1, + 2,2); + p.drawLine(param.calcXOffsetI(curX_1), + param.calcYOffsetI(curY_1), + param.calcXOffsetI(curX_2), + param.calcYOffsetI(curY_2)); + + } + // current becomes the last + lastInBounds = curInBounds; + curX_1 = curX_2; + curY_1 = curY_2; + } + } + } //end if show waypoints +} + + + void MapData::paintDepthFilteredLines(MapParameters& param, QPainter& p) const { //---------------------------------------------------------------------- @@ -2422,7 +2618,8 @@ (m_lastParam.showLocations() != param.showLocations()) || (m_lastParam.showLines() != param.showLines()) || (m_lastParam.showGridLines() != param.showGridLines()) || - (m_lastParam.showGridTicks() != param.showGridTicks()) || + (m_lastParam.showGridTicks() != param.showGridTicks()) || + (m_lastParam.showWaypoints() != param.showWaypoints()) || (m_lastParam.showBackgroundImage() != param.showBackgroundImage()) || (m_lastParam.gridLineColor() != param.gridLineColor()) || (m_lastParam.gridTickColor() != param.gridTickColor()) || @@ -2506,6 +2703,9 @@ } } + if (param.showWaypoints() && m_mapData.waypointActive()) + m_mapData.paintWaypoints(param, tmp); + //---------------------------------------------------------------------- /* Paint the locations */ if (param.showLocations()) Modified: showeq/branches/cn187_devel/src/mapcore.h =================================================================== --- showeq/branches/cn187_devel/src/mapcore.h 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/src/mapcore.h 2024-08-18 14:58:29 UTC (rev 1510) @@ -79,6 +79,7 @@ //---------------------------------------------------------------------- // constants +#define WAYPOINT_DONE_RADIUS 10 //---------------------------------------------------------------------- // MapParameters @@ -122,6 +123,7 @@ int gridResolution() const { return m_gridResolution; } const QColor& gridLineColor() const { return m_gridLineColor; } const QColor& gridTickColor() const { return m_gridTickColor; } + const QColor& waypointColor() const { return m_waypointColor; } const QColor& backgroundColor() const { return m_backgroundColor; } const QFont& font() const { return m_font; } int16_t headRoom() const { return m_headRoom; } @@ -134,6 +136,7 @@ bool showLines() const { return m_showLines; } bool showGridLines() const { return m_showGridLines; } bool showGridTicks() const { return m_showGridTicks; } + bool showWaypoints() const { return m_showWaypoints; } // utility methods int calcXOffset (int mapCoordinate) const; @@ -170,8 +173,10 @@ void setShowLines(bool val) { m_showLines = val; } void setShowGridLines(bool val) { m_showGridLines = val; } void setShowGridTicks(bool val) { m_showGridTicks = val; } + void setShowWaypoints(bool val) { m_showWaypoints = val; } void setGridLineColor(const QColor& color) { m_gridLineColor = color; } void setGridTickColor(const QColor& color) { m_gridTickColor = color; } + void setWaypointColor(const QColor& color) { m_waypointColor = color; } void setHeadRoom(int16_t headRoom); void setFloorRoom(int16_t floorRoom); void setLayerVisibility(uint8_t layerNum, bool isVisible); @@ -201,6 +206,7 @@ int m_gridResolution; QColor m_gridLineColor; QColor m_gridTickColor; + QColor m_waypointColor; QColor m_backgroundColor; QFont m_font; int16_t m_headRoom; @@ -215,6 +221,7 @@ bool m_showLines; bool m_showGridLines; bool m_showGridTicks; + bool m_showWaypoints; uint32_t m_layerVisibility; }; @@ -567,6 +574,7 @@ int16_t maxX() const { return m_maxX; } int16_t maxY() const { return m_maxY; } MapLayer* mapLayer(uint8_t layerNum); + MapLayer* waypointLayer(); uint8_t numLayers() const { return m_mapLayers.count(); } QList<MapAggro*>& aggros() { return m_aggros; } const QPixmap& image() const { return m_image; } @@ -595,6 +603,16 @@ void setEditLayer(uint8_t layerNum) { m_editLayer = layerNum; } uint8_t editLayer() const { return m_editLayer; } + // waypoints + void startWaypointLine(const MapPoint& point); + void addWaypoint(const MapPoint& point); + void clearWaypoints(void); + void checkWaypointComplete(const MapPoint& playerPos); + bool waypointActive() const { return m_waypointActive; } + const MapPoint* closestWaypointToPoint3D(const MapPoint& point, const uint32_t& dist) const; + const MapPoint* closestWaypointToPoint2D(const MapPoint& point, const uint32_t& dist) const; + void paintWaypoints(MapParameters& param, QPainter& p) const; + // map painting void paintGrid(MapParameters& param, QPainter& p) const; void paintLines(MapParameters& param, QPainter& p) const; @@ -623,6 +641,9 @@ bool m_xset; bool m_yset; + MapLayer* m_waypointLayer; + MapLineM* m_curWaypoints; + bool m_waypointActive; }; inline Modified: showeq/branches/cn187_devel/src/s_everquest.h =================================================================== --- showeq/branches/cn187_devel/src/s_everquest.h 2024-08-16 02:42:37 UTC (rev 1509) +++ showeq/branches/cn187_devel/src/s_everquest.h 2024-08-18 14:58:29 UTC (rev 1510) @@ -124,6 +124,8 @@ AddStruct(bazaarTraderRequest); AddStruct(bazaarSearchQueryStruct); AddStruct(bazaarSearchResponseStruct); +AddStruct(waypointRequestStruct); +AddStruct(waypointStruct); AddStruct(guildListStruct); AddStruct(worldGuildListStruct); AddStruct(worldMOTDStruct); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:42:38
|
Revision: 1509 http://sourceforge.net/p/seq/svn/1509 Author: cn187 Date: 2024-08-16 02:42:37 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Fix compile error for qt4 Modified Paths: -------------- showeq/branches/cn187_devel/src/mapcore.cpp Modified: showeq/branches/cn187_devel/src/mapcore.cpp =================================================================== --- showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:28 UTC (rev 1508) +++ showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:42:37 UTC (rev 1509) @@ -2344,7 +2344,12 @@ // draw the text int offset_x = -2; int offset_y = -2; + +#if (QT_VERSION >= QT_VERSION_CHECK(5,11,0)) int ha = fm.horizontalAdvance(currentLoc->name()); +#else + int ha = fm.width(currentLoc->name()); +#endif // if the location label is going to run off the side of the map (and // thus be cut off), scoot the label to the left enough to show the // whole thing This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:23:31
|
Revision: 1508 http://sourceforge.net/p/seq/svn/1508 Author: cn187 Date: 2024-08-16 02:23:28 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Don't cut off map location labels if at right edge of map Modified Paths: -------------- showeq/branches/cn187_devel/src/mapcore.cpp Modified: showeq/branches/cn187_devel/src/mapcore.cpp =================================================================== --- showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:21 UTC (rev 1507) +++ showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:28 UTC (rev 1508) @@ -2313,6 +2313,7 @@ // set the font p.setFont(param.font()); + QFontMetrics fm(param.font()); for (int i = 0; i < m_mapLayers.count(); ++i) { @@ -2341,8 +2342,17 @@ p.setPen(color); // draw the text - p.drawText(param.calcXOffsetI(currentLoc->x()) - 2, - param.calcYOffsetI(currentLoc->y()) - 2, + int offset_x = -2; + int offset_y = -2; + int ha = fm.horizontalAdvance(currentLoc->name()); + // if the location label is going to run off the side of the map (and + // thus be cut off), scoot the label to the left enough to show the + // whole thing + if (param.calcXOffsetI(currentLoc->x()) + ha > param.calcXOffsetI(m_minX)) + offset_x -= ha - (param.calcXOffsetI(m_minX) - param.calcXOffsetI(currentLoc->x())); + + p.drawText(param.calcXOffsetI(currentLoc->x()) + offset_x, + param.calcYOffsetI(currentLoc->y()) + offset_y, currentLoc->name()); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:23:23
|
Revision: 1507 http://sourceforge.net/p/seq/svn/1507 Author: cn187 Date: 2024-08-16 02:23:21 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Don't hardcode colors for lines with unspecified color (SEQ map format) Modified Paths: -------------- showeq/branches/cn187_devel/src/mapcore.cpp Modified: showeq/branches/cn187_devel/src/mapcore.cpp =================================================================== --- showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:13 UTC (rev 1506) +++ showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:21 UTC (rev 1507) @@ -667,8 +667,9 @@ // Line Color color = (*fit++); - if (color.isEmpty()) - color = "#7F7F7F"; + if (color.isEmpty()) + color = pSEQPrefs->getPrefString("MapColor" + QString::number(21),//use gray + "MapColors", getMapConvertColor(0x80, 0x80, 0x80)); // Number of points specifiedLinePoints = (*fit++).toUInt(&ok); @@ -748,8 +749,9 @@ // Line Color color = (*fit++); - if (color.isEmpty()) - color = "#7F7F7F"; + if (color.isEmpty()) + color = pSEQPrefs->getPrefString("MapColor" + QString::number(21),//use gray + "MapColors", getMapConvertColor(0x80, 0x80, 0x80)); // Number of points specifiedLinePoints = (*fit++).toUInt(&ok); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:23:16
|
Revision: 1506 http://sourceforge.net/p/seq/svn/1506 Author: cn187 Date: 2024-08-16 02:23:13 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Fix duplication of map labels when using non-SOE map format Modified Paths: -------------- showeq/branches/cn187_devel/src/mapcore.cpp Modified: showeq/branches/cn187_devel/src/mapcore.cpp =================================================================== --- showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:05 UTC (rev 1505) +++ showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:13 UTC (rev 1506) @@ -832,14 +832,16 @@ // add the appropriate style Location depending on if the global height is set layer->locations().append(new MapLocation(name, color, mx, my, mz)); } - - // add the appropriate style Location depending on if the global - // height has been set - if (globHeightSet) - layer->locations().append(new MapLocation(name, color, mx, my, globHeight)); - else - layer->locations().append(new MapLocation(name, color, mx, my)); - + else + { + // add the appropriate style Location depending on if the global + // height has been set + if (globHeightSet) + layer->locations().append(new MapLocation(name, color, mx, my, globHeight)); + else + layer->locations().append(new MapLocation(name, color, mx, my)); + } + // adjust map boundaries quickCheckPos(mx, my); } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:23:07
|
Revision: 1505 http://sourceforge.net/p/seq/svn/1505 Author: cn187 Date: 2024-08-16 02:23:05 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Don't extend map area to 0,0 if the map doesn't reach that far Modified Paths: -------------- showeq/branches/cn187_devel/src/mapcore.cpp showeq/branches/cn187_devel/src/mapcore.h Modified: showeq/branches/cn187_devel/src/mapcore.cpp =================================================================== --- showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:22:51 UTC (rev 1504) +++ showeq/branches/cn187_devel/src/mapcore.cpp 2024-08-16 02:23:05 UTC (rev 1505) @@ -472,6 +472,8 @@ { m_zoneLongName = ""; m_zoneShortName = ""; + m_xset = false; + m_yset = false; m_minX = -50; m_maxX = 50; m_minY = -50; Modified: showeq/branches/cn187_devel/src/mapcore.h =================================================================== --- showeq/branches/cn187_devel/src/mapcore.h 2024-08-16 02:22:51 UTC (rev 1504) +++ showeq/branches/cn187_devel/src/mapcore.h 2024-08-16 02:23:05 UTC (rev 1505) @@ -620,6 +620,9 @@ QPixmap m_image; bool m_imageLoaded; uint8_t m_editLayer; + + bool m_xset; + bool m_yset; }; inline @@ -631,6 +634,23 @@ printf("in x: %i, in y: %i, max(%i,%i) Min(%i,%i)\n", x, y, m_maxX, m_maxY, m_minX, m_minY); #endif /* MAP_DEBUG */ + if (!m_xset) + { + m_minX = x; + m_maxX = x; + m_xset = true; + flag = true; + } + + if (!m_yset) + { + m_minY = y; + m_maxY = y; + m_yset = true; + flag = true; + } + + if (x > m_maxX) { m_maxX = x; @@ -664,6 +684,20 @@ { // quick, no-nonsense checking of the bounds, for batch use. // call updateBounds() after finished with the batch + if (!m_xset) + { + m_minX = x; + m_maxX = x; + m_xset = true; + } + + if (!m_yset) + { + m_minY = y; + m_maxY = y; + m_yset = true; + } + if (x > m_maxX) m_maxX = x; if (y > m_maxY) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:22:53
|
Revision: 1504 http://sourceforge.net/p/seq/svn/1504 Author: cn187 Date: 2024-08-16 02:22:51 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Mask high bits of zoneid so player purchased housing/guildhalls don't show as unknown Modified Paths: -------------- showeq/branches/cn187_devel/src/zonemgr.cpp Modified: showeq/branches/cn187_devel/src/zonemgr.cpp =================================================================== --- showeq/branches/cn187_devel/src/zonemgr.cpp 2024-08-16 02:22:29 UTC (rev 1503) +++ showeq/branches/cn187_devel/src/zonemgr.cpp 2024-08-16 02:22:51 UTC (rev 1504) @@ -101,8 +101,8 @@ QString ZoneMgr::zoneNameFromID(uint16_t zoneId) { const char* zoneName = NULL; - if (zoneId < (sizeof(zoneNames) / sizeof (ZoneNames))) - zoneName = zoneNames[zoneId].shortName; + if ((zoneId & 0x0fff) < (sizeof(zoneNames) / sizeof(ZoneNames))) + zoneName = zoneNames[zoneId & 0x0fff].shortName; if (zoneName != NULL) return zoneName; @@ -120,8 +120,8 @@ QString ZoneMgr::zoneLongNameFromID(uint16_t zoneId) { const char* zoneName = NULL; - if (zoneId < (sizeof(zoneNames) / sizeof (ZoneNames))) - zoneName = zoneNames[zoneId].longName; + if ((zoneId & 0x0fff) < (sizeof(zoneNames) / sizeof(ZoneNames))) + zoneName = zoneNames[zoneId & 0x0fff].longName; if (zoneName != NULL) return zoneName; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:22:46
|
Revision: 1503 http://sourceforge.net/p/seq/svn/1503 Author: cn187 Date: 2024-08-16 02:22:29 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Fix sort by distance when Fast Machine is enabled Modified Paths: -------------- showeq/branches/cn187_devel/src/spawnlistcommon.cpp Modified: showeq/branches/cn187_devel/src/spawnlistcommon.cpp =================================================================== --- showeq/branches/cn187_devel/src/spawnlistcommon.cpp 2024-08-16 02:22:23 UTC (rev 1502) +++ showeq/branches/cn187_devel/src/spawnlistcommon.cpp 2024-08-16 02:22:29 UTC (rev 1503) @@ -144,10 +144,20 @@ case 5: // coord 2 case 6: // coord 3 case 7: // ID - case 8: // distance return data(column, Qt::DisplayRole).value<int>() < other.data(column, Qt::DisplayRole).value<int>(); + case 8: // distance + // "fast machine" option will use float, not int + return + ((data(column, Qt::DisplayRole).canConvert<float>()) ? + data(column, Qt::DisplayRole).value<float>() : + data(column, Qt::DisplayRole).value<int>()) + < + ((other.data(column, Qt::DisplayRole).canConvert<float>()) ? + other.data(column, Qt::DisplayRole).value<float>() : + other.data(column, Qt::DisplayRole).value<int>()); + case 0: // name case 9: // race case 10:// class This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-08-16 02:22:24
|
Revision: 1502 http://sourceforge.net/p/seq/svn/1502 Author: cn187 Date: 2024-08-16 02:22:23 +0000 (Fri, 16 Aug 2024) Log Message: ----------- Swap x/y when reading charProfileStruct Fixes starting map size issue in NRo, etc. Modified Paths: -------------- showeq/branches/cn187_devel/src/zonemgr.cpp Modified: showeq/branches/cn187_devel/src/zonemgr.cpp =================================================================== --- showeq/branches/cn187_devel/src/zonemgr.cpp 2024-07-26 01:47:28 UTC (rev 1501) +++ showeq/branches/cn187_devel/src/zonemgr.cpp 2024-08-16 02:22:23 UTC (rev 1502) @@ -473,12 +473,12 @@ player->zoneId = netStream.readUInt16NC(); player->zoneInstance = netStream.readUInt16NC(); + memcpy(&player->y, netStream.pos(), sizeof(player->y)); + netStream.skipBytes(sizeof(player->y)); + memcpy(&player->x, netStream.pos(), sizeof(player->x)); netStream.skipBytes(sizeof(player->x)); - memcpy(&player->y, netStream.pos(), sizeof(player->y)); - netStream.skipBytes(sizeof(player->y)); - memcpy(&player->z, netStream.pos(), sizeof(player->z)); netStream.skipBytes(sizeof(player->z)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-07-26 01:47:31
|
Revision: 1501 http://sourceforge.net/p/seq/svn/1501 Author: cn187 Date: 2024-07-26 01:47:28 +0000 (Fri, 26 Jul 2024) Log Message: ----------- Release 6.3.16 - Update to version 6.3.16 - Support for EQ Patch 07/17/24 - Struct and opcode updates (Newby) Modified Paths: -------------- showeq/branches/cn187_devel/ChangeLog showeq/branches/cn187_devel/conf/zoneopcodes.xml showeq/branches/cn187_devel/configure.in showeq/branches/cn187_devel/src/everquest.h Modified: showeq/branches/cn187_devel/ChangeLog =================================================================== --- showeq/branches/cn187_devel/ChangeLog 2024-07-26 01:47:19 UTC (rev 1500) +++ showeq/branches/cn187_devel/ChangeLog 2024-07-26 01:47:28 UTC (rev 1501) @@ -1,3 +1,9 @@ +cn187 (07/17/24) +---------------- +- Update to version 6.3.16 +- Support for EQ Patch 07/17/24 +- Struct and opcode updates (Newby) + cn187 (06/19/24) ---------------- - Update to version 6.3.15 Modified: showeq/branches/cn187_devel/conf/zoneopcodes.xml =================================================================== --- showeq/branches/cn187_devel/conf/zoneopcodes.xml 2024-07-26 01:47:19 UTC (rev 1500) +++ showeq/branches/cn187_devel/conf/zoneopcodes.xml 2024-07-26 01:47:28 UTC (rev 1501) @@ -3,37 +3,37 @@ <seqopcodes> <!-- Critical opcodes used directly by ShowEQ --> - <opcode id="3132" name="OP_PlayerProfile" updated="06/19/24"> + <opcode id="3193" name="OP_PlayerProfile" updated="07/17/24"> <comment>CharProfileCode</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="5e3e" name="OP_ZoneEntry" updated="06/19/24"> + <opcode id="1eb3" name="OP_ZoneEntry" updated="07/17/24"> <comment>ZoneEntryCode</comment> <payload dir="client" typename="ClientZoneEntryStruct" sizechecktype="match"/> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="3407" name="OP_TimeOfDay" updated="06/19/24"> + <opcode id="39b4" name="OP_TimeOfDay" updated="07/17/24"> <comment>TimeOfDayCode</comment> <payload dir="server" typename="timeOfDayStruct" sizechecktype="match"/> </opcode> - <opcode id="5e02" name="OP_NewZone" updated="06/19/24"> + <opcode id="518c" name="OP_NewZone" updated="07/17/24"> <comment>NewZoneCode</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="12c4" name="OP_SpawnDoor" updated="06/19/24"> + <opcode id="221a" name="OP_SpawnDoor" updated="07/17/24"> <comment>DoorSpawnsCode</comment> <payload dir="server" typename="doorStruct" sizechecktype="modulus"/> </opcode> - <opcode id="739b" name="OP_GroundSpawn" updated="06/19/24"> + <opcode id="4feb" name="OP_GroundSpawn" updated="07/17/24"> <comment>MakeDropCode</comment> <payload dir="server" typename="makeDropStruct" sizechecktype="none"/> <payload dir="client" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="6086" name="OP_SendZonePoints" updated="06/19/24"> + <opcode id="4743" name="OP_SendZonePoints" updated="07/17/24"> <comment>Coords in a zone that will port you to another zone</comment> <payload dir="server" typename="zonePointsStruct" sizechecktype="none"/> </opcode> - <opcode id="0753" name="OP_AAExpUpdate" updated="06/19/24"> + <opcode id="0d97" name="OP_AAExpUpdate" updated="07/17/24"> <comment>Receiving AA experience. Also when percent to AA changes.</comment> <payload dir="server" typename="altExpUpdateStruct" sizechecktype="match"/> </opcode> @@ -41,32 +41,32 @@ <comment>ExpUpdateCode</comment> <payload dir="server" typename="expUpdateStruct" sizechecktype="match"/> </opcode> - <opcode id="6b08" name="OP_GuildMOTD" updated="06/19/24"> + <opcode id="37e3" name="OP_GuildMOTD" updated="07/17/24"> <comment>GuildMOTD</comment> <payload dir="server" typename="guildMOTDStruct" sizechecktype="none"/> </opcode> - <opcode id="0c4e" name="OP_ClientUpdate" updated="06/19/24"> + <opcode id="4187" name="OP_ClientUpdate" updated="07/17/24"> <comment>Position updates</comment> <payload dir="server" typename="playerSpawnPosStruct" sizechecktype="match"/> <payload dir="both" typename="playerSelfPosStruct" sizechecktype="match"/> </opcode> - <opcode id="6ed3" name="OP_NpcMoveUpdate" updated="06/19/24"> + <opcode id="1f6b" name="OP_NpcMoveUpdate" updated="07/17/24"> <comment>Position updates</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="669f" name="OP_MobUpdate" updated="06/19/24"> + <opcode id="3afa" name="OP_MobUpdate" updated="07/17/24"> <comment>MobUpdateCode</comment> <payload dir="both" typename="spawnPositionUpdate" sizechecktype="match"/> </opcode> - <opcode id="0bee" name="OP_DeleteSpawn" updated="06/19/24"> + <opcode id="1a9e" name="OP_DeleteSpawn" updated="07/17/24"> <comment>DeleteSpawnCode</comment> <payload dir="both" typename="deleteSpawnStruct" sizechecktype="match"/> </opcode> - <opcode id="1a60" name="OP_RemoveSpawn" updated="06/19/24"> + <opcode id="67ae" name="OP_RemoveSpawn" updated="07/17/24"> <comment>Remove spawn from zone</comment> <payload dir="both" typename="removeSpawnStruct" sizechecktype="none"/> </opcode> - <opcode id="3f63" name="OP_Death" updated="06/19/24"> + <opcode id="7c61" name="OP_Death" updated="07/17/24"> <comment>old NewCorpseCode</comment> <payload dir="server" typename="newCorpseStruct" sizechecktype="match"/> </opcode> @@ -74,7 +74,7 @@ <comment>SpawnUpdateCode</comment> <payload dir="both" typename="SpawnUpdateStruct" sizechecktype="match"/> </opcode> - <opcode id="59cf" name="OP_SpawnAppearance" updated="06/19/24"> + <opcode id="033d" name="OP_SpawnAppearance" updated="07/17/24"> <comment>SpawnAppearanceCode</comment> <payload dir="both" typename="spawnAppearanceStruct" sizechecktype="match"/> </opcode> @@ -86,15 +86,15 @@ <comment>NpcHpUpdateCode Update HP % of a PC or NPC</comment> <payload dir="both" typename="hpNpcUpdateStruct" sizechecktype="match"/> </opcode> - <opcode id="082d" name="OP_GuildMemberUpdate" updated="06/19/24"> + <opcode id="2bfb" name="OP_GuildMemberUpdate" updated="07/17/24"> <comment>Info regarding guild members</comment> <payload dir="server" typename="GuildMemberUpdate" sizechecktype="match"/> </opcode> - <opcode id="2870" name="OP_ClickObject" updated="06/19/24"> + <opcode id="4454" name="OP_ClickObject" updated="07/17/24"> <comment>Items dropped on the ground</comment> <payload dir="both" typename="remDropStruct" sizechecktype="match"/> </opcode> - <opcode id="24fc" name="OP_Action" updated="06/19/24"> + <opcode id="681d" name="OP_Action" updated="07/17/24"> <comment>Spells cast etc</comment> <payload dir="both" typename="actionStruct" sizechecktype="match"/> <payload dir="both" typename="actionAltStruct" sizechecktype="match"/> @@ -103,11 +103,11 @@ <comment>Combat actions i.e. bash, kick etc</comment> <payload dir="both" typename="action2Struct" sizechecktype="match"/> </opcode> - <opcode id="0fd2" name="OP_Consider" updated="06/19/24"> + <opcode id="4126" name="OP_Consider" updated="07/17/24"> <comment>ConsiderCode</comment> <payload dir="both" typename="considerStruct" sizechecktype="match"/> </opcode> - <opcode id="133c" name="OP_TargetMouse" updated="06/19/24"> + <opcode id="0987" name="OP_TargetMouse" updated="07/17/24"> <comment>Targeting a person - old ClientTargetCode</comment> <payload dir="both" typename="clientTargetStruct" sizechecktype="match"/> </opcode> @@ -123,7 +123,7 @@ <comment>Server putting players into shroud form</comment> <payload dir="server" typename="spawnShroudSelf" sizechecktype="none"/> </opcode> - <opcode id="146c" name="OP_ZoneChange" updated="06/19/24"> + <opcode id="24bc" name="OP_ZoneChange" updated="07/17/24"> <comment>old ZoneChangeCode</comment> <payload dir="both" typename="zoneChangeStruct" sizechecktype="match"/> </opcode> @@ -191,19 +191,19 @@ <comment>EmoteTextCode</comment> <payload dir="both" typename="emoteTextStruct" sizechecktype="none"/> </opcode> - <opcode id="3256" name="OP_SimpleMessage" updated="06/19/24"> + <opcode id="1520" name="OP_SimpleMessage" updated="07/17/24"> <comment>SimpleMessageCode</comment> <payload dir="server" typename="simpleMessageStruct" sizechecktype="match"/> </opcode> - <opcode id="3fba" name="OP_FormattedMessage" updated="06/19/24"> + <opcode id="3fc6" name="OP_FormattedMessage" updated="07/17/24"> <comment>FormattedMessageCode i.e. pet dismissed etc</comment> <payload dir="server" typename="formattedMessageStruct" sizechecktype="none"/> </opcode> - <opcode id="2148" name="OP_CommonMessage" updated="06/19/24"> + <opcode id="60f9" name="OP_CommonMessage" updated="07/17/24"> <comment>ChannelMessageCode i.e. /tell /ooc /shout etc</comment> <payload dir="both" typename="channelMessageStruct" sizechecktype="none"/> </opcode> - <opcode id="686f" name="OP_SpecialMesg" updated="06/19/24"> + <opcode id="36f2" name="OP_SpecialMesg" updated="07/17/24"> <comment>Communicate textual info to client including hail responses etc</comment> <payload dir="server" typename="specialMessageStruct" sizechecktype="none"/> </opcode> @@ -307,7 +307,7 @@ <comment>List of group members - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="705e" name="OP_GuildMemberList" updated="06/19/24"> + <opcode id="6d8b" name="OP_GuildMemberList" updated="07/17/24"> <comment>List of guild members - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> @@ -367,7 +367,7 @@ <comment>Fellowship information - 2576 bytes</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="ffff" name="OP_ExpandedGuildInfo" updated="05/15/24"> + <opcode id="725b" name="OP_ExpandedGuildInfo" updated="07/17/24"> <comment>Guild ranks and other misc guild data - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> @@ -535,7 +535,7 @@ <comment>Listing of all guilds. Can be triggered by /lfg search?</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="7b05" name="OP_GuildsInZoneList" updated="06/19/24"> + <opcode id="3f04" name="OP_GuildsInZoneList" updated="07/17/24"> <comment>Listing of guild names present in the current zone. Generally seen on zoning</comment> <payload dir="server" typename="guildsInZoneListStruct" sizechecktype="none"/> </opcode> @@ -595,7 +595,7 @@ <comment>Free to play nags and other data - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="238b" name="OP_Find" updated="06/19/24"> + <opcode id="54c9" name="OP_Find" updated="07/17/24"> <comment>Find window data - 112 bytes</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> Modified: showeq/branches/cn187_devel/configure.in =================================================================== --- showeq/branches/cn187_devel/configure.in 2024-07-26 01:47:19 UTC (rev 1500) +++ showeq/branches/cn187_devel/configure.in 2024-07-26 01:47:28 UTC (rev 1501) @@ -2,7 +2,7 @@ dnl $Id$ $Name$ AC_PREREQ(2.59) -AC_INIT(showeq, 6.3.15) +AC_INIT(showeq, 6.3.16) AC_CONFIG_SRCDIR(src/main.cpp) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_SYSTEM Modified: showeq/branches/cn187_devel/src/everquest.h =================================================================== --- showeq/branches/cn187_devel/src/everquest.h 2024-07-26 01:47:19 UTC (rev 1500) +++ showeq/branches/cn187_devel/src/everquest.h 2024-07-26 01:47:28 UTC (rev 1501) @@ -1119,28 +1119,30 @@ struct { + signed deltaX:13; // change in x + signed deltaY:13; // change in y + unsigned padding00:6; + + unsigned heading:12; // heading + signed x:19; // x coord (1st loc value) + unsigned padding01:1; + signed z:19; // z coord (3rd loc value) - unsigned pitch:12; // pitch (up/down heading) - unsigned padding00:1; + unsigned padding02:13; + signed y:19; // y coord (2nd loc value) signed deltaHeading:10; // change in heading - signed y:19; // y coord (2nd loc value) - unsigned padding01:3; + unsigned padding03:3; - signed x:19; // x coord (1st loc value) - unsigned heading:12; // heading - unsigned padding02:1; + signed deltaZ:13; // change in z + unsigned pitch:12; // pitch (up/down heading) + unsigned padding04:7; - signed deltaX:13; // change in x signed animation:10; // current animation - unsigned padding03:9; + unsigned padding05:22; - signed deltaY:13; // change in y - signed deltaZ:13; // change in z - unsigned padding04:6; - }; - int32_t posData[5]; + int32_t posData[6]; }; @@ -2391,7 +2393,7 @@ /* ** Player Position Update -** Length: 24 Octets +** Length: 28 Octets ** OpCode: PlayerPosCode */ struct playerSpawnPosStruct @@ -2399,31 +2401,33 @@ /*0000*/ uint16_t spawnId; /*0002*/ uint16_t spawnId2; /*0004*/ - signed z:19; // z coord (3rd loc value) - unsigned pitch:12; // pitch (up/down heading) - unsigned padding00:1; + signed deltaX:13; // change in x + signed deltaY:13; // change in y + unsigned padding00:6; /*0008*/ - signed deltaHeading:10; // change in heading - signed y:19; // y coord (2nd loc value) - unsigned padding01:3; + unsigned heading:12; // heading + signed x:19; // x coord (1st loc value) + unsigned padding01:1; /*0012*/ - signed x:19; // x coord (1st loc value) - unsigned heading:12; // heading - unsigned padding02:1; + signed z:19; // z coord (3rd loc value) + unsigned padding02:13; /*0016*/ - signed deltaX:13; // change in x - signed animation:10; // current animation - unsigned padding03:9; + signed y:19; // y coord (2nd loc value) + signed deltaHeading:10; // change in heading + unsigned padding03:3; /*0020*/ - signed deltaY:13; // change in y signed deltaZ:13; // change in z - unsigned padding04:6; + unsigned pitch:12; // pitch (up/down heading) + unsigned padding04:7; /*0024*/ + signed animation:10; // current animation + unsigned padding05:22; +/*0028*/ }; /* ** Self Position Update -** Length: 38 Octets +** Length: 42 Octets ** OpCode: PlayerPosCode */ struct playerSelfPosStruct @@ -2432,26 +2436,28 @@ /*0002*/ uint16_t spawnId; // Player's spawn id /*0004*/ uint16_t unknown0004; // ***Placeholder /*0006*/ - signed animation:10; // current animation - unsigned pitch:12; // pitch (up/down heading) - unsigned padding00:10; + float x; // x coord (1st loc value) /*0010*/ - float deltaY; // change in y + signed deltaHeading:10; // change in heading + unsigned padding01:22; /*0014*/ - float deltaX; // change in x + float z; // z coord (3rd loc value) /*0018*/ float deltaZ; // change in z /*0022*/ - float z; // z coord (3rd loc value) + signed animation:10; // current animation + unsigned padding04:22; /*0026*/ - float x; // x coord (1st loc value) + float deltaX; // change in x /*0030*/ - float y; // y coord (2nd loc value) + float deltaY; // change in y /*0034*/ - signed deltaHeading:10; // change in heading unsigned heading:12; // heading - unsigned padding07:10; + unsigned pitch:12; // pitch (up/down heading) + unsigned padding07:8; /*0038*/ + float y; // y coord (2nd loc value) +/*0042*/ }; /* This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-07-26 01:47:22
|
Revision: 1500 http://sourceforge.net/p/seq/svn/1500 Author: cn187 Date: 2024-07-26 01:47:19 +0000 (Fri, 26 Jul 2024) Log Message: ----------- Fix for regex regression due to different behavior between Qt4 and Qt5/6 Modified Paths: -------------- showeq/branches/cn187_devel/src/eqstr.cpp Modified: showeq/branches/cn187_devel/src/eqstr.cpp =================================================================== --- showeq/branches/cn187_devel/src/eqstr.cpp 2024-07-17 23:22:54 UTC (rev 1499) +++ showeq/branches/cn187_devel/src/eqstr.cpp 2024-07-26 01:47:19 UTC (rev 1500) @@ -254,11 +254,11 @@ #else if (!substFormatStringRes.isEmpty()) { - formatString.replace(curPos-2, rxt.matchedLength()+2, substFormatStringRes); + formatString.replace(curPos, rxt.matchedLength(), substFormatStringRes); } else { - formatString.replace(curPos-2, rxt.matchedLength()+2, ""); + formatString.replace(curPos, rxt.matchedLength(), ""); curPos += rxt.matchedLength(); // if no replacement string, skip over } @@ -293,7 +293,7 @@ // some messages contains spell names with additional delimited fields if (sub.contains('^')) { - sub = sub.section("^", -1); + sub = sub.mid(sub.lastIndexOf('^')+1); // they also contain an oddball apostrophe if (sub.startsWith("'")) sub.replace(0, 1, ""); @@ -320,17 +320,17 @@ // some messages contains spell names with additional delimited fields if (sub.contains('^')) { - sub = sub.section("^", -1); + sub = sub.mid(sub.lastIndexOf('^')+1); // they also contain an oddball apostrophe if (sub.startsWith("'")) sub.replace(0, 1, ""); } - formatString.replace(curPos-1, rx.matchedLength()+1, argList[substArg-1]); + formatString.replace(curPos, rx.matchedLength(), sub); } else { //no argument for this replacement, so replace with empty string - formatString.replace(curPos-1, rx.matchedLength()+1, ""); + formatString.replace(curPos, rx.matchedLength(), ""); curPos += rx.matchedLength(); // if no such argument, skip over } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-07-17 23:22:56
|
Revision: 1499 http://sourceforge.net/p/seq/svn/1499 Author: cn187 Date: 2024-07-17 23:22:54 +0000 (Wed, 17 Jul 2024) Log Message: ----------- Tag for release 6.3.16 Added Paths: ----------- showeq/tags/v6_3_16/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-07-17 23:20:39
|
Revision: 1498 http://sourceforge.net/p/seq/svn/1498 Author: cn187 Date: 2024-07-17 23:20:36 +0000 (Wed, 17 Jul 2024) Log Message: ----------- Release 6.3.16 - Update to version 6.3.16 - Support for EQ Patch 07/17/24 - Struct and opcode updates (Newby) Modified Paths: -------------- showeq/trunk/ChangeLog showeq/trunk/conf/zoneopcodes.xml showeq/trunk/configure.in showeq/trunk/src/everquest.h Modified: showeq/trunk/ChangeLog =================================================================== --- showeq/trunk/ChangeLog 2024-07-17 14:27:28 UTC (rev 1497) +++ showeq/trunk/ChangeLog 2024-07-17 23:20:36 UTC (rev 1498) @@ -1,3 +1,9 @@ +cn187 (07/17/24) +---------------- +- Update to version 6.3.16 +- Support for EQ Patch 07/17/24 +- Struct and opcode updates (Newby) + cn187 (06/19/24) ---------------- - Update to version 6.3.15 Modified: showeq/trunk/conf/zoneopcodes.xml =================================================================== --- showeq/trunk/conf/zoneopcodes.xml 2024-07-17 14:27:28 UTC (rev 1497) +++ showeq/trunk/conf/zoneopcodes.xml 2024-07-17 23:20:36 UTC (rev 1498) @@ -3,37 +3,37 @@ <seqopcodes> <!-- Critical opcodes used directly by ShowEQ --> - <opcode id="3132" name="OP_PlayerProfile" updated="06/19/24"> + <opcode id="3193" name="OP_PlayerProfile" updated="07/17/24"> <comment>CharProfileCode</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="5e3e" name="OP_ZoneEntry" updated="06/19/24"> + <opcode id="1eb3" name="OP_ZoneEntry" updated="07/17/24"> <comment>ZoneEntryCode</comment> <payload dir="client" typename="ClientZoneEntryStruct" sizechecktype="match"/> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="3407" name="OP_TimeOfDay" updated="06/19/24"> + <opcode id="39b4" name="OP_TimeOfDay" updated="07/17/24"> <comment>TimeOfDayCode</comment> <payload dir="server" typename="timeOfDayStruct" sizechecktype="match"/> </opcode> - <opcode id="5e02" name="OP_NewZone" updated="06/19/24"> + <opcode id="518c" name="OP_NewZone" updated="07/17/24"> <comment>NewZoneCode</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="12c4" name="OP_SpawnDoor" updated="06/19/24"> + <opcode id="221a" name="OP_SpawnDoor" updated="07/17/24"> <comment>DoorSpawnsCode</comment> <payload dir="server" typename="doorStruct" sizechecktype="modulus"/> </opcode> - <opcode id="739b" name="OP_GroundSpawn" updated="06/19/24"> + <opcode id="4feb" name="OP_GroundSpawn" updated="07/17/24"> <comment>MakeDropCode</comment> <payload dir="server" typename="makeDropStruct" sizechecktype="none"/> <payload dir="client" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="6086" name="OP_SendZonePoints" updated="06/19/24"> + <opcode id="4743" name="OP_SendZonePoints" updated="07/17/24"> <comment>Coords in a zone that will port you to another zone</comment> <payload dir="server" typename="zonePointsStruct" sizechecktype="none"/> </opcode> - <opcode id="0753" name="OP_AAExpUpdate" updated="06/19/24"> + <opcode id="0d97" name="OP_AAExpUpdate" updated="07/17/24"> <comment>Receiving AA experience. Also when percent to AA changes.</comment> <payload dir="server" typename="altExpUpdateStruct" sizechecktype="match"/> </opcode> @@ -41,32 +41,32 @@ <comment>ExpUpdateCode</comment> <payload dir="server" typename="expUpdateStruct" sizechecktype="match"/> </opcode> - <opcode id="6b08" name="OP_GuildMOTD" updated="06/19/24"> + <opcode id="37e3" name="OP_GuildMOTD" updated="07/17/24"> <comment>GuildMOTD</comment> <payload dir="server" typename="guildMOTDStruct" sizechecktype="none"/> </opcode> - <opcode id="0c4e" name="OP_ClientUpdate" updated="06/19/24"> + <opcode id="4187" name="OP_ClientUpdate" updated="07/17/24"> <comment>Position updates</comment> <payload dir="server" typename="playerSpawnPosStruct" sizechecktype="match"/> <payload dir="both" typename="playerSelfPosStruct" sizechecktype="match"/> </opcode> - <opcode id="6ed3" name="OP_NpcMoveUpdate" updated="06/19/24"> + <opcode id="1f6b" name="OP_NpcMoveUpdate" updated="07/17/24"> <comment>Position updates</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="669f" name="OP_MobUpdate" updated="06/19/24"> + <opcode id="3afa" name="OP_MobUpdate" updated="07/17/24"> <comment>MobUpdateCode</comment> <payload dir="both" typename="spawnPositionUpdate" sizechecktype="match"/> </opcode> - <opcode id="0bee" name="OP_DeleteSpawn" updated="06/19/24"> + <opcode id="1a9e" name="OP_DeleteSpawn" updated="07/17/24"> <comment>DeleteSpawnCode</comment> <payload dir="both" typename="deleteSpawnStruct" sizechecktype="match"/> </opcode> - <opcode id="1a60" name="OP_RemoveSpawn" updated="06/19/24"> + <opcode id="67ae" name="OP_RemoveSpawn" updated="07/17/24"> <comment>Remove spawn from zone</comment> <payload dir="both" typename="removeSpawnStruct" sizechecktype="none"/> </opcode> - <opcode id="3f63" name="OP_Death" updated="06/19/24"> + <opcode id="7c61" name="OP_Death" updated="07/17/24"> <comment>old NewCorpseCode</comment> <payload dir="server" typename="newCorpseStruct" sizechecktype="match"/> </opcode> @@ -74,7 +74,7 @@ <comment>SpawnUpdateCode</comment> <payload dir="both" typename="SpawnUpdateStruct" sizechecktype="match"/> </opcode> - <opcode id="59cf" name="OP_SpawnAppearance" updated="06/19/24"> + <opcode id="033d" name="OP_SpawnAppearance" updated="07/17/24"> <comment>SpawnAppearanceCode</comment> <payload dir="both" typename="spawnAppearanceStruct" sizechecktype="match"/> </opcode> @@ -86,15 +86,15 @@ <comment>NpcHpUpdateCode Update HP % of a PC or NPC</comment> <payload dir="both" typename="hpNpcUpdateStruct" sizechecktype="match"/> </opcode> - <opcode id="082d" name="OP_GuildMemberUpdate" updated="06/19/24"> + <opcode id="2bfb" name="OP_GuildMemberUpdate" updated="07/17/24"> <comment>Info regarding guild members</comment> <payload dir="server" typename="GuildMemberUpdate" sizechecktype="match"/> </opcode> - <opcode id="2870" name="OP_ClickObject" updated="06/19/24"> + <opcode id="4454" name="OP_ClickObject" updated="07/17/24"> <comment>Items dropped on the ground</comment> <payload dir="both" typename="remDropStruct" sizechecktype="match"/> </opcode> - <opcode id="24fc" name="OP_Action" updated="06/19/24"> + <opcode id="681d" name="OP_Action" updated="07/17/24"> <comment>Spells cast etc</comment> <payload dir="both" typename="actionStruct" sizechecktype="match"/> <payload dir="both" typename="actionAltStruct" sizechecktype="match"/> @@ -103,11 +103,11 @@ <comment>Combat actions i.e. bash, kick etc</comment> <payload dir="both" typename="action2Struct" sizechecktype="match"/> </opcode> - <opcode id="0fd2" name="OP_Consider" updated="06/19/24"> + <opcode id="4126" name="OP_Consider" updated="07/17/24"> <comment>ConsiderCode</comment> <payload dir="both" typename="considerStruct" sizechecktype="match"/> </opcode> - <opcode id="133c" name="OP_TargetMouse" updated="06/19/24"> + <opcode id="0987" name="OP_TargetMouse" updated="07/17/24"> <comment>Targeting a person - old ClientTargetCode</comment> <payload dir="both" typename="clientTargetStruct" sizechecktype="match"/> </opcode> @@ -123,7 +123,7 @@ <comment>Server putting players into shroud form</comment> <payload dir="server" typename="spawnShroudSelf" sizechecktype="none"/> </opcode> - <opcode id="146c" name="OP_ZoneChange" updated="06/19/24"> + <opcode id="24bc" name="OP_ZoneChange" updated="07/17/24"> <comment>old ZoneChangeCode</comment> <payload dir="both" typename="zoneChangeStruct" sizechecktype="match"/> </opcode> @@ -191,19 +191,19 @@ <comment>EmoteTextCode</comment> <payload dir="both" typename="emoteTextStruct" sizechecktype="none"/> </opcode> - <opcode id="3256" name="OP_SimpleMessage" updated="06/19/24"> + <opcode id="1520" name="OP_SimpleMessage" updated="07/17/24"> <comment>SimpleMessageCode</comment> <payload dir="server" typename="simpleMessageStruct" sizechecktype="match"/> </opcode> - <opcode id="3fba" name="OP_FormattedMessage" updated="06/19/24"> + <opcode id="3fc6" name="OP_FormattedMessage" updated="07/17/24"> <comment>FormattedMessageCode i.e. pet dismissed etc</comment> <payload dir="server" typename="formattedMessageStruct" sizechecktype="none"/> </opcode> - <opcode id="2148" name="OP_CommonMessage" updated="06/19/24"> + <opcode id="60f9" name="OP_CommonMessage" updated="07/17/24"> <comment>ChannelMessageCode i.e. /tell /ooc /shout etc</comment> <payload dir="both" typename="channelMessageStruct" sizechecktype="none"/> </opcode> - <opcode id="686f" name="OP_SpecialMesg" updated="06/19/24"> + <opcode id="36f2" name="OP_SpecialMesg" updated="07/17/24"> <comment>Communicate textual info to client including hail responses etc</comment> <payload dir="server" typename="specialMessageStruct" sizechecktype="none"/> </opcode> @@ -307,7 +307,7 @@ <comment>List of group members - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="705e" name="OP_GuildMemberList" updated="06/19/24"> + <opcode id="6d8b" name="OP_GuildMemberList" updated="07/17/24"> <comment>List of guild members - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> @@ -367,7 +367,7 @@ <comment>Fellowship information - 2576 bytes</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="ffff" name="OP_ExpandedGuildInfo" updated="05/15/24"> + <opcode id="725b" name="OP_ExpandedGuildInfo" updated="07/17/24"> <comment>Guild ranks and other misc guild data - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> @@ -535,7 +535,7 @@ <comment>Listing of all guilds. Can be triggered by /lfg search?</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="7b05" name="OP_GuildsInZoneList" updated="06/19/24"> + <opcode id="3f04" name="OP_GuildsInZoneList" updated="07/17/24"> <comment>Listing of guild names present in the current zone. Generally seen on zoning</comment> <payload dir="server" typename="guildsInZoneListStruct" sizechecktype="none"/> </opcode> @@ -595,7 +595,7 @@ <comment>Free to play nags and other data - Variable length</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> - <opcode id="238b" name="OP_Find" updated="06/19/24"> + <opcode id="54c9" name="OP_Find" updated="07/17/24"> <comment>Find window data - 112 bytes</comment> <payload dir="server" typename="uint8_t" sizechecktype="none"/> </opcode> Modified: showeq/trunk/configure.in =================================================================== --- showeq/trunk/configure.in 2024-07-17 14:27:28 UTC (rev 1497) +++ showeq/trunk/configure.in 2024-07-17 23:20:36 UTC (rev 1498) @@ -2,7 +2,7 @@ dnl $Id$ $Name$ AC_PREREQ(2.59) -AC_INIT(showeq, 6.3.15) +AC_INIT(showeq, 6.3.16) AC_CONFIG_SRCDIR(src/main.cpp) AC_CONFIG_MACRO_DIR([m4]) AC_CANONICAL_SYSTEM Modified: showeq/trunk/src/everquest.h =================================================================== --- showeq/trunk/src/everquest.h 2024-07-17 14:27:28 UTC (rev 1497) +++ showeq/trunk/src/everquest.h 2024-07-17 23:20:36 UTC (rev 1498) @@ -1119,28 +1119,30 @@ struct { + signed deltaX:13; // change in x + signed deltaY:13; // change in y + unsigned padding00:6; + + unsigned heading:12; // heading + signed x:19; // x coord (1st loc value) + unsigned padding01:1; + signed z:19; // z coord (3rd loc value) - unsigned pitch:12; // pitch (up/down heading) - unsigned padding00:1; + unsigned padding02:13; + signed y:19; // y coord (2nd loc value) signed deltaHeading:10; // change in heading - signed y:19; // y coord (2nd loc value) - unsigned padding01:3; + unsigned padding03:3; - signed x:19; // x coord (1st loc value) - unsigned heading:12; // heading - unsigned padding02:1; + signed deltaZ:13; // change in z + unsigned pitch:12; // pitch (up/down heading) + unsigned padding04:7; - signed deltaX:13; // change in x signed animation:10; // current animation - unsigned padding03:9; + unsigned padding05:22; - signed deltaY:13; // change in y - signed deltaZ:13; // change in z - unsigned padding04:6; - }; - int32_t posData[5]; + int32_t posData[6]; }; @@ -2391,7 +2393,7 @@ /* ** Player Position Update -** Length: 24 Octets +** Length: 28 Octets ** OpCode: PlayerPosCode */ struct playerSpawnPosStruct @@ -2399,31 +2401,33 @@ /*0000*/ uint16_t spawnId; /*0002*/ uint16_t spawnId2; /*0004*/ - signed z:19; // z coord (3rd loc value) - unsigned pitch:12; // pitch (up/down heading) - unsigned padding00:1; + signed deltaX:13; // change in x + signed deltaY:13; // change in y + unsigned padding00:6; /*0008*/ - signed deltaHeading:10; // change in heading - signed y:19; // y coord (2nd loc value) - unsigned padding01:3; + unsigned heading:12; // heading + signed x:19; // x coord (1st loc value) + unsigned padding01:1; /*0012*/ - signed x:19; // x coord (1st loc value) - unsigned heading:12; // heading - unsigned padding02:1; + signed z:19; // z coord (3rd loc value) + unsigned padding02:13; /*0016*/ - signed deltaX:13; // change in x - signed animation:10; // current animation - unsigned padding03:9; + signed y:19; // y coord (2nd loc value) + signed deltaHeading:10; // change in heading + unsigned padding03:3; /*0020*/ - signed deltaY:13; // change in y signed deltaZ:13; // change in z - unsigned padding04:6; + unsigned pitch:12; // pitch (up/down heading) + unsigned padding04:7; /*0024*/ + signed animation:10; // current animation + unsigned padding05:22; +/*0028*/ }; /* ** Self Position Update -** Length: 38 Octets +** Length: 42 Octets ** OpCode: PlayerPosCode */ struct playerSelfPosStruct @@ -2432,26 +2436,28 @@ /*0002*/ uint16_t spawnId; // Player's spawn id /*0004*/ uint16_t unknown0004; // ***Placeholder /*0006*/ - signed animation:10; // current animation - unsigned pitch:12; // pitch (up/down heading) - unsigned padding00:10; + float x; // x coord (1st loc value) /*0010*/ - float deltaY; // change in y + signed deltaHeading:10; // change in heading + unsigned padding01:22; /*0014*/ - float deltaX; // change in x + float z; // z coord (3rd loc value) /*0018*/ float deltaZ; // change in z /*0022*/ - float z; // z coord (3rd loc value) + signed animation:10; // current animation + unsigned padding04:22; /*0026*/ - float x; // x coord (1st loc value) + float deltaX; // change in x /*0030*/ - float y; // y coord (2nd loc value) + float deltaY; // change in y /*0034*/ - signed deltaHeading:10; // change in heading unsigned heading:12; // heading - unsigned padding07:10; + unsigned pitch:12; // pitch (up/down heading) + unsigned padding07:8; /*0038*/ + float y; // y coord (2nd loc value) +/*0042*/ }; /* This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-07-17 14:27:34
|
Revision: 1497 http://sourceforge.net/p/seq/svn/1497 Author: cn187 Date: 2024-07-17 14:27:28 +0000 (Wed, 17 Jul 2024) Log Message: ----------- Add Filter List/Edit Window Modified Paths: -------------- showeq/branches/cn187_devel/src/Makefile.am showeq/branches/cn187_devel/src/editor.cpp showeq/branches/cn187_devel/src/filter.cpp showeq/branches/cn187_devel/src/filter.h showeq/branches/cn187_devel/src/filtermgr.cpp showeq/branches/cn187_devel/src/filtermgr.h showeq/branches/cn187_devel/src/interface.cpp showeq/branches/cn187_devel/src/interface.h showeq/branches/cn187_devel/src/spawnlistcommon.cpp Added Paths: ----------- showeq/branches/cn187_devel/src/filterlistwindow.cpp showeq/branches/cn187_devel/src/filterlistwindow.h showeq/branches/cn187_devel/src/toolbaricons.cpp showeq/branches/cn187_devel/src/toolbaricons.h Modified: showeq/branches/cn187_devel/src/Makefile.am =================================================================== --- showeq/branches/cn187_devel/src/Makefile.am 2024-07-15 01:00:22 UTC (rev 1496) +++ showeq/branches/cn187_devel/src/Makefile.am 2024-07-17 14:27:28 UTC (rev 1497) @@ -5,7 +5,7 @@ bin_PROGRAMS = showeq showeq_SOURCES = main.cpp spawn.cpp spawnshell.cpp spawnlist.cpp spellshell.cpp \ - spelllist.cpp vpacket.cpp editor.cpp filter.cpp packetfragment.cpp packetstream.cpp \ + spelllist.cpp vpacket.cpp editor.cpp filterlistwindow.cpp filter.cpp packetfragment.cpp packetstream.cpp \ packetinfo.cpp packet.cpp packetcapture.cpp packetformat.cpp interface.cpp compass.cpp \ map.cpp util.cpp experiencelog.cpp combatlog.cpp player.cpp skilllist.cpp \ statlist.cpp filtermgr.cpp mapcore.cpp category.cpp compassframe.cpp group.cpp \ @@ -15,10 +15,10 @@ datalocationmgr.cpp eqstr.cpp messages.cpp message.cpp messagefilter.cpp messagewindow.cpp \ messageshell.cpp terminal.cpp filteredspawnlog.cpp messagefilterdialog.cpp \ diagnosticmessages.cpp mapicon.cpp filternotifications.cpp netstream.cpp guildshell.cpp \ - guildlist.cpp bazaarlog.cpp mapicondialog.cpp packetcaptureprovider.cpp + guildlist.cpp bazaarlog.cpp mapicondialog.cpp packetcaptureprovider.cpp toolbaricons.cpp showeq_moc_SRCS = bazaarlog.moc category.moc combatlog.moc compass.moc \ - compassframe.moc datetimemgr.moc editor.moc experiencelog.moc \ + compassframe.moc datetimemgr.moc editor.moc filterlistwindow.moc experiencelog.moc \ filteredspawnlog.moc filtermgr.moc filternotifications.moc group.moc \ guild.moc guildlist.moc guildshell.moc interface.moc logger.moc \ map.moc mapicon.moc mapicondialog.moc messagefilter.moc \ @@ -38,6 +38,7 @@ $(srcdir)/compassframe.cpp: compassframe.moc $(srcdir)/datetimemgr.cpp: datetimemgr.moc $(srcdir)/editor.cpp: editor.moc +$(srcdir)/filterlistwindow.cpp: filterlistwindow.moc $(srcdir)/experiencelog.cpp: experiencelog.moc $(srcdir)/filteredspawnlog.cpp: filteredspawnlog.moc $(srcdir)/filtermgr.cpp: filtermgr.moc @@ -113,7 +114,7 @@ EXTRA_DIST = h2info.pl -noinst_HEADERS = classes.h compass.h everquest.h interface.h main.h map.h filter.h vpacket.h editor.h packet.h packetcapture.h packetcommon.h packetformat.h packetstream.h packetfragment.h packetinfo.h races.h skills.h spells.h util.h experiencelog.h combatlog.h spawn.h spawnshell.h spawnlist.h spellshell.h spelllist.h languages.h weapons.h weapons1.h weapons27.h weapons28.h weapons29.h weapons2a.h weapons2b.h weapons2c.h weapons2d.h weapons2e.h weapons2f.h weapons30.h weapons4e.h decode.h cgiconv.h skilllist.h statlist.h deity.h player.h crctab.h filtermgr.h point.h pointarray.h mapcore.h category.h compassframe.h group.h guild.h fixpt.h netdiag.h zones.h logger.h xmlconv.h xmlpreferences.h seqwindow.h seqlistview.h zonemgr.h spawnmonitor.h spawnpointlist.h typenames.h spawnlistcommon.h spawnlist2.h datetimemgr.h spawnlog.h packetlog.h datalocationmgr.h eqstr.h messages.h messagefilter.h messagewindow.h messageshell.h terminal.h filteredspawnlog.h messagefilterdialog.h diagnosticmessages.h mapicon.h mapicondialog.h mapicondialog.ui filternotifications.h netstream.h guildshell.h guildlist.h bazaarlog.h message.h s_everquest.h staticspells.h packetcaptureprovider.h mapcolors.h +noinst_HEADERS = classes.h compass.h everquest.h interface.h main.h map.h filter.h vpacket.h editor.h filterlistwindow.h packet.h packetcapture.h packetcommon.h packetformat.h packetstream.h packetfragment.h packetinfo.h races.h skills.h spells.h util.h experiencelog.h combatlog.h spawn.h spawnshell.h spawnlist.h spellshell.h spelllist.h languages.h weapons.h weapons1.h weapons27.h weapons28.h weapons29.h weapons2a.h weapons2b.h weapons2c.h weapons2d.h weapons2e.h weapons2f.h weapons30.h weapons4e.h decode.h cgiconv.h skilllist.h statlist.h deity.h player.h crctab.h filtermgr.h point.h pointarray.h mapcore.h category.h compassframe.h group.h guild.h fixpt.h netdiag.h zones.h logger.h xmlconv.h xmlpreferences.h seqwindow.h seqlistview.h zonemgr.h spawnmonitor.h spawnpointlist.h typenames.h spawnlistcommon.h spawnlist2.h datetimemgr.h spawnlog.h packetlog.h datalocationmgr.h eqstr.h messages.h messagefilter.h messagewindow.h messageshell.h terminal.h filteredspawnlog.h messagefilterdialog.h diagnosticmessages.h mapicon.h mapicondialog.h mapicondialog.ui filternotifications.h netstream.h guildshell.h guildlist.h bazaarlog.h message.h s_everquest.h staticspells.h packetcaptureprovider.h mapcolors.h toolbaricons.h CLEANFILES = $(nodist_showeq_SOURCES) Modified: showeq/branches/cn187_devel/src/editor.cpp =================================================================== --- showeq/branches/cn187_devel/src/editor.cpp 2024-07-15 01:00:22 UTC (rev 1496) +++ showeq/branches/cn187_devel/src/editor.cpp 2024-07-17 14:27:28 UTC (rev 1497) @@ -43,55 +43,10 @@ #include <QCloseEvent> #include "util.h" +#include "toolbaricons.h" #include "editor.h" -/* XPM */ -static const char *filesave[] = { -" 14 14 4 1", -". c #040404", -"# c #808304", -"a c #bfc2bf", -"b c None", -"..............", -".#.aaaaaaaa.a.", -".#.aaaaaaaa...", -".#.aaaaaaaa.#.", -".#.aaaaaaaa.#.", -".#.aaaaaaaa.#.", -".#.aaaaaaaa.#.", -".##........##.", -".############.", -".##.........#.", -".##......aa.#.", -".##......aa.#.", -".##......aa.#.", -"b............." -}; - -/* XPM */ -static const char *fileopen[] = { -" 16 13 5 1", -". c #040404", -"# c #808304", -"a c None", -"b c #f3f704", -"c c #f3f7f3", -"aaaaaaaaa...aaaa", -"aaaaaaaa.aaa.a.a", -"aaaaaaaaaaaaa..a", -"a...aaaaaaaa...a", -".bcb.......aaaaa", -".cbcbcbcbc.aaaaa", -".bcbcbcbcb.aaaaa", -".cbcb...........", -".bcb.#########.a", -".cb.#########.aa", -".b.#########.aaa", -"..#########.aaaa", -"...........aaaaa" -}; - EditorWindow::EditorWindow(const char *fileName) : QMainWindow( 0 ) { @@ -98,8 +53,8 @@ setObjectName("ShowEQ - Editor"); setAttribute(Qt::WA_DeleteOnClose); QPixmap openIcon, saveIcon; - openIcon = QPixmap( fileopen ); - saveIcon = QPixmap( filesave ); + openIcon = ToolbarIcons::FileOpen(); + saveIcon = ToolbarIcons::FileSave(); fileTools = new QToolBar(this); fileTools->setWindowTitle( tr( "File Operations" ) ); Modified: showeq/branches/cn187_devel/src/filter.cpp =================================================================== --- showeq/branches/cn187_devel/src/filter.cpp 2024-07-15 01:00:22 UTC (rev 1496) +++ showeq/branches/cn187_devel/src/filter.cpp 2024-07-17 14:27:28 UTC (rev 1497) @@ -45,6 +45,19 @@ //#define DEBUG_FILTER +#define X(a, b) #b, +const QString FilterStringFieldName[FSF_Max] = { + FILTERSTRINGFIELD_TABLE +}; +#undef X + +#define X(a, b) #b, +const QString FilterStringInfoFieldName[FSIF_Max] = { + FILTERSTRINGINFOFIELD_TABLE +}; +#undef X + + //---------------------------------------------------------------------- // LoadXmlContentHandler declaration class LoadXmlContentHandler : public QObject @@ -182,6 +195,27 @@ (const char*)regexString, minLevel, maxLevel); #endif + // in theory, we have minLevel and maxLevel, so there should be no level range + // appended to the filter string. But there are situation where that can + // happen, so check for it and remove it if found. Otherwise, if + // we leave it attached, the filter will never match anything since the + // level range will be treated as part of the match string. + + QString filterString; + QString workString = regexString; + + // find the semi-colon that seperates the regex from the level info + int breakPoint = workString.indexOf(';'); + + // if no semi-colon, then it's all a regex + if (breakPoint == -1) + filterString = regexString; + else + // regex is the left most part of the string up to breakPoint characters + filterString = workString.left(breakPoint); + + filterString = regexString; + #if (QT_VERSION >= QT_VERSION_CHECK(5,5,0)) if (!caseSensitive) m_regexp.setPatternOptions(QRegularExpression::CaseInsensitiveOption); @@ -193,9 +227,9 @@ // For the pattern, save off the original. This is what will be saved // during save operations. But the actual regexp we filter with will // mark the # in spawn names as optional to aid in filter writing. - m_regexpOriginalPattern = QString(regexString.toLatin1().data()); + m_regexpOriginalPattern = filterString; - QString fixedFilterPattern = regexString; + QString fixedFilterPattern = filterString; fixedFilterPattern.replace("Name:", "Name:#?", Qt::CaseInsensitive); m_regexp.setPattern(fixedFilterPattern); @@ -474,6 +508,49 @@ } } +QString Filter::getFilterString(int index) const +{ + if (index >= m_filterItems.size()) + return QString(); + + FilterItem* item = m_filterItems[index]; + QString pattern = item->filterPattern(); + + return pattern; +} + +QString Filter::getOrigFilterString(int index) const +{ + if (index >= m_filterItems.size()) + return QString(); + + FilterItem* item = m_filterItems[index]; + QString pattern = item->origFilterPattern(); + + return pattern; +} + +int Filter::getMinLevel(int index) const +{ + if (index >= m_filterItems.size()) + return -1; + + FilterItem* item = m_filterItems[index]; + + return item->minLevel(); +} + +int Filter::getMaxLevel(int index) const +{ + if (index >= m_filterItems.size()) + return -1; + + FilterItem* item = m_filterItems[index]; + + return item->maxLevel(); +}; + + //---------------------------------------------------------------------- // Filters Filters::Filters(const FilterTypes& types) @@ -755,6 +832,59 @@ filter->remFilter(filterPattern); } +int Filters::numFilters(uint8_t type) const +{ + uint32_t mask = (1 << type); + FilterMap::const_iterator it = m_filters.find(mask); + + if (it == m_filters.end()) return 0; + + return it->second->numFilters(); +} + +QString Filters::getFilterString(uint8_t type, int index) const +{ + uint32_t mask = (1 << type); + FilterMap::const_iterator it = m_filters.find(mask); + + if (it == m_filters.end()) return QString(); + + return it->second->getFilterString(index); +} + +QString Filters::getOrigFilterString(uint8_t type, int index) const +{ + uint32_t mask = (1 << type); + FilterMap::const_iterator it = m_filters.find(mask); + + if (it == m_filters.end()) return QString(); + + return it->second->getOrigFilterString(index); +} + +int Filters::getMinLevel(uint8_t type, int index) const +{ + uint32_t mask = (1 << type); + FilterMap::const_iterator it = m_filters.find(mask); + + if (it == m_filters.end()) return -1; + + return it->second->getMinLevel(index); +} + +int Filters::getMaxLevel(uint8_t type, int index) const +{ + uint32_t mask = (1 << type); + FilterMap::const_iterator it = m_filters.find(mask); + + if (it == m_filters.end()) return -1; + + return it->second->getMaxLevel(index); +} + + + + /////////////////////////////////// // FilterTypes FilterTypes::FilterTypes() Modified: showeq/branches/cn187_devel/src/filter.h =================================================================== --- showeq/branches/cn187_devel/src/filter.h 2024-07-15 01:00:22 UTC (rev 1496) +++ showeq/branches/cn187_devel/src/filter.h 2024-07-17 14:27:28 UTC (rev 1497) @@ -43,7 +43,73 @@ #include <map> + //-------------------------------------------------- +// defines and enums + +// HumanReadableName, FilterStringFieldName +#define FILTERSTRINGFIELD_TABLE \ + X(Name, Name) \ + X(Level, Level) \ + X(Race, Race) \ + X(Class, Class) \ + X(NPC, NPC) \ + X(X, X) \ + X(Y, Y) \ + X(Z, Z) \ + X(Light, Light) \ + X(Deity, Deity) \ + X(RaceTeam, RTeam) \ + X(DeityTeam, DTeam) \ + X(Type, Type) \ + X(LastName, LastName) \ + X(Guild, Guild) \ + X(SpawnTime, Spawn) \ + X(Info, Info) \ + X(GM, GM) + +// HumanReadableName, FilterStringFieldName +#define FILTERSTRINGINFOFIELD_TABLE \ + X(Light, Light) \ + X(Head, H) \ + X(Chest, C) \ + X(Arms, A) \ + X(Waist, W) \ + X(Gloves, G) \ + X(Legs, L) \ + X(Feet, F) \ + X(Primary, 1) \ + X(Secondary, 2) + + +#define X(a, b) FSF_##a, +enum FilterStringField +{ + FILTERSTRINGFIELD_TABLE + FSF_Max +}; +#undef X + +#define X(a, b) FSIF_##a, +enum FilterStringInfoField +{ + FILTERSTRINGINFOFIELD_TABLE + FSIF_Max +}; +#undef X + +extern const QString FilterStringFieldName[FSF_Max]; +extern const QString FilterStringInfoFieldName[FSIF_Max]; + + +// 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" +#define FSF_MAXLEVEL_NAME "MaxLevel" +#define FSF_MAXLEVEL_LABEL "Max Level" + + +//-------------------------------------------------- // forward declarations class FilterItem; class Filter; @@ -72,6 +138,7 @@ QString name() const { return m_regexp.pattern(); } QString filterPattern() const { return m_regexp.pattern(); } + QString origFilterPattern() const { return m_regexpOriginalPattern; } uint8_t minLevel() const { return m_minLevel; } uint8_t maxLevel() const { return m_maxLevel; } bool valid() { return m_regexp.isValid(); } @@ -107,6 +174,12 @@ void listFilters(void); void setCaseSensitive(bool caseSensitive); + int numFilters() const { return m_filterItems.size(); } + QString getFilterString(int index) const; + QString getOrigFilterString(int index) const; + int getMinLevel(int index) const; + int getMaxLevel(int index) const; + private: FilterItem* findFilter(const QString& filterPattern); @@ -136,7 +209,11 @@ uint8_t minLevel = 0, uint8_t maxLevel = 0); void remFilter(uint8_t type, const QString& filterString); - protected: + int numFilters(uint8_t type) const; + QString getFilterString(uint8_t type, int index) const; + QString getOrigFilterString(uint8_t type, int index)const; + int getMinLevel(uint8_t type, int index) const; + int getMaxLevel(uint8_t type, int index) const; protected: QString m_file; Copied: showeq/branches/cn187_devel/src/filterlistwindow.cpp (from rev 1496, showeq/branches/cn187_devel/src/filtermgr.cpp) =================================================================== --- showeq/branches/cn187_devel/src/filterlistwindow.cpp (rev 0) +++ showeq/branches/cn187_devel/src/filterlistwindow.cpp 2024-07-17 14:27:28 UTC (rev 1497) @@ -0,0 +1,1297 @@ +/* + * filterlistwindow.cpp + * Copyright 2024 by the respective ShowEQ Developers + * + * This file is part of ShowEQ. + * http://www.sourceforge.net/projects/seq + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#include <QWidget> +#include <QHBoxLayout> +#include <QVBoxLayout> +#include <QTabWidget> +#include <QTreeView> +#include <QDebug> +#include <QHeaderView> +#include <QLineEdit> +#include <QLabel> +#include <QGridLayout> +#include <QVBoxLayout> +#include <QHBoxLayout> +#include <QPushButton> +#include <QCheckBox> +#include <QToolBar> +#include <QAction> +#include <QMenuBar> +#include <QMenu> +#include <QFileDialog> + +#include "diagnosticmessages.h" +#include "filtermgr.h" +#include "filterlistwindow.h" +#include "toolbaricons.h" + + + +#define FILTERLISTCOLUMN_TABLE \ + X(FilterString) \ + X(MinLevel) \ + X(MaxLevel) + +#define X(a) FLC_##a, +enum FilterListColumn { + FILTERLISTCOLUMN_TABLE + FLC_Max +}; +#undef X + +#define X(a) #a, +const QString FilterListColumnName[] = { + FILTERLISTCOLUMN_TABLE +}; +#undef X + +enum DataItemUserRole +{ + DIUR_FilterStringWithLevelRange=Qt::UserRole + 1, +}; + + +FilterListWindow::FilterListWindow(QString filename, QWidget* parent, Qt::WindowFlags flags): + QMainWindow(parent, flags), + m_filename(filename), + m_tabWidget(nullptr), + m_statusBar(nullptr), + m_filters(nullptr), + m_types(nullptr) +{ + //setModal(true); + setAttribute(Qt::WA_DeleteOnClose); + setWindowTitle(filename); + + m_types = new FilterTypes; + uint8_t type; + uint32_t mask; + #define X(a, b, c) m_types->registerType(#a, type, mask); + FILTER_TYPE_TABLE + #undef X + + m_filters = new Filters(*m_types); + + QMenuBar* menubar = new QMenuBar(this); + setMenuBar(menubar); + + QMenu* fileMenu = new QMenu("&File", this); + +#if (QT_VERSION >= QT_VERSION_CHECK(6,3,0)) + fileMenu->addAction(ToolbarIcons::FileOpen(), "&Open", Qt::CTRL|Qt::Key_O, this, SLOT(load())); + fileMenu->addAction(ToolbarIcons::FileSave(), "&Save", Qt::CTRL|Qt::Key_S, this, SLOT(save())); + fileMenu->addSeparator(); + fileMenu->addAction("&Close", Qt::CTRL|Qt::Key_W, this, SLOT(close())); +#else + fileMenu->addAction(ToolbarIcons::FileOpen(), "&Open", this, SLOT(load()), Qt::CTRL|Qt::Key_O); + fileMenu->addAction(ToolbarIcons::FileSave(), "&Save", this, SLOT(save()), Qt::CTRL|Qt::Key_S); + fileMenu->addSeparator(); + fileMenu->addAction("&Close", this, SLOT(close()), Qt::CTRL|Qt::Key_W); +#endif + + menubar->addMenu(fileMenu); + + QToolBar* toolbar = new QToolBar(this); + toolbar->addAction(ToolbarIcons::FileOpen(), "Open File", this, SLOT(load())); + toolbar->addAction(ToolbarIcons::FileSave(), "Save File", this, SLOT(save())); + + addToolBar(toolbar); + + m_tabWidget = new QTabWidget(this); + + QStringList tabs = { + #define X(a, b, c) #a, + FILTER_TYPE_TABLE + }; + #undef X + + for (uint8_t i=0; i < SIZEOF_FILTERS; ++i) + { + QWidget* t = createTab(m_types->name(i)); + m_tabWidget->addTab(t, "&" + m_types->name(i)); + } + + setCentralWidget(m_tabWidget); + + m_statusBar = new QStatusBar(this); + setStatusBar(m_statusBar); + + loadFile(); + + show(); + + m_statusBar->showMessage("Ready", 2000); + +} + +FilterListWindow::~FilterListWindow() +{ + if (m_filters) + delete m_filters; + + if (m_types) + delete m_types; + + qDeleteAll(m_models); + m_models.clear(); + + qDeleteAll(m_views); + m_views.clear(); +} + +void FilterListWindow::setTabLabel(uint8_t type, int count) +{ +#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0)) + if (!m_tabWidget || !m_tabWidget->tabBar()) + return; + + m_tabWidget->tabBar()->setTabText(type, QString("&") + m_types->name(type) +#else + if (!m_tabWidget) + return; + + m_tabWidget->setTabText(type, QString("&") + m_types->name(type) +#endif + + " (" + QString::number(count) + ")"); +} + +QWidget* FilterListWindow::createTab(QString name) +{ + uint8_t type = m_types->type(name); + + QWidget* w = new QWidget(this); + w->setObjectName(name); + QVBoxLayout* l = new QVBoxLayout(w); + + QToolBar* tabButtons = new QToolBar(w); + + QAction* tmpAction = new QAction("+", nullptr); + tmpAction->setToolTip("Add New Item"); + tmpAction->setProperty("type", m_types->type(name)); + tmpAction->setProperty("action", "add"); + tabButtons->addAction(tmpAction); + + tmpAction = new QAction("-", nullptr); + tmpAction->setToolTip("Delete Selected Item"); + tmpAction->setProperty("type", m_types->type(name)); + tmpAction->setProperty("action", "delete"); + tabButtons->addAction(tmpAction); + + l->addWidget(tabButtons); + connect(tabButtons, SIGNAL(actionTriggered(QAction*)), this, SLOT(tabButtonClicked(QAction*))); + + + QTreeView* t = new QTreeView(); + m_views[type] = t; + t->setRootIsDecorated(false); + t->setSelectionMode(QAbstractItemView::SingleSelection); + t->setSelectionBehavior(QAbstractItemView::SelectRows); + t->expandAll(); + t->setItemsExpandable(false); + + connect(t, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(editItem(QModelIndex))); + l->addWidget(t); + + return w; +} + +void FilterListWindow::tabButtonClicked(QAction* action) +{ + uint8_t type = action->property("type").toInt(); + QString a = action->property("action").toString(); + if (a == "add") + createItem(type); + else if (a == "delete") + deleteItem(type); +} + +void FilterListWindow::createItem(uint8_t type) +{ + bool ok = false; + QString filterString; + filterString = FilterDialog::getFilter(this, "Add " + m_types->name(type) + " Filter", filterString, &ok); + if (ok) + { + m_models[type]->addFilter(filterString); + setTabLabel(type, m_models[type]->rowCount()); + } +} + +void FilterListWindow::deleteItem(uint8_t type) +{ + QModelIndexList selectedRows = m_views[type]->selectionModel()->selectedRows(); + if (selectedRows.size()) + { + QModelIndex selected = selectedRows[0]; //only one selection allowed, so we can take the first + m_models[type]->removeFilter(selected); + setTabLabel(type, m_models[type]->rowCount()); + } +} + +void FilterListWindow::editItem(QModelIndex index) +{ + //TODO rework the whole filterdialog/filtermodel/filters call chain + //to to better handle min/max level rather than this kludge + // + const QAbstractItemModel* model = index.model(); + QString filterString = model->data(index, DIUR_FilterStringWithLevelRange).toString(); + uint8_t type = index.internalId(); + bool ok = false; + filterString = FilterDialog::getFilter(this, "Edit " + m_types->name(type) + " Filter", filterString, &ok); + if (ok) + { + m_models[type]->removeFilter(index); + m_models[type]->addFilter(filterString); + } +} + +void FilterListWindow::load() +{ + QString fn = QFileDialog::getOpenFileName(this, "Open File", + m_filename, "XML Files (*.xml)"); + if (fn.isEmpty()) + { + m_statusBar->showMessage("File Open Cancelled", 2000); + return; + } + + m_filename = fn; + setWindowTitle(m_filename); + loadFile(); +} + +void FilterListWindow::loadFile() +{ + + for (uint8_t i=0; i < SIZEOF_FILTERS; ++i) + m_views[i]->setModel(nullptr); + + qDeleteAll(m_models); + m_models.clear(); + + m_filters->load(m_filename); + + for (int i=0; i < SIZEOF_FILTERS; ++i) + { + m_models[i] = new FilterModel(m_filters, i); + m_views[i]->setModel(m_models[i]); + setTabLabel(i, m_models[i]->rowCount()); + +#if (QT_VERSION >= QT_VERSION_CHECK(5,0,0)) + m_views[i]->header()->setSectionResizeMode(QHeaderView::ResizeToContents); +#else + m_views[i]->header()->setResizeMode(QHeaderView::ResizeToContents); +#endif + } + + m_statusBar->showMessage(QString("Loaded %1").arg(m_filename), 2000); +} + +void FilterListWindow::save() +{ + if (m_filename.isEmpty()) + saveAs(); + else + if (!m_filters->save()) + m_statusBar->showMessage(QString("Could not write to %1").arg(m_filename), + 2000); + else + m_statusBar->showMessage(QString("Saved %1").arg(m_filename), 2000); +} + +void FilterListWindow::saveAs() +{ + QString fn = QFileDialog::getSaveFileName(this, "Save File", + m_filename, "XML Files (*.xml)"); + if (fn.isEmpty()) + { + m_statusBar->showMessage("Save File Cancelled", 2000); + return; + } + + m_filename = fn; + setWindowTitle(m_filename); + save(); +} + + +FilterModel::FilterModel(Filters* filters, uint8_t type, QObject* parent) : + QAbstractItemModel(parent), + m_filters(filters), + m_type(type) +{ } + +FilterModel::~FilterModel() +{} + +QModelIndex FilterModel::index(int row, int column, const QModelIndex &parent) const +{ + return createIndex(row, column, m_type); +} + +QModelIndex FilterModel::parent(const QModelIndex &index) const +{ + return QModelIndex(); +} + +int FilterModel::rowCount(const QModelIndex &parent) const +{ + return m_filters->numFilters(m_type); +} + +int FilterModel::columnCount(const QModelIndex &parent) const +{ + return FLC_Max; +} + +QVariant FilterModel::headerData(int section, Qt::Orientation, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + return FilterListColumnName[section]; + + default: + return QVariant(); + } +} + +QVariant FilterModel::data(const QModelIndex &index, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + switch(index.column()) + { + case FLC_FilterString: + return m_filters->getOrigFilterString(m_type, index.row()); + case FLC_MinLevel: + return m_filters->getMinLevel(m_type, index.row()); + case FLC_MaxLevel: + return m_filters->getMaxLevel(m_type, index.row()); + default: + return QVariant(); + } + case DIUR_FilterStringWithLevelRange: + { + int minLevel = m_filters->getMinLevel(m_type, index.row()); + int maxLevel = m_filters->getMaxLevel(m_type, index.row()); + QString filterString = m_filters->getOrigFilterString(m_type, index.row()); + if (minLevel > 0 || maxLevel > 0) + { + filterString += ';'; + if (minLevel > 0) + { + filterString += QString::number(minLevel); + if (maxLevel > 0) + filterString += "-" + QString::number(maxLevel); + else + filterString += "-" + QString::number(SHRT_MAX); + } + else + { + filterString += "0-" + QString::number(maxLevel); + } + } + return filterString; + } + + default: + return QVariant(); + } +} + +void FilterModel::addFilter(QString filterPattern) +{ + //TODO rework the whole filterdialog/filtermodel/filters call chain + //to to better handle min/max level rather than this kludge + int minLevel = 0; + int maxLevel = 0; + + QString workString = filterPattern; + int breakpoint = workString.indexOf(';'); + if (breakpoint == -1) + { + beginInsertRows(QModelIndex(), rowCount(), 1); + m_filters->addFilter(m_type, filterPattern); + endInsertRows(); + } + else + { + //this is basically a copy of the level string parsing code in FilterItem() + filterPattern = workString.left(breakpoint); + QString levelString = workString.mid(breakpoint+1); + breakpoint = levelString.indexOf('-'); + bool ok; + int level; + if (breakpoint == -1) + { + level = levelString.toInt(&ok); + if (ok) + minLevel = level; + } + else + { + level = levelString.left(breakpoint).toInt(&ok); + if (ok) + minLevel = level; + + levelString = levelString.mid(breakpoint+1); + if (levelString.isEmpty()) + { + maxLevel = SHRT_MAX; + } + else + { + level = levelString.toInt(&ok); + if (ok) + maxLevel = level; + } + } + if (maxLevel < minLevel) + maxLevel = minLevel; + + + beginInsertRows(QModelIndex(), rowCount(), 1); + m_filters->addFilter(m_type, filterPattern, minLevel, maxLevel); + endInsertRows(); + + + } + + emit dataChanged(index(rowCount()-1, 0), index(rowCount(), 1)); +} + +void FilterModel::removeFilter(QModelIndex selection) +{ + beginRemoveRows(QModelIndex(), selection.row(), 1); + m_filters->remFilter(m_type, m_filters->getFilterString(m_type, selection.row())); + endRemoveRows(); +} + + +FilterFormField::FilterFormField(QString name, QString labeltext, QWidget* parent) : + QWidget(parent), + m_name(name), + m_labeltext(labeltext), + m_check(nullptr), + m_label(nullptr), + m_edit(nullptr) +{ + if (m_labeltext.isNull()) + m_labeltext = m_name; + + m_check = new QCheckBox(this); + m_check->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed); + + m_label = new QLabel(m_labeltext, this); + QSizePolicy tmpPolicy = m_label->sizePolicy(); + tmpPolicy.setVerticalPolicy(QSizePolicy::Fixed); + m_label->setSizePolicy(tmpPolicy); + + m_edit = new QLineEdit(this); + tmpPolicy = m_edit->sizePolicy(); + tmpPolicy.setVerticalPolicy(QSizePolicy::Fixed); + m_edit->setSizePolicy(tmpPolicy); + + QHBoxLayout* layout = new QHBoxLayout(this); + layout->addWidget(m_check); + layout->addWidget(m_label); + layout->addWidget(m_edit); + + connect(m_check, SIGNAL(toggled(bool)), m_edit, SLOT(setEnabled(bool))); + m_edit->installEventFilter(this); +} + +bool FilterFormField::eventFilter(QObject* object, QEvent* event) +{ + if (object == m_edit && event->type() == QEvent::MouseButtonPress) + { + m_check->setChecked(true); + //stateChanged(Qt::Checked); + m_edit->setFocus(Qt::MouseFocusReason); + return true; + } + return false; +} + +void FilterFormField::stateChanged(int state) +{ + bool old_check_state = m_check->blockSignals(true); + bool old_edit_state = m_edit->blockSignals(true); + switch (state) + { + case Qt::Unchecked: + m_check->setChecked(false); + m_edit->setEnabled(false); + break; + case Qt::PartiallyChecked: + break; + case Qt::Checked: + m_check->setChecked(true); + m_edit->setEnabled(true); + break; + } + m_check->blockSignals(old_check_state); + m_edit->blockSignals(old_edit_state); +} + +void ToggleAllCheckBox::nextCheckState() +{ + switch(checkState()) + { + case Qt::Unchecked: + setCheckState(Qt::Checked); + break; + case Qt::PartiallyChecked: + setCheckState(Qt::Unchecked); + break; + case Qt::Checked: + setCheckState(Qt::Unchecked); + break; + } + +} + +FilterDialog::FilterDialog(QWidget* parent, Qt::WindowFlags flags) : + QDialog(parent, flags), + m_toggleAll(nullptr), + m_filterString(QString()), + m_fieldCount(0), + m_fieldsCheckedCount(0) +{ + //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 = FSIF_Head; field < FSIF_Max; ++field) + { + QString name = FilterStringInfoFieldName[field]; + m_spawnFilterMap[name] = ""; + } + m_spawnFilterMap[FSF_MINLEVEL_NAME] = ""; + m_spawnFilterMap[FSF_MAXLEVEL_NAME] = ""; + + createForm(); +} + +FilterDialog::~FilterDialog() +{ } + +void FilterDialog::createForm() +{ + + const int colspc_x = 20; + const int colspc_y = 1; + + QVBoxLayout* pageLayout = new QVBoxLayout(this); + QGridLayout* gridLayout = new QGridLayout(); + + // info/instructions + QLabel* tmpLabel = new QLabel("All fields except '" FSF_MINLEVEL_LABEL "' and '" FSF_MAXLEVEL_LABEL "' accept Regular Expression syntax.", this); + tmpLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + pageLayout->addWidget(tmpLabel); + tmpLabel = new QLabel("For an exact level match or matching multiple levels using a RegEx, use the 'Level' field.", this); + tmpLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + pageLayout->addWidget(tmpLabel); + tmpLabel = new QLabel("To limit to a simple level range (no RegEx), use the '" FSF_MINLEVEL_LABEL "' and '" FSF_MAXLEVEL_LABEL "' fields.", this); + tmpLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + pageLayout->addWidget(tmpLabel); + tmpLabel = new QLabel("Any fields left blank or not checked will not be matched against.", this); + tmpLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed); + pageLayout->addWidget(tmpLabel); + + pageLayout->addItem(new QSpacerItem(colspc_x, 25)); + + //using an extra widget so the spacing lines up + QWidget* toggleAllWidget = new QWidget(); + QHBoxLayout* toggleAllLayout = new QHBoxLayout(toggleAllWidget); + m_toggleAll = new ToggleAllCheckBox(); + m_toggleAll->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); + m_toggleAll->setTristate(true); + toggleAllLayout->addWidget(m_toggleAll); + toggleAllLayout->addWidget(new QLabel("Toggle All", this)); + connect(m_toggleAll, SIGNAL(stateChanged(int)), this, SLOT(toggleAllToggled(int))); + + pageLayout->addLayout(gridLayout); + gridLayout->addWidget(toggleAllWidget, 0, 0); + + #define X(a, b) #a, + const QString labels[] = { + FILTERSTRINGFIELD_TABLE + }; + #undef X + + 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); + m_fieldCount++; + + } + + #define X(a, b) #a, + const QString info_labels[] = { + FILTERSTRINGINFOFIELD_TABLE + }; + #undef X + + // Starting with head, since Light is already created above. + for (int field = FSIF_Head; field < FSIF_Max; ++field) + { + QString name = FilterStringInfoFieldName[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); + m_fieldCount += 2; + + 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", + //Info fields + "H", "C", "A", "W", "G", "L", "F", "1", "2" }; + + int row = 1; //toggle all is row 0 + int col = 0; + for (auto fieldname : formFieldOrder) + { + gridLayout->addWidget(m_filterFields[fieldname], row, col++); + + connect(m_toggleAll, SIGNAL(stateChanged(int)), m_filterFields[fieldname], SLOT(stateChanged(int))); + connect(m_filterFields[fieldname]->m_check, SIGNAL(toggled(bool)), this, SLOT(fieldToggled(bool))); + + if (fieldname == "Guild" || fieldname == "Deity" || + fieldname == FSF_MAXLEVEL_NAME || fieldname == "Z" || + fieldname == "GM" || fieldname == "Spawn" || + fieldname == "Light" || + fieldname == "A" || fieldname == "L") + { + row++; + col = 0; + } + } + + //buttons + QHBoxLayout* buttonLayout = new QHBoxLayout(); + pageLayout->addItem(new QSpacerItem(colspc_x, 25)); + pageLayout->addLayout(buttonLayout); + + QPushButton* resetButton = new QPushButton("Reset"); + resetButton->setDefault(false); + resetButton->setAutoDefault(false); + buttonLayout->addWidget(resetButton); + connect(resetButton, SIGNAL(clicked()), this, SLOT(resetForm())); + + buttonLayout->addItem(new QSpacerItem(colspc_x, colspc_y)); + + QPushButton* okButton = new QPushButton("Ok"); + okButton->setDefault(false); + okButton->setAutoDefault(false); + buttonLayout->addWidget(okButton); + connect(okButton, SIGNAL(clicked()), this, SLOT(acceptDialog())); + + QPushButton* cancelButton = new QPushButton("Cancel"); + cancelButton->setDefault(false); + cancelButton->setAutoDefault(false); + buttonLayout->addWidget(cancelButton); + connect(cancelButton, SIGNAL(clicked()), this, SLOT(reject())); +} + +void FilterDialog::setData(const QString filterString) +{ + m_spawnFilterString = filterString; + + FilterString2FilterFieldMap(filterString, &m_spawnFilterMap); + + resetForm(); +} + +void FilterDialog::resetForm() +{ + 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()) + { + m_filterFields[name]->stateChanged(Qt::Checked); + m_fieldsCheckedCount++; + } + else + { + m_filterFields[name]->stateChanged(Qt::Unchecked); + } + } + + //starting with Head, since Light was handled above + for (int field = FSIF_Head; field < FSIF_Max; ++field) + { + QString name = FilterStringInfoFieldName[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()) + { + m_filterFields[FSF_MINLEVEL_NAME]->stateChanged(Qt::Checked); + m_fieldsCheckedCount++; + } + else + { + m_filterFields[FSF_MINLEVEL_NAME]->stateChanged(Qt::Unchecked); + } + m_filterFields[FSF_MAXLEVEL_NAME]->m_edit->setText(m_spawnFilterMap[FSF_MAXLEVEL_NAME]); + if (m_filterFields[FSF_MAXLEVEL_NAME]->m_edit->text().length()) + { + m_filterFields[FSF_MAXLEVEL_NAME]->stateChanged(Qt::Checked); + m_fieldsCheckedCount++; + } + else + { + m_filterFields[FSF_MAXLEVEL_NAME]->stateChanged(Qt::Unchecked); + } + + bool old_state = m_toggleAll->blockSignals(true); + if (m_fieldsCheckedCount == 0) + m_toggleAll->setCheckState(Qt::Unchecked); + else if (m_fieldsCheckedCount == m_fieldCount) + m_toggleAll->setCheckState(Qt::Checked); + else + m_toggleAll->setCheckState(Qt::PartiallyChecked); + m_toggleAll->blockSignals(old_state); + +} + +void FilterDialog::acceptDialog() +{ + FilterFieldMap map; + + //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 = FSIF_Head; field < FSIF_Max; ++field) + { + QString name = FilterStringInfoFieldName[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(); + + if (m_filterFields[FSF_MAXLEVEL_NAME]->m_edit->isEnabled()) + map[FSF_MAXLEVEL_NAME] = m_filterFields[FSF_MAXLEVEL_NAME]->m_edit->text(); + + + m_filterString = FilterFieldMap2FilterString(&map); + + done(QDialog::Accepted); +} + +void FilterDialog::fieldToggled(bool checked) +{ + if (checked) + m_fieldsCheckedCount++; + else + m_fieldsCheckedCount--; + + bool old_state = m_toggleAll->blockSignals(true); + if (m_fieldsCheckedCount == m_fieldCount) + m_toggleAll->setCheckState(Qt::Checked); + else if (m_fieldsCheckedCount == 0) + m_toggleAll->setCheckState(Qt::Unchecked); + else + m_toggleAll->setCheckState(Qt::PartiallyChecked); + m_toggleAll->blockSignals(old_state); +} + +void FilterDialog::toggleAllToggled(int state) +{ + if (sender() != m_toggleAll) + return; + + switch(state) + { + case Qt::Checked: + m_fieldsCheckedCount = m_fieldCount; + break; + case Qt::Unchecked: + m_fieldsCheckedCount = 0; + break; + case Qt::PartiallyChecked: + m_toggleAll->setCheckState(Qt::Checked); + m_fieldsCheckedCount = m_fieldCount; + } + emit stateChanged(m_toggleAll->checkState()); +} + +QString FilterDialog::getFilter(QWidget* parent, const QString& title, + const QString& filterString, bool* ok, Qt::WindowFlags flags, + Qt::InputMethodHints inputMethodHints) +{ + FilterDialog* dlg = new FilterDialog(parent, flags); + dlg->setWindowTitle(title); + dlg->setData(filterString); + + const int ret = dlg->exec(); + if (ok) + *ok = ret; + + QString result; + if (ok) + result = dlg->m_filterString; + + dlg->deleteLater(); + return result; +} + + +void FilterString2FilterFieldMap(const QString filterString, FilterFieldMap* map) +{ + if (!map || !filterString.length()) + return; + + QString levelSuffix; + QString regex; + int minLevel = -1; + int maxLevel = -1; + + int split = filterString.lastIndexOf(';'); + if (split == -1) + { + regex = filterString; + } + else + { + regex = filterString.left(split); + levelSuffix = filterString.mid(split+1); + } + + + // parse level range string + if (levelSuffix.length()) + { + auto range = levelSuffix.split('-'); + bool ok = false; + + if (range.size() == 1) + { + //no dash, only a single level specified - treat as exact match + int level = range[0].toInt(&ok); + if (ok) + { + minLevel = level; + maxLevel = level; + } + else + { + seqWarn("Could not parse level: %s", range[0].toLatin1().data()); + } + } + else if (range.size() == 2) + { + //one dash, two fields - treat as range + int level = range[0].toInt(&ok); + if (ok) + minLevel = level; + else + seqWarn("Could not parse min level: %s", range[0].toLatin1().data()); + + ok = false; + level = range[1].toInt(&ok); + if (ok) + maxLevel = level; + else + seqWarn("Could not parse max level: %s", range[0].toLatin1().data()); + + + // if range wasn't fully/correctly specified, use defaults + minLevel = (minLevel > -1) ? minLevel : 0; + maxLevel = (maxLevel > -1) ? maxLevel : SHRT_MAX; + + } + else + { + seqWarn("Ignoring malformed level range string."); + } + + if (maxLevel < minLevel) + { + int tmp = maxLevel; + maxLevel = minLevel; + minLevel = tmp; + } + } + + + //process filter string and set form/map fields + QStringList tokens = regex.split(":"); + + QStringList::const_iterator itr = tokens.begin(); + for (; itr < tokens.end(); ++itr) + { + QString name = *itr; + if (!map->contains(name)) + { + if (!name.length() && itr == tokens.end() - 1) + { + //filter string has an ending : that we can ignore + continue; + } + + // Info isn't in the map, but we need to process it. + // Also, if there are multi-field wildcards, it could parse + // as a name of ".*" + // Otherwise, skip any unknown fields + if (name != "Info" && name != ".*") + { + seqWarn("Ignoring unknown filter string field: %s", name.toLatin1().data()); + ++itr; // skip this field's data + continue; + } + } + + // handle multi-field wildcards + if (name == ".*") + { + if (++itr == tokens.end()) + break; + + QString value = *itr; + if (map->contains(value) || value == "Info") + { + // value is the next specified field name, so we'll back the + // iterator back to 'name == ".*"' and restart the loop + --itr; + continue; + } + else + { + // we have a value but we don't know what field it belongs to. + // If the next field is set, we could figure it out by working + // backwards, but it's probably not worth the effort. + // So we're just going to warn and ignore it + seqWarn("A match value of \"%s\" was found, but no field was specified. Ignoring.", + value.toLatin1().data()); + continue; + } + } + + // get field data + if (++itr == tokens.end()) + break; + QString value = *itr; + if (!value.trimmed().length()) + continue; + + if (name == "Name" && (value == "Door" || value == "Drop")) + { + //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; + } + + 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) + { + //strip multi field wildcards from name (note, order matters here) + subfield_name = subfield_name.remove("( | .* )"); + subfield_name = subfield_name.remove(".*"); + + // 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 = FSIF_Light; field < FSIF_Max; ++field) + { + if (subfield_name == FilterStringInfoFieldName[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; + + //replace multi field wildcards in value/next + value = value.replace("( | .* )", " "); + + int delim = value.lastIndexOf(' '); + QString next_subfield_name = value.mid(delim+1); + value = value.left(delim); + + (*map)[subfield_name] = value.trimmed(); + + subfield_name = next_subfield_name; + + } + + if (itr == tokens.end()) + break; + } + else + { + (*map)[name] = value.trimmed(); + } + } + + if (minLevel > -1) + (*map)[FSF_MINLEVEL_NAME] = QString::number(minLevel); + + if (maxLevel > -1) + (*map)[FSF_MAXLEVEL_NAME] = QString::number(maxLevel); + +} + +QString FilterFieldMap2FilterString(FilterFieldMap* map) +{ + if (!map) + return QString(); + + QString filterString; + bool wildcard = false; + bool has_first_match = false; + + for (int field = FSF_Name; field < FSF_Max; ++field) + { + QString name = FilterStringFieldName[field]; + + if (name == "Info") + { + //info subfields need special handling + bool info_added = false; + bool info_wildcard = false; + for (int info_field = FSIF_Light; info_field < FSIF_Max; ++info_field) + { + QString subfield_name = FilterStringInfoFieldName[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 += " "; + } + //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(); + + has_first_match = true; + + if (wildcard) + { + wildcard = false; + filterString += ".*:"; + } + filterString += name; + filterString += ":"; + + //Remove/change :'s depending on the field + if (name == "Spawn") + filterString += value.replace(':', '.'); + else if (name != "Name") + filterString += value.remove(':'); + else + filterString += value; + + filterString += ":"; + + } + } + + //min/max level are not part of normal regex string, but still part of filter + int minLevel = -1; + int maxLevel = -1; + + if (map->contains(FSF_MINLEVEL_NAME)) + { + QString value = (*map)[FSF_MINLEVEL_NAME]; + value = value.trimmed(); + bool ok = false; + int level = value.toInt(&ok); + if (ok) + minLevel = level; + } + + if (map->contains(FSF_MAXLEVEL_NAME)) + { + QString value = (*map)[FSF_MAXLEVEL_NAME]; + value = value.trimmed(); + bool ok = false; + int level = value.toInt(&ok); + if (ok) + maxLevel = level; + } + + if (minLevel >= 0 || maxLevel >= 0) + { + minLevel = (minLevel >= 0) ? minLevel : 0; + maxLevel = (maxLevel >= 0) ? maxLevel : SHRT_MAX; + + if (maxLevel < minLevel) + { + int tmp = maxLevel; + maxLevel = minLevel; + minLevel = tmp; + } + + filterString += ";"; + filterString += QString::number(minLevel); + filterString += "-"; + filterString += QString::number(maxLevel); + } + + return filterString; +} + + +#ifndef QMAKEBUILD +#include "filterlistwindow.moc" +#endif Added: showeq/branches/cn187_devel/src/filterlistwindow.h =================================================================== --- showeq/branches/cn187_devel/src/filterlistwindow.h (rev 0) +++ showeq/branches/cn187_devel/src/filterlistwindow.h 2024-07-17 14:27:28 UTC (rev 1497) @@ -0,0 +1,171 @@ +/* + * filterlistwindow.h + * Copyright 2024 by the respective ShowEQ Developers + * + * This file is part of ShowEQ. + * http://www.sourceforge.net/projects/seq + * + * 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; either version 2 of the License, or + * (at your option) any later version. + * + * 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 + */ + +#ifndef FILTERLISTWINDOW_H +#define FILTERLISTWINDOW_H + +#include <QDialog> +#include <QMainWindow> +#include <QAbstractItemModel> +#include <QEvent> +#include <QStatusBar> + +#include "filter.h" + +typedef QHash<QString, QString> FilterFieldMap; + +class FilterModel; + +class FilterListWindow : public QMainWindow +{ + Q_OBJECT + + public: + FilterListWindow(QString filename, QWidget* parent=nullptr, + Qt::WindowFlags flags = Qt::WindowFlags()); + ~FilterListWindow(); + + protected: + QWidget* createTab(QString name); + void setTabLabel(uint8_t type, int count); + + protected slots: + void editItem(QModelIndex index); + void tabButtonClicked(QAction* action); + void createItem(uint8_t type); + void deleteItem(uint8_t type); + void load(); + void loadFile(); + void save(); + void saveAs(); + + private: + QString m_filename; + QTabWidget* m_tabWidget; + QStatusBar* m_statusBar; + Filters* m_filters; + FilterTypes* m_types; + QHash<uint8_t, QTreeView*> m_views; + QHash<uint8_t, FilterModel*> m_models; + + +}; + +class FilterModel : public QAbstractItemModel +{ + Q_OBJECT + + public: + FilterModel(Filters* filters, uint8_t type, QObject* parent=nullptr); + virtual ~FilterModel(); + + virtual QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; + virtual QModelIndex parent(const QModelIndex &index) const; + virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; + virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; + virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; + virtual QVariant headerData(int section, Qt::Orientation, int role = Qt::DisplayRole) const; + + void addFilter(QString filterPattern); + void removeFilter(QModelIndex selection); + + private: + Filters* m_filters; + uint8_t m_type; +}; + + +class FilterFormField : public QWidget +{ + Q_OBJECT + + public: + FilterFormField(QString name, QString labeltext = QString(), QWidget* parent=nullptr); + + QString m_name; + QString m_labeltext; + QCheckBox* m_check; + QLabel* m_label; + QLineEdit* m_edit; + + public slots: + bool eventFilter(QObject* object, QEvent* event); + void stateChanged(int state); +}; + +//SubClassing QCheckBox so we can control the sequence of check/uncheck/partial when +//clicking "Toggle All" +class ToggleAllCheckBox : public QCheckBox +{ + protected: + virtual void nextCheckState() override; + +}; + + + +class FilterDialog : public QDialog +{ + Q_OBJECT + + public: + + static QString getFilter(QWidget* parent, const QString& title, + const QString& filterString, bool* ok=nullptr, + Qt::WindowFlags flags = Qt::WindowFlags(), + Qt::InputMethodHints inputMethodHints = Qt::ImhNone); + + protected: + FilterDialog(QWidget* parent=nullptr, Qt::WindowFlags flags = Qt::WindowFlags()); + ~FilterDialog(); + + void setData(const QString filterString); + void createForm(); + + QHash<QString, FilterFormField*> m_filterFields; + ToggleAllCheckBox* m_toggleAll; + + QString m_spawnFilterString; + FilterFieldMap m_spawnFilterMap; + + QString m_filterString; + int m_fieldCount; + int m_fieldsCheckedCount; + bool m_hasTrailingColon; + + signals: + void stateChanged(int state); + + protected slots: + void resetForm(); + void acceptDialog(); + void fieldToggled(bool checked); + void toggleAllToggled(int state); + +}; + +// helper functions +void FilterString2FilterFieldMap(const QString filterString, FilterFieldMap* map); +QString FilterFieldMap2FilterString(FilterFieldMap* map); + + +#endif Modified: showeq/branches/cn187_devel/src/filtermgr.cpp ===============================================================... [truncated message content] |
From: <cn...@us...> - 2024-07-15 01:00:23
|
Revision: 1496 http://sourceforge.net/p/seq/svn/1496 Author: cn187 Date: 2024-07-15 01:00:22 +0000 (Mon, 15 Jul 2024) Log Message: ----------- Fix qt4 compile error Modified Paths: -------------- showeq/branches/cn187_devel/src/filtermgr.cpp Modified: showeq/branches/cn187_devel/src/filtermgr.cpp =================================================================== --- showeq/branches/cn187_devel/src/filtermgr.cpp 2024-07-15 00:29:11 UTC (rev 1495) +++ showeq/branches/cn187_devel/src/filtermgr.cpp 2024-07-15 01:00:22 UTC (rev 1496) @@ -988,9 +988,9 @@ // 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.back() == ' ') + if (filterString.length() && filterString.endsWith(" ")) { - filterString = filterString.chopped(1); + filterString.chop(1); filterString += "( | .* )"; } else This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-07-15 00:29:14
|
Revision: 1495 http://sourceforge.net/p/seq/svn/1495 Author: cn187 Date: 2024-07-15 00:29:11 +0000 (Mon, 15 Jul 2024) Log Message: ----------- Remove debug print Modified Paths: -------------- showeq/branches/cn187_devel/src/filtermgr.cpp Modified: showeq/branches/cn187_devel/src/filtermgr.cpp =================================================================== --- showeq/branches/cn187_devel/src/filtermgr.cpp 2024-07-15 00:26:20 UTC (rev 1494) +++ showeq/branches/cn187_devel/src/filtermgr.cpp 2024-07-15 00:29:11 UTC (rev 1495) @@ -954,7 +954,6 @@ { if (!info_wildcard) { - seqInfo("%s not in map, setting info wildcard", subfield_name.toLatin1().data()); info_wildcard = true; } continue; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <cn...@us...> - 2024-07-15 00:26:23
|
Revision: 1494 http://sourceforge.net/p/seq/svn/1494 Author: cn187 Date: 2024-07-15 00:26:20 +0000 (Mon, 15 Jul 2024) Log Message: ----------- Fix up filter string logic for edge cases with equipment fields Modified Paths: -------------- showeq/branches/cn187_devel/src/filtermgr.cpp Modified: showeq/branches/cn187_devel/src/filtermgr.cpp =================================================================== --- showeq/branches/cn187_devel/src/filtermgr.cpp 2024-07-14 17:11:08 UTC (rev 1493) +++ showeq/branches/cn187_devel/src/filtermgr.cpp 2024-07-15 00:26:20 UTC (rev 1494) @@ -946,14 +946,16 @@ { //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) { QString subfield_name = InfoFilterStringFieldName[info_field]; if (!map->contains(subfield_name) || !(*map)[subfield_name].trimmed().length()) { - if (has_first_match && !wildcard) + if (!info_wildcard) { - wildcard = true; + seqInfo("%s not in map, setting info wildcard", subfield_name.toLatin1().data()); + info_wildcard = true; } continue; } @@ -961,24 +963,61 @@ QString value = (*map)[subfield_name]; value = value.trimmed(); - has_first_match = true; if (!info_added) { - filterString += "Info:"; + if (wildcard) + { + wildcard = false; + filterString += ".*:Info:"; + } + else + { + filterString += "Info:"; + } info_added = true; } - if (wildcard) + if (info_wildcard) { - wildcard = false; - filterString += ".*"; + 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.back() == ' ') + { + filterString = filterString.chopped(1); + filterString += "( | .* )"; + } + else + { + filterString += ".*"; + } } + filterString += subfield_name; filterString += ":"; filterString += value; filterString += " "; } - filterString += ":"; + //end of Info loop, tidy up + if (info_added) + { + if (info_wildcard) + { + info_wildcard = false; + filterString += ".*:"; + } + else + { + filterString += ":"; + } + } } else { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |