aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-11-21 12:25:22 +0100
committerfunjoker <funjoker109@gmail.com>2023-12-01 23:28:35 +0100
commit070cd23b6cf2e985713b90455cb7f7c53535cbcf (patch)
treecfcd414ecc4d3ef05253140ce83897f693d6dcd3
parentb6e346eaf0ee9a1c0dc2c7977ac950b77c857ecf (diff)
Core/Calendar: Implement different timezone support for ingame calendar
Closes #8390 Closes #29427 (cherry picked from commit b888b1b09f71a8b8b4a9d45c804a1f164fb65ac3)
-rw-r--r--dep/boost/CMakeLists.txt2
-rw-r--r--sql/base/auth_database.sql2
-rw-r--r--sql/updates/auth/master/2023_11_21_00_auth.sql1
-rw-r--r--src/common/Time/Timer.h (renamed from src/common/Utilities/Timer.h)0
-rw-r--r--src/common/Time/Timezone.cpp179
-rw-r--r--src/common/Time/Timezone.h37
-rw-r--r--src/common/Utilities/Hash.h12
-rw-r--r--src/common/Utilities/Util.cpp24
-rw-r--r--src/common/Utilities/Util.h3
-rw-r--r--src/server/bnetserver/Server/Session.cpp31
-rw-r--r--src/server/bnetserver/Server/Session.h2
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.cpp4
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp154
-rw-r--r--src/server/game/Achievements/CriteriaHandler.cpp15
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.cpp12
-rw-r--r--src/server/game/Calendar/CalendarMgr.cpp291
-rw-r--r--src/server/game/Calendar/CalendarMgr.h64
-rw-r--r--src/server/game/Conditions/ConditionMgr.cpp26
-rw-r--r--src/server/game/Entities/Player/Player.cpp4
-rw-r--r--src/server/game/Guilds/Guild.cpp30
-rw-r--r--src/server/game/Guilds/Guild.h2
-rw-r--r--src/server/game/Handlers/AuthHandler.cpp13
-rw-r--r--src/server/game/Handlers/CalendarHandler.cpp31
-rw-r--r--src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp7
-rw-r--r--src/server/game/Scenarios/Scenario.cpp87
-rw-r--r--src/server/game/Scenarios/Scenario.h15
-rw-r--r--src/server/game/Server/Packets/AchievementPackets.cpp66
-rw-r--r--src/server/game/Server/Packets/AchievementPackets.h19
-rw-r--r--src/server/game/Server/Packets/CalendarPackets.cpp39
-rw-r--r--src/server/game/Server/Packets/CalendarPackets.h39
-rw-r--r--src/server/game/Server/Packets/GuildPackets.cpp4
-rw-r--r--src/server/game/Server/Packets/GuildPackets.h5
-rw-r--r--src/server/game/Server/Packets/MiscPackets.cpp4
-rw-r--r--src/server/game/Server/Packets/MiscPackets.h5
-rw-r--r--src/server/game/Server/Packets/SystemPackets.h6
-rw-r--r--src/server/game/Server/WorldSession.cpp7
-rw-r--r--src/server/game/Server/WorldSession.h6
-rw-r--r--src/server/game/Server/WorldSocket.cpp27
-rw-r--r--src/server/game/Services/WorldserverService.cpp2
-rw-r--r--src/server/game/Time/GameTime.cpp17
-rw-r--r--src/server/game/Time/GameTime.h6
-rw-r--r--src/server/game/Time/WowTime.cpp219
-rw-r--r--src/server/game/Time/WowTime.h90
-rw-r--r--src/server/shared/Packets/ByteBuffer.cpp23
-rw-r--r--src/server/shared/Packets/ByteBuffer.h4
-rw-r--r--src/server/shared/Realm/RealmList.cpp10
-rw-r--r--src/server/shared/Realm/RealmList.h4
47 files changed, 1188 insertions, 462 deletions
diff --git a/dep/boost/CMakeLists.txt b/dep/boost/CMakeLists.txt
index 5d0f372594e..845f4ee8edc 100644
--- a/dep/boost/CMakeLists.txt
+++ b/dep/boost/CMakeLists.txt
@@ -29,7 +29,7 @@ else()
set(BOOST_REQUIRED_VERSION 1.71)
endif()
-find_package(Boost ${BOOST_REQUIRED_VERSION} REQUIRED system filesystem program_options iostreams regex)
+find_package(Boost ${BOOST_REQUIRED_VERSION} REQUIRED system filesystem program_options iostreams regex locale)
if(NOT Boost_FOUND)
if(NOT DEFINED ENV{BOOST_ROOT} AND NOT DEFINED Boost_DIR AND NOT DEFINED BOOST_ROOT AND NOT DEFINED BOOSTROOT)
diff --git a/sql/base/auth_database.sql b/sql/base/auth_database.sql
index 32724d2ef56..8a82e84f05c 100644
--- a/sql/base/auth_database.sql
+++ b/sql/base/auth_database.sql
@@ -46,6 +46,7 @@ CREATE TABLE `account` (
`muteby` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`locale` tinyint unsigned NOT NULL DEFAULT '0',
`os` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
+ `timezone_offset` smallint NOT NULL DEFAULT '0',
`recruiter` int unsigned NOT NULL DEFAULT '0',
`battlenet_account` int unsigned DEFAULT NULL,
`battlenet_index` tinyint unsigned DEFAULT NULL,
@@ -2759,6 +2760,7 @@ INSERT INTO `updates` VALUES
('2023_11_09_01_auth.sql','BC9BC28D41608A78166B5A38F3A7F598FBDB879D','RELEASED','2023-11-09 18:21:59',0),
('2023_11_14_00_auth.sql','192D729737C5E3332D7B5B9B7F9DBDD9626D7B98','RELEASED','2023-11-14 11:36:05',0),
('2023_11_15_00_auth.sql','DC89EA5C9D799C213B3E6A606F081697ADEF8250','RELEASED','2023-11-15 10:47:53',0),
+('2023_11_21_00_auth.sql','146E5E6EF94C5DB78343372A8FDB32B062B80040','RELEASED','2023-11-21 11:24:11',0),
('2023_11_23_00_auth.sql','EC3D1289A07E387BF4D2AC94EEBE3A29483EAD3A','RELEASED','2023-11-23 02:39:18',0);
/*!40000 ALTER TABLE `updates` ENABLE KEYS */;
UNLOCK TABLES;
diff --git a/sql/updates/auth/master/2023_11_21_00_auth.sql b/sql/updates/auth/master/2023_11_21_00_auth.sql
new file mode 100644
index 00000000000..1dc190782d7
--- /dev/null
+++ b/sql/updates/auth/master/2023_11_21_00_auth.sql
@@ -0,0 +1 @@
+ALTER TABLE `account` ADD `timezone_offset` smallint NOT NULL DEFAULT '0' AFTER `os`;
diff --git a/src/common/Utilities/Timer.h b/src/common/Time/Timer.h
index e0ecb5b2d13..e0ecb5b2d13 100644
--- a/src/common/Utilities/Timer.h
+++ b/src/common/Time/Timer.h
diff --git a/src/common/Time/Timezone.cpp b/src/common/Time/Timezone.cpp
new file mode 100644
index 00000000000..f7acfe5df5c
--- /dev/null
+++ b/src/common/Time/Timezone.cpp
@@ -0,0 +1,179 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "Timezone.h"
+#include "Hash.h"
+#include "MapUtils.h"
+#include "Util.h"
+#include <boost/locale/date_time_facet.hpp>
+#include <boost/locale/generator.hpp>
+#include <chrono>
+#include <unordered_map>
+
+namespace
+{
+std::unordered_map<uint32, Minutes, std::identity> InitTimezoneHashDb()
+{
+#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
+
+ // Generate our hash db to match values sent in client authentication packets
+ std::unordered_map<uint32, Minutes, std::identity> hashToOffset;
+ std::chrono::system_clock::time_point dummmy;
+ for (std::chrono::time_zone const& zone : std::chrono::get_tzdb().zones)
+ {
+ std::chrono::sys_info sysInfo = zone.get_info(dummmy);
+ Minutes offsetMinutes = std::chrono::duration_cast<Minutes>(sysInfo.offset);
+ std::string offsetStr = Trinity::ToString(offsetMinutes.count());
+ hashToOffset.emplace(Trinity::HashFnv1a(offsetStr), offsetMinutes);
+ }
+
+#else
+ // Pre-generated list of timezone offsets and their hashes for compilers (and their stl implementations) that dont support timezone api yet
+ std::unordered_map<uint32, Minutes, std::identity> hashToOffset =
+ {
+ { 0xAADC2D37u, -720min },
+ { 0x362F107Bu, -690min },
+ { 0x2C44C70Cu, -660min },
+ { 0xB84A209Eu, -640min },
+ { 0xBA3D57D1u, -630min },
+ { 0x4040695Au, -600min },
+ { 0xB65A75D0u, -570min },
+ { 0xC8614DEBu, -540min },
+ { 0x3A68BD26u, -510min },
+ { 0x51E8096Cu, -480min },
+ { 0x4DD8F896u, -420min },
+ { 0x674B7C0Fu, -360min },
+ { 0x633C6B39u, -300min },
+ { 0x0BAD340Au, -240min },
+ { 0x74B25683u, -225min },
+ { 0x09B9FCD7u, -210min },
+ { 0x150C169Bu, -180min },
+ { 0x191B2771u, -120min },
+ { 0xD7D3B14Eu, -60min },
+ { 0x47CE5170u, -44min },
+ { 0x350CA8AFu, 0min },
+ { 0x15E8E23Bu, 60min },
+ { 0x733864AEu, 120min },
+ { 0xF71F9C94u, 180min },
+ { 0xBDE50F54u, 210min },
+ { 0x2BDD6DB9u, 240min },
+ { 0xB1E07F42u, 270min },
+ { 0x454FF132u, 300min },
+ { 0x3F4DA929u, 330min },
+ { 0xD1554AC4u, 360min },
+ { 0xBB667143u, 390min },
+ { 0x9E2B78C9u, 420min },
+ { 0x1C377816u, 450min },
+ { 0x1A4440E3u, 480min },
+ { 0xB49DF789u, 525min },
+ { 0xC3A28C54u, 540min },
+ { 0x35A9FB8Fu, 570min },
+ { 0x889BD751u, 600min },
+ { 0x8CAAE827u, 660min },
+ { 0x7285EE60u, 690min },
+ { 0x1CC2DEF4u, 720min },
+ { 0x89B8FD2Fu, 765min },
+ { 0x98DBA70Eu, 780min },
+ { 0xC59585BBu, 840min }
+ };
+#endif
+
+ return hashToOffset;
+}
+
+std::unordered_map<uint32, Minutes, std::identity> const _timezoneOffsetsByHash = InitTimezoneHashDb();
+
+using ClientSupportedTimezone = std::pair<Minutes, std::string>;
+std::array<ClientSupportedTimezone, 11> const _clientSupportedTimezones =
+{{
+ { -480min, "America/Los_Angeles" },
+ { -420min, "America/Denver" },
+ { -360min, "America/Chicago" },
+ { -300min, "America/New_York" },
+ { -180min, "America/Sao_Paulo" },
+ { 0min, "Etc/UTC" },
+ { 60min, "Europe/Paris" },
+ { 480min, "Asia/Shanghai" },
+ { 480min, "Asia/Taipei" },
+ { 540min, "Asia/Seoul" },
+ { 600min, "Australia/Melbourne" },
+}};
+}
+
+namespace Trinity::Timezone
+{
+Minutes GetOffsetByHash(uint32 hash)
+{
+ if (Minutes const* offset = Containers::MapGetValuePtr(_timezoneOffsetsByHash, hash))
+ return *offset;
+
+ return 0min;
+}
+
+Minutes GetSystemZoneOffsetAt(SystemTimePoint date)
+{
+ Seconds offset;
+#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
+ offset = std::chrono::current_zone()->get_info(date).offset;
+#else
+ tm buf = TimeBreakdown(std::chrono::system_clock::to_time_t(date));
+ offset = Seconds(buf.tm_gmtoff);
+#endif
+ return std::chrono::duration_cast<Minutes>(offset);
+}
+
+Minutes GetSystemZoneOffset(bool applyDst /*= true*/)
+{
+ std::chrono::system_clock::time_point date = std::chrono::system_clock::from_time_t(std::time_t(0));
+ if (applyDst)
+ date = std::chrono::system_clock::now();
+
+ return GetSystemZoneOffsetAt(date);
+}
+
+std::string GetSystemZoneName()
+{
+#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS
+ return std::string(std::chrono::current_zone()->name());
+#else
+ static std::locale calendarLocale = boost::locale::generator().generate("");
+ std::unique_ptr<boost::locale::abstract_calendar> p(std::use_facet<class boost::locale::calendar_facet>(calendarLocale).create_calendar());
+ return p->get_timezone();
+#endif
+}
+
+std::string_view FindClosestClientSupportedTimezone(std::string_view currentTimezone, Minutes currentTimezoneOffset)
+{
+ // try exact match
+ auto itr = std::find_if(_clientSupportedTimezones.begin(), _clientSupportedTimezones.end(), [currentTimezone](ClientSupportedTimezone const& tz)
+ {
+ return tz.second == currentTimezone;
+ });
+ if (itr != _clientSupportedTimezones.end())
+ return itr->second;
+
+ // try closest offset
+ itr = std::min_element(_clientSupportedTimezones.begin(), _clientSupportedTimezones.end(), [currentTimezoneOffset](ClientSupportedTimezone const& left, ClientSupportedTimezone const& right)
+ {
+ Minutes leftDiff = left.first - currentTimezoneOffset;
+ Minutes rightDiff = right.first - currentTimezoneOffset;
+ return std::abs(leftDiff.count()) < std::abs(rightDiff.count());
+ });
+
+ return itr->second;
+}
+}
diff --git a/src/common/Time/Timezone.h b/src/common/Time/Timezone.h
new file mode 100644
index 00000000000..769bf0c5921
--- /dev/null
+++ b/src/common/Time/Timezone.h
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITYCORE_TIMEZONE_H
+#define TRINITYCORE_TIMEZONE_H
+
+#include "Define.h"
+#include "Duration.h"
+
+namespace Trinity::Timezone
+{
+TC_COMMON_API Minutes GetOffsetByHash(uint32 hash);
+
+// Returns the time offset that must be added to UTC time to get localtime
+TC_COMMON_API Minutes GetSystemZoneOffsetAt(SystemTimePoint date);
+TC_COMMON_API Minutes GetSystemZoneOffset(bool applyDst = true);
+
+TC_COMMON_API std::string GetSystemZoneName();
+
+TC_COMMON_API std::string_view FindClosestClientSupportedTimezone(std::string_view currentTimezone, Minutes currentTimezoneOffset);
+}
+
+#endif // TRINITYCORE_TIMEZONE_H
diff --git a/src/common/Utilities/Hash.h b/src/common/Utilities/Hash.h
index b63201bf07a..18f7442fb44 100644
--- a/src/common/Utilities/Hash.h
+++ b/src/common/Utilities/Hash.h
@@ -19,6 +19,7 @@
#define TrinityCore_Hash_h__
#include <functional>
+#include <string_view>
#include <utility>
namespace Trinity
@@ -28,6 +29,17 @@ namespace Trinity
{
seed ^= std::hash<T>()(val) + 0x9E3779B9 + (seed << 6) + (seed >> 2);
}
+
+ inline std::uint32_t HashFnv1a(std::string_view data)
+ {
+ std::uint32_t hash = 0x811C9DC5u;
+ for (char c : data)
+ {
+ hash ^= c;
+ hash *= 0x1000193u;
+ }
+ return hash;
+ }
}
//! Hash implementation for std::pair to allow using pairs in unordered_set or as key for unordered_map
diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp
index ac97e724902..d852ed655a0 100644
--- a/src/common/Utilities/Util.cpp
+++ b/src/common/Utilities/Util.cpp
@@ -58,9 +58,20 @@ std::vector<std::string_view> Trinity::Tokenize(std::string_view str, char sep,
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
struct tm* localtime_r(time_t const* time, struct tm *result)
{
- localtime_s(result, time);
+ if (localtime_s(result, time) != 0)
+ return nullptr;
return result;
}
+struct tm* gmtime_r(time_t const* time, struct tm* result)
+{
+ if (gmtime_s(result, time) != 0)
+ return nullptr;
+ return result;
+}
+time_t timegm(struct tm* tm)
+{
+ return _mkgmtime(tm);
+}
#endif
tm TimeBreakdown(time_t time)
@@ -70,17 +81,6 @@ tm TimeBreakdown(time_t time)
return timeLocal;
}
-time_t LocalTimeToUTCTime(time_t time)
-{
-#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
- return time + _timezone;
-#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
- return timegm(gmtime(&time));
-#else
- return time + timezone;
-#endif
-}
-
time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime)
{
tm timeLocal = TimeBreakdown(time);
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index be4a68d7788..334b3ab6ac0 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -54,8 +54,9 @@ TC_COMMON_API Optional<int64> MoneyStringToMoney(std::string const& moneyString)
#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__))
TC_COMMON_API struct tm* localtime_r(time_t const* time, struct tm *result);
+TC_COMMON_API struct tm* gmtime_r(time_t const* time, struct tm *result);
+TC_COMMON_API time_t timegm(struct tm* tm);
#endif
-TC_COMMON_API time_t LocalTimeToUTCTime(time_t time);
TC_COMMON_API time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime = true);
TC_COMMON_API tm TimeBreakdown(time_t t);
diff --git a/src/server/bnetserver/Server/Session.cpp b/src/server/bnetserver/Server/Session.cpp
index 6e5b16cd477..95c46418a7d 100644
--- a/src/server/bnetserver/Server/Session.cpp
+++ b/src/server/bnetserver/Server/Session.cpp
@@ -21,13 +21,17 @@
#include "CryptoRandom.h"
#include "DatabaseEnv.h"
#include "Errors.h"
+#include "Hash.h"
#include "IPLocation.h"
-#include "QueryCallback.h"
#include "LoginRESTService.h"
+#include "MapUtils.h"
#include "ProtobufJSON.h"
+#include "QueryCallback.h"
#include "RealmList.h"
-#include "ServiceDispatcher.h"
#include "RealmList.pb.h"
+#include "ServiceDispatcher.h"
+#include "Timezone.h"
+#include <rapidjson/document.h>
#include <zlib.h>
void Battlenet::Session::AccountInfo::LoadResult(PreparedQueryResult result)
@@ -229,6 +233,26 @@ uint32 Battlenet::Session::HandleLogon(authentication::v1::LogonRequest const* l
_os = logonRequest->platform();
_build = logonRequest->application_version();
+ _timezoneOffset = [&]
+ {
+ if (!logonRequest->has_device_id())
+ return 0min;
+
+ rapidjson::Document doc;
+ doc.Parse(logonRequest->device_id());
+ if (doc.HasParseError())
+ return 0min;
+
+ auto itr = doc.FindMember("UTCO");
+ if (itr == doc.MemberEnd())
+ return 0min;
+
+ if (!itr->value.IsUint())
+ return 0min;
+
+ return Trinity::Timezone::GetOffsetByHash(itr->value.GetUint());
+ }();
+
if (logonRequest->has_cached_web_credentials())
return VerifyWebCredentials(logonRequest->cached_web_credentials(), continuation);
@@ -670,7 +694,8 @@ uint32 Battlenet::Session::GetRealmList(std::unordered_map<std::string, Variant
uint32 Battlenet::Session::JoinRealm(std::unordered_map<std::string, Variant const*> const& params, game_utilities::v1::ClientResponse* response)
{
if (Variant const* realmAddress = GetParam(params, "Param_RealmAddress"))
- return sRealmList->JoinRealm(realmAddress->uint_value(), _build, GetRemoteIpAddress(), _clientSecret, GetLocaleByName(_locale), _os, _gameAccountInfo->Name, response);
+ return sRealmList->JoinRealm(realmAddress->uint_value(), _build, GetRemoteIpAddress(), _clientSecret, GetLocaleByName(_locale),
+ _os, _timezoneOffset, _gameAccountInfo->Name, response);
return ERROR_WOW_SERVICES_INVALID_JOIN_TICKET;
}
diff --git a/src/server/bnetserver/Server/Session.h b/src/server/bnetserver/Server/Session.h
index fd375b3a19a..01167d38a0b 100644
--- a/src/server/bnetserver/Server/Session.h
+++ b/src/server/bnetserver/Server/Session.h
@@ -19,6 +19,7 @@
#define Session_h__
#include "AsyncCallbackProcessor.h"
+#include "Duration.h"
#include "Realm.h"
#include "SslContext.h"
#include "SslSocket.h"
@@ -173,6 +174,7 @@ namespace Battlenet
std::string _locale;
std::string _os;
uint32 _build;
+ Minutes _timezoneOffset;
std::string _ipCountry;
diff --git a/src/server/database/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp
index 0b9fd4e8f89..5745a063e53 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.cpp
+++ b/src/server/database/Database/Implementation/LoginDatabase.cpp
@@ -39,7 +39,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
PrepareStatement(LOGIN_UPD_LOGON, "UPDATE account SET salt = ?, verifier = ? WHERE id = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME, "SELECT id FROM account WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_ACCOUNT_LIST_BY_NAME, "SELECT id, username FROM account WHERE username = ?", CONNECTION_SYNCH);
- PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.session_key_bnet, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, ba.id, aa.SecurityLevel, "
+ PrepareStatement(LOGIN_SEL_ACCOUNT_INFO_BY_NAME, "SELECT a.id, a.session_key_bnet, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, a.timezone_offset, ba.id, aa.SecurityLevel, "
"bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id "
"FROM account a LEFT JOIN account r ON a.id = r.recruiter LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id "
"LEFT JOIN account_access aa ON a.id = aa.AccountID AND aa.RealmID IN (-1, ?) LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 "
@@ -129,7 +129,7 @@ void LoginDatabaseConnection::DoPrepareStatements()
" FROM battlenet_accounts ba LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account a ON ba.id = a.battlenet_account"
" LEFT JOIN account_banned ab ON a.id = ab.id AND ab.active = 1 LEFT JOIN account_access aa ON a.id = aa.AccountID AND aa.RealmID = -1 WHERE ba.LoginTicket = ? ORDER BY a.id", CONNECTION_ASYNC);
PrepareStatement(LOGIN_UPD_BNET_LAST_LOGIN_INFO, "UPDATE battlenet_accounts SET last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE id = ?", CONNECTION_ASYNC);
- PrepareStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LOGIN_INFO, "UPDATE account SET session_key_bnet = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ? WHERE username = ?", CONNECTION_SYNCH);
+ PrepareStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LOGIN_INFO, "UPDATE account SET session_key_bnet = ?, last_ip = ?, last_login = NOW(), locale = ?, failed_logins = 0, os = ?, timezone_offset = ? WHERE username = ?", CONNECTION_SYNCH);
PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_ACCOUNT_ID, "SELECT rc.acctid, rc.numchars, r.id, r.Region, r.Battlegroup FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id WHERE rc.acctid = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID, "SELECT rc.acctid, rc.numchars, r.id, r.Region, r.Battlegroup FROM realmcharacters rc INNER JOIN realmlist r ON rc.realmid = r.id LEFT JOIN account a ON rc.acctid = a.id WHERE a.battlenet_account = ?", CONNECTION_ASYNC);
PrepareStatement(LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS, "SELECT lpc.accountId, lpc.region, lpc.battlegroup, lpc.realmId, lpc.characterName, lpc.characterGUID, lpc.lastPlayedTime FROM account_last_played_character lpc LEFT JOIN account a ON lpc.accountId = a.id WHERE a.battlenet_account = ?", CONNECTION_ASYNC);
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 46891c35031..a2b401215f2 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -370,42 +370,42 @@ void PlayerAchievementMgr::SendAllData(Player const* /*receiver*/) const
if (!achievement)
continue;
- WorldPackets::Achievement::EarnedAchievement earned;
+ WorldPackets::Achievement::EarnedAchievement& earned = achievementData.Data.Earned.emplace_back();
earned.Id = completedAchievement.first;
- earned.Date = completedAchievement.second.Date;
+ earned.Date.SetUtcTimeFromUnixTime(completedAchievement.second.Date);
+ earned.Date += _owner->GetSession()->GetTimezoneOffset();
if (!(achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT))
{
earned.Owner = _owner->GetGUID();
earned.VirtualRealmAddress = earned.NativeRealmAddress = GetVirtualRealmAddress();
}
- achievementData.Data.Earned.push_back(earned);
}
for (std::pair<uint32 const, CriteriaProgress> const& criteriaProgres : _criteriaProgress)
{
Criteria const* criteria = sCriteriaMgr->GetCriteria(criteriaProgres.first);
- WorldPackets::Achievement::CriteriaProgress progress;
+ WorldPackets::Achievement::CriteriaProgress& progress = achievementData.Data.Progress.emplace_back();
progress.Id = criteriaProgres.first;
progress.Quantity = criteriaProgres.second.Counter;
progress.Player = criteriaProgres.second.PlayerGUID;
progress.Flags = 0;
- progress.Date = criteriaProgres.second.Date;
+ progress.Date.SetUtcTimeFromUnixTime(criteriaProgres.second.Date);
+ progress.Date += _owner->GetSession()->GetTimezoneOffset();
progress.TimeFromStart = Seconds::zero();
progress.TimeFromCreate = Seconds::zero();
- achievementData.Data.Progress.push_back(progress);
if (criteria->FlagsCu & CRITERIA_FLAG_CU_ACCOUNT)
{
- WorldPackets::Achievement::CriteriaProgress progress;
- progress.Id = criteriaProgres.first;
- progress.Quantity = criteriaProgres.second.Counter;
- progress.Player = _owner->GetSession()->GetBattlenetAccountGUID();
- progress.Flags = 0;
- progress.Date = criteriaProgres.second.Date;
- progress.TimeFromStart = Seconds::zero();
- progress.TimeFromCreate = Seconds::zero();
- allAccountCriteria.Progress.push_back(progress);
+ WorldPackets::Achievement::CriteriaProgress& accountProgress = allAccountCriteria.Progress.emplace_back();
+ accountProgress.Id = criteriaProgres.first;
+ accountProgress.Quantity = criteriaProgres.second.Counter;
+ accountProgress.Player = _owner->GetSession()->GetBattlenetAccountGUID();
+ accountProgress.Flags = 0;
+ accountProgress.Date.SetUtcTimeFromUnixTime(criteriaProgres.second.Date);
+ accountProgress.Date += _owner->GetSession()->GetTimezoneOffset();
+ accountProgress.TimeFromStart = Seconds::zero();
+ accountProgress.TimeFromCreate = Seconds::zero();
}
}
@@ -429,28 +429,28 @@ void PlayerAchievementMgr::SendAchievementInfo(Player* receiver, uint32 /*achiev
if (!achievement)
continue;
- WorldPackets::Achievement::EarnedAchievement earned;
+ WorldPackets::Achievement::EarnedAchievement& earned = inspectedAchievements.Data.Earned.emplace_back();
earned.Id = completedAchievement.first;
- earned.Date = completedAchievement.second.Date;
+ earned.Date.SetUtcTimeFromUnixTime(completedAchievement.second.Date);
+ earned.Date += receiver->GetSession()->GetTimezoneOffset();
if (!(achievement->Flags & ACHIEVEMENT_FLAG_ACCOUNT))
{
earned.Owner = _owner->GetGUID();
earned.VirtualRealmAddress = earned.NativeRealmAddress = GetVirtualRealmAddress();
}
- inspectedAchievements.Data.Earned.push_back(earned);
}
for (std::pair<uint32 const, CriteriaProgress> const& criteriaProgres : _criteriaProgress)
{
- WorldPackets::Achievement::CriteriaProgress progress;
+ WorldPackets::Achievement::CriteriaProgress& progress = inspectedAchievements.Data.Progress.emplace_back();
progress.Id = criteriaProgres.first;
progress.Quantity = criteriaProgres.second.Counter;
progress.Player = criteriaProgres.second.PlayerGUID;
progress.Flags = 0;
- progress.Date = criteriaProgres.second.Date;
+ progress.Date.SetUtcTimeFromUnixTime(criteriaProgres.second.Date);
+ progress.Date += receiver->GetSession()->GetTimezoneOffset();
progress.TimeFromStart = Seconds::zero();
progress.TimeFromCreate = Seconds::zero();
- inspectedAchievements.Data.Progress.push_back(progress);
}
receiver->SendDirectMessage(inspectedAchievements.Write());
@@ -571,7 +571,8 @@ void PlayerAchievementMgr::SendCriteriaUpdate(Criteria const* criteria, Criteria
if (criteria->Entry->StartTimer)
criteriaUpdate.Progress.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
- criteriaUpdate.Progress.Date = progress->Date;
+ criteriaUpdate.Progress.Date.SetUtcTimeFromUnixTime(progress->Date);
+ criteriaUpdate.Progress.Date += _owner->GetSession()->GetTimezoneOffset();
criteriaUpdate.Progress.TimeFromStart = timeElapsed;
criteriaUpdate.Progress.TimeFromCreate = Seconds::zero();
@@ -588,7 +589,8 @@ void PlayerAchievementMgr::SendCriteriaUpdate(Criteria const* criteria, Criteria
if (criteria->Entry->StartTimer)
criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
- criteriaUpdate.CurrentTime = progress->Date;
+ criteriaUpdate.CurrentTime.SetUtcTimeFromUnixTime(progress->Date);
+ criteriaUpdate.CurrentTime += _owner->GetSession()->GetTimezoneOffset();
criteriaUpdate.ElapsedTime = timeElapsed;
criteriaUpdate.CreationTime = 0;
@@ -639,16 +641,26 @@ void PlayerAchievementMgr::SendAchievementEarned(AchievementEntry const* achieve
}
}
- WorldPackets::Achievement::AchievementEarned achievementEarned;
- achievementEarned.Sender = _owner->GetGUID();
- achievementEarned.Earner = _owner->GetGUID();
- achievementEarned.EarnerNativeRealm = achievementEarned.EarnerVirtualRealm = GetVirtualRealmAddress();
- achievementEarned.AchievementID = achievement->ID;
- achievementEarned.Time = GameTime::GetGameTime();
+ auto achievementEarnedBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Achievement::AchievementEarned achievementEarned;
+ achievementEarned.Sender = _owner->GetGUID();
+ achievementEarned.Earner = _owner->GetGUID();
+ achievementEarned.EarnerNativeRealm = achievementEarned.EarnerVirtualRealm = GetVirtualRealmAddress();
+ achievementEarned.AchievementID = achievement->ID;
+ achievementEarned.Time = *GameTime::GetUtcWowTime();
+ achievementEarned.Time += receiver->GetSession()->GetTimezoneOffset();
+ receiver->SendDirectMessage(achievementEarned.Write());
+ };
+
if (!(achievement->Flags & ACHIEVEMENT_FLAG_TRACKING_FLAG))
- _owner->SendMessageToSetInRange(achievementEarned.Write(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), true);
+ {
+ float dist = sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY);
+ Trinity::MessageDistDeliverer notifier(_owner, achievementEarnedBuilder, dist);
+ Cell::VisitWorldObjects(_owner, notifier, dist);
+ }
else
- _owner->SendDirectMessage(achievementEarned.Write());
+ achievementEarnedBuilder(_owner);
}
void PlayerAchievementMgr::SendPacket(WorldPacket const* data) const
@@ -672,11 +684,16 @@ void GuildAchievementMgr::Reset()
ObjectGuid guid = _owner->GetGUID();
for (std::pair<uint32 const, CompletedAchievementData> const& completedAchievement : _completedAchievements)
{
- WorldPackets::Achievement::GuildAchievementDeleted guildAchievementDeleted;
- guildAchievementDeleted.AchievementID = completedAchievement.first;
- guildAchievementDeleted.GuildGUID = guid;
- guildAchievementDeleted.TimeDeleted = GameTime::GetGameTime();
- SendPacket(guildAchievementDeleted.Write());
+ auto packetBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Achievement::GuildAchievementDeleted guildAchievementDeleted;
+ guildAchievementDeleted.AchievementID = completedAchievement.first;
+ guildAchievementDeleted.GuildGUID = guid;
+ guildAchievementDeleted.TimeDeleted = *GameTime::GetUtcWowTime();
+ guildAchievementDeleted.TimeDeleted += receiver->GetSession()->GetTimezoneOffset();
+ receiver->SendDirectMessage(guildAchievementDeleted.Write());
+ };
+ _owner->BroadcastWorker(packetBuilder);
}
_achievementPoints = 0;
@@ -823,10 +840,10 @@ void GuildAchievementMgr::SendAllData(Player const* receiver) const
if (!achievement)
continue;
- WorldPackets::Achievement::EarnedAchievement earned;
+ WorldPackets::Achievement::EarnedAchievement& earned = allGuildAchievements.Earned.emplace_back();
earned.Id = completedAchievement.first;
- earned.Date = completedAchievement.second.Date;
- allGuildAchievements.Earned.push_back(earned);
+ earned.Date.SetUtcTimeFromUnixTime(completedAchievement.second.Date);
+ earned.Date += receiver->GetSession()->GetTimezoneOffset();
}
receiver->SendDirectMessage(allGuildAchievements.Write());
@@ -839,23 +856,22 @@ void GuildAchievementMgr::SendAchievementInfo(Player* receiver, uint32 achieveme
{
if (CriteriaTree const* tree = sCriteriaMgr->GetCriteriaTree(achievement->CriteriaTree))
{
- CriteriaMgr::WalkCriteriaTree(tree, [this, &guildCriteriaUpdate](CriteriaTree const* node)
+ CriteriaMgr::WalkCriteriaTree(tree, [this, &guildCriteriaUpdate, receiver](CriteriaTree const* node)
{
if (node->Criteria)
{
auto progress = this->_criteriaProgress.find(node->Criteria->ID);
if (progress != this->_criteriaProgress.end())
{
- WorldPackets::Achievement::GuildCriteriaProgress guildCriteriaProgress;
+ WorldPackets::Achievement::GuildCriteriaProgress& guildCriteriaProgress = guildCriteriaUpdate.Progress.emplace_back();
guildCriteriaProgress.CriteriaID = node->Criteria->ID;
guildCriteriaProgress.DateCreated = 0;
guildCriteriaProgress.DateStarted = 0;
- guildCriteriaProgress.DateUpdated = progress->second.Date;
+ guildCriteriaProgress.DateUpdated.SetUtcTimeFromUnixTime(progress->second.Date);
+ guildCriteriaProgress.DateUpdated += receiver->GetSession()->GetTimezoneOffset();
guildCriteriaProgress.Quantity = progress->second.Counter;
guildCriteriaProgress.PlayerGUID = progress->second.PlayerGUID;
guildCriteriaProgress.Flags = 0;
-
- guildCriteriaUpdate.Progress.push_back(guildCriteriaProgress);
}
}
});
@@ -876,16 +892,15 @@ void GuildAchievementMgr::SendAllTrackedCriterias(Player* receiver, std::set<uin
if (progress == _criteriaProgress.end())
continue;
- WorldPackets::Achievement::GuildCriteriaProgress guildCriteriaProgress;
+ WorldPackets::Achievement::GuildCriteriaProgress& guildCriteriaProgress = guildCriteriaUpdate.Progress.emplace_back();
guildCriteriaProgress.CriteriaID = criteriaId;
guildCriteriaProgress.DateCreated = 0;
guildCriteriaProgress.DateStarted = 0;
- guildCriteriaProgress.DateUpdated = progress->second.Date;
+ guildCriteriaProgress.DateUpdated.SetUtcTimeFromUnixTime(progress->second.Date);
+ guildCriteriaProgress.DateUpdated += receiver->GetSession()->GetTimezoneOffset();
guildCriteriaProgress.Quantity = progress->second.Counter;
guildCriteriaProgress.PlayerGUID = progress->second.PlayerGUID;
guildCriteriaProgress.Flags = 0;
-
- guildCriteriaUpdate.Progress.push_back(guildCriteriaProgress);
}
receiver->SendDirectMessage(guildCriteriaUpdate.Write());
@@ -949,19 +964,21 @@ void GuildAchievementMgr::CompletedAchievement(AchievementEntry const* achieveme
void GuildAchievementMgr::SendCriteriaUpdate(Criteria const* entry, CriteriaProgress const* progress, Seconds /*timeElapsed*/, bool /*timedCompleted*/) const
{
- WorldPackets::Achievement::GuildCriteriaUpdate guildCriteriaUpdate;
- guildCriteriaUpdate.Progress.resize(1);
-
- WorldPackets::Achievement::GuildCriteriaProgress& guildCriteriaProgress = guildCriteriaUpdate.Progress[0];
- guildCriteriaProgress.CriteriaID = entry->ID;
- guildCriteriaProgress.DateCreated = 0;
- guildCriteriaProgress.DateStarted = 0;
- guildCriteriaProgress.DateUpdated = progress->Date;
- guildCriteriaProgress.Quantity = progress->Counter;
- guildCriteriaProgress.PlayerGUID = progress->PlayerGUID;
- guildCriteriaProgress.Flags = 0;
-
- _owner->BroadcastPacketIfTrackingAchievement(guildCriteriaUpdate.Write(), entry->ID);
+ for (Player const* member : _owner->GetMembersTrackingCriteria(entry->ID))
+ {
+ WorldPackets::Achievement::GuildCriteriaUpdate guildCriteriaUpdate;
+ WorldPackets::Achievement::GuildCriteriaProgress& guildCriteriaProgress = guildCriteriaUpdate.Progress.emplace_back();
+ guildCriteriaProgress.CriteriaID = entry->ID;
+ guildCriteriaProgress.DateCreated = 0;
+ guildCriteriaProgress.DateStarted = 0;
+ guildCriteriaProgress.DateUpdated.SetUtcTimeFromUnixTime(progress->Date);
+ guildCriteriaProgress.DateUpdated += member->GetSession()->GetTimezoneOffset();
+ guildCriteriaProgress.Quantity = progress->Counter;
+ guildCriteriaProgress.PlayerGUID = progress->PlayerGUID;
+ guildCriteriaProgress.Flags = 0;
+
+ member->SendDirectMessage(guildCriteriaUpdate.Write());
+ }
}
void GuildAchievementMgr::SendCriteriaProgressRemoved(uint32 criteriaId)
@@ -985,11 +1002,16 @@ void GuildAchievementMgr::SendAchievementEarned(AchievementEntry const* achievem
sWorld->SendGlobalMessage(serverFirstAchievement.Write());
}
- WorldPackets::Achievement::GuildAchievementEarned guildAchievementEarned;
- guildAchievementEarned.AchievementID = achievement->ID;
- guildAchievementEarned.GuildGUID = _owner->GetGUID();
- guildAchievementEarned.TimeEarned = GameTime::GetGameTime();
- SendPacket(guildAchievementEarned.Write());
+ auto guildAchievementEarnedBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Achievement::GuildAchievementEarned guildAchievementEarned;
+ guildAchievementEarned.AchievementID = achievement->ID;
+ guildAchievementEarned.GuildGUID = _owner->GetGUID();
+ guildAchievementEarned.TimeEarned = *GameTime::GetUtcWowTime();
+ guildAchievementEarned.TimeEarned += receiver->GetSession()->GetTimezoneOffset();
+ receiver->SendDirectMessage(guildAchievementEarned.Write());
+ };
+ _owner->BroadcastWorker(guildAchievementEarnedBuilder);
}
void GuildAchievementMgr::SendPacket(WorldPacket const* data) const
diff --git a/src/server/game/Achievements/CriteriaHandler.cpp b/src/server/game/Achievements/CriteriaHandler.cpp
index a821b11c642..8d9a54c8789 100644
--- a/src/server/game/Achievements/CriteriaHandler.cpp
+++ b/src/server/game/Achievements/CriteriaHandler.cpp
@@ -49,6 +49,7 @@
#include "World.h"
#include "WorldSession.h"
#include "WorldStateMgr.h"
+#include "WowTime.h"
bool CriteriaData::IsValid(Criteria const* criteria)
{
@@ -2230,14 +2231,12 @@ bool CriteriaHandler::ModifierSatisfied(ModifierTreeEntry const* modifier, uint6
break;
case ModifierTreeType::TimeBetween: // 109
{
- ByteBuffer unpacker;
- unpacker << reqValue;
- time_t from = unpacker.ReadPackedTime();
- unpacker.rpos(0);
- unpacker.wpos(0);
- unpacker << secondaryAsset;
- time_t to = unpacker.ReadPackedTime();
- if (GameTime::GetGameTime() < from || GameTime::GetGameTime() > to)
+ WowTime from;
+ from.SetPackedTime(reqValue);
+ WowTime to;
+ to.SetPackedTime(secondaryAsset);
+
+ if (!GameTime::GetWowTime()->IsInRange(from, to))
return false;
break;
}
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
index 0d149078279..21332e20171 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.cpp
@@ -34,11 +34,11 @@
#include "ObjectAccessor.h"
#include "ObjectMgr.h"
#include "Player.h"
-#include "Realm.h"
#include "ScriptMgr.h"
+#include "Timezone.h"
#include "World.h"
-#include "WorldPacket.h"
#include "WorldSession.h"
+#include "WowTime.h"
#include <boost/dynamic_bitset.hpp>
#include <numeric>
#include <sstream>
@@ -1911,13 +1911,13 @@ void AuctionHouseObject::SendAuctionInvoice(AuctionPosting const* auction, Playe
// owner exist (online or offline)
if ((owner || sCharacterCache->HasCharacterCacheEntry(auction->Owner)) && !sAuctionBotConfig->IsBotChar(auction->Owner))
{
- ByteBuffer tempBuffer;
- tempBuffer.AppendPackedTime(GameTime::GetGameTime() + sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY));
- uint32 eta = tempBuffer.read<uint32>();
+ WowTime eta = *GameTime::GetUtcWowTime();
+ eta += Seconds(sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY));
+ eta += owner->GetSession()->GetTimezoneOffset();
MailDraft(AuctionHouseMgr::BuildItemAuctionMailSubject(AuctionMailType::Invoice, auction),
AuctionHouseMgr::BuildAuctionInvoiceMailBody(auction->Bidder, auction->BidAmount, auction->BuyoutOrUnitPrice, auction->Deposit,
- CalculateAuctionHouseCut(auction->BidAmount), sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY), eta))
+ CalculateAuctionHouseCut(auction->BidAmount), sWorld->getIntConfig(CONFIG_MAIL_DELIVERY_DELAY), eta.GetPackedTime()))
.SendMailTo(trans, MailReceiver(owner, auction->Owner), this, MAIL_CHECK_MASK_COPIED);
}
}
diff --git a/src/server/game/Calendar/CalendarMgr.cpp b/src/server/game/Calendar/CalendarMgr.cpp
index fdceaa3762e..66f8ab9cb27 100644
--- a/src/server/game/Calendar/CalendarMgr.cpp
+++ b/src/server/game/Calendar/CalendarMgr.cpp
@@ -24,12 +24,16 @@
#include "GuildMgr.h"
#include "Log.h"
#include "Mail.h"
+#include "MapUtils.h"
#include "ObjectAccessor.h"
#include "Player.h"
+#include "StringConvert.h"
+#include "WorldSession.h"
+#include "WowTime.h"
#include <sstream>
CalendarInvite::CalendarInvite() : _inviteId(1), _eventId(0), _invitee(), _senderGUID(), _responseTime(0),
-_status(CALENDAR_STATUS_INVITED), _rank(CALENDAR_RANK_PLAYER), _note("") { }
+_status(CALENDAR_STATUS_INVITED), _rank(CALENDAR_RANK_PLAYER), _note() { }
CalendarInvite::~CalendarInvite()
{
@@ -184,7 +188,6 @@ void CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover)
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
CharacterDatabasePreparedStatement* stmt;
- MailDraft mail(calendarEvent->BuildCalendarMailSubject(remover), calendarEvent->BuildCalendarMailBody());
CalendarInviteStore& eventInvites = _invites[calendarEvent->GetEventId()];
for (size_t i = 0; i < eventInvites.size(); ++i)
@@ -197,7 +200,10 @@ void CalendarMgr::RemoveEvent(CalendarEvent* calendarEvent, ObjectGuid remover)
// guild events only? check invite status here?
// When an event is deleted, all invited (accepted/declined? - verify) guildies are notified via in-game mail. (wowwiki)
if (!remover.IsEmpty() && invite->GetInviteeGUID() != remover)
+ {
+ MailDraft mail(calendarEvent->BuildCalendarMailSubject(remover), calendarEvent->BuildCalendarMailBody(ObjectAccessor::FindConnectedPlayer(invite->GetInviteeGUID())));
mail.SendMailTo(trans, MailReceiver(invite->GetInviteeGUID().GetCounter()), calendarEvent, MAIL_CHECK_MASK_COPIED);
+ }
delete invite;
}
@@ -375,7 +381,7 @@ void CalendarMgr::DeleteOldEvents()
}
}
-CalendarEventStore CalendarMgr::GetEventsCreatedBy(ObjectGuid guid, bool includeGuildEvents)
+CalendarEventStore CalendarMgr::GetEventsCreatedBy(ObjectGuid guid, bool includeGuildEvents) const
{
CalendarEventStore result;
for (CalendarEventStore::const_iterator itr = _events.begin(); itr != _events.end(); ++itr)
@@ -385,7 +391,7 @@ CalendarEventStore CalendarMgr::GetEventsCreatedBy(ObjectGuid guid, bool include
return result;
}
-CalendarEventStore CalendarMgr::GetGuildEvents(ObjectGuid::LowType guildId)
+CalendarEventStore CalendarMgr::GetGuildEvents(ObjectGuid::LowType guildId) const
{
CalendarEventStore result;
@@ -400,7 +406,7 @@ CalendarEventStore CalendarMgr::GetGuildEvents(ObjectGuid::LowType guildId)
return result;
}
-CalendarEventStore CalendarMgr::GetPlayerEvents(ObjectGuid guid)
+CalendarEventStore CalendarMgr::GetPlayerEvents(ObjectGuid guid) const
{
CalendarEventStore events;
@@ -419,12 +425,16 @@ CalendarEventStore CalendarMgr::GetPlayerEvents(ObjectGuid guid)
return events;
}
-CalendarInviteStore const& CalendarMgr::GetEventInvites(uint64 eventId)
+CalendarInviteStore CalendarMgr::GetEventInvites(uint64 eventId) const
{
- return _invites[eventId];
+ CalendarInviteStore invites;
+ if (CalendarInviteStore const* invitesStore = Trinity::Containers::MapGetValuePtr(_invites, eventId))
+ invites = *invitesStore;
+
+ return invites;
}
-CalendarInviteStore CalendarMgr::GetPlayerInvites(ObjectGuid guid)
+CalendarInviteStore CalendarMgr::GetPlayerInvites(ObjectGuid guid) const
{
CalendarInviteStore invites;
@@ -465,20 +475,17 @@ std::string CalendarEvent::BuildCalendarMailSubject(ObjectGuid remover) const
return strm.str();
}
-std::string CalendarEvent::BuildCalendarMailBody() const
+std::string CalendarEvent::BuildCalendarMailBody(Player const* invitee) const
{
- WorldPacket data;
- uint32 time;
- std::ostringstream strm;
+ WowTime time;
+ time.SetUtcTimeFromUnixTime(_date);
+ if (invitee)
+ time += invitee->GetSession()->GetTimezoneOffset();
- // we are supposed to send PackedTime so i used WorldPacket to pack it
- data.AppendPackedTime(_date);
- data >> time;
- strm << time;
- return strm.str();
+ return Trinity::ToString(time.GetPackedTime());
}
-void CalendarMgr::SendCalendarEventInvite(CalendarInvite const& invite)
+void CalendarMgr::SendCalendarEventInvite(CalendarInvite const& invite) const
{
CalendarEvent* calendarEvent = GetEvent(invite.GetEventId());
@@ -487,71 +494,103 @@ void CalendarMgr::SendCalendarEventInvite(CalendarInvite const& invite)
uint8 level = player ? player->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(invitee);
- WorldPackets::Calendar::CalendarInviteAdded packet;
- packet.EventID = calendarEvent ? calendarEvent->GetEventId() : 0;
- packet.InviteGuid = invitee;
- packet.InviteID = calendarEvent ? invite.GetInviteId() : 0;
- packet.Level = level;
- packet.ResponseTime = invite.GetResponseTime();
- packet.Status = invite.GetStatus();
- packet.Type = calendarEvent ? calendarEvent->IsGuildEvent() : 0; // Correct ?
- packet.ClearPending = calendarEvent ? !calendarEvent->IsGuildEvent() : true; // Correct ?
+ auto packetBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Calendar::CalendarInviteAdded packet;
+ packet.EventID = calendarEvent ? calendarEvent->GetEventId() : 0;
+ packet.InviteGuid = invitee;
+ packet.InviteID = calendarEvent ? invite.GetInviteId() : 0;
+ packet.Level = level;
+ packet.ResponseTime.SetUtcTimeFromUnixTime(invite.GetResponseTime());
+ packet.ResponseTime += receiver->GetSession()->GetTimezoneOffset();
+ packet.Status = invite.GetStatus();
+ packet.Type = calendarEvent ? calendarEvent->IsGuildEvent() : 0; // Correct ?
+ packet.ClearPending = calendarEvent ? !calendarEvent->IsGuildEvent() : true; // Correct ?
+
+ receiver->SendDirectMessage(packet.Write());
+ };
if (!calendarEvent) // Pre-invite
{
if (Player* playerSender = ObjectAccessor::FindConnectedPlayer(invite.GetSenderGUID()))
- playerSender->SendDirectMessage(packet.Write());
+ packetBuilder(playerSender);
}
else
{
if (calendarEvent->GetOwnerGUID() != invite.GetInviteeGUID()) // correct?
- SendPacketToAllEventRelatives(packet.Write(), *calendarEvent);
+ for (Player* receiver : GetAllEventRelatives(*calendarEvent))
+ packetBuilder(receiver);
}
}
-void CalendarMgr::SendCalendarEventUpdateAlert(CalendarEvent const& calendarEvent, time_t originalDate)
+void CalendarMgr::SendCalendarEventUpdateAlert(CalendarEvent const& calendarEvent, time_t originalDate) const
{
- WorldPackets::Calendar::CalendarEventUpdatedAlert packet;
- packet.ClearPending = true; // FIXME
- packet.Date = calendarEvent.GetDate();
- packet.Description = calendarEvent.GetDescription();
- packet.EventClubID = calendarEvent.GetGuildId();
- packet.EventID = calendarEvent.GetEventId();
- packet.EventName = calendarEvent.GetTitle();
- packet.EventType = calendarEvent.GetType();
- packet.Flags = calendarEvent.GetFlags();
- packet.LockDate = calendarEvent.GetLockDate(); // Always 0 ?
- packet.OriginalDate = originalDate;
- packet.TextureID = calendarEvent.GetTextureId();
+ auto packetBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Calendar::CalendarEventUpdatedAlert packet;
+ packet.ClearPending = true; // FIXME
+ packet.Date.SetUtcTimeFromUnixTime(calendarEvent.GetDate());
+ packet.Date += receiver->GetSession()->GetTimezoneOffset();
+ packet.Description = calendarEvent.GetDescription();
+ packet.EventClubID = calendarEvent.GetGuildId();
+ packet.EventID = calendarEvent.GetEventId();
+ packet.EventName = calendarEvent.GetTitle();
+ packet.EventType = calendarEvent.GetType();
+ packet.Flags = calendarEvent.GetFlags();
+ packet.LockDate.SetUtcTimeFromUnixTime(calendarEvent.GetLockDate()); // Always 0 ?
+ if (calendarEvent.GetLockDate())
+ packet.LockDate += receiver->GetSession()->GetTimezoneOffset();
+ packet.OriginalDate.SetUtcTimeFromUnixTime(originalDate);
+ packet.OriginalDate += receiver->GetSession()->GetTimezoneOffset();
+ packet.TextureID = calendarEvent.GetTextureId();
- SendPacketToAllEventRelatives(packet.Write(), calendarEvent);
+ receiver->SendDirectMessage(packet.Write());
+ };
+
+ for (Player* receiver : GetAllEventRelatives(calendarEvent))
+ packetBuilder(receiver);
}
-void CalendarMgr::SendCalendarEventStatus(CalendarEvent const& calendarEvent, CalendarInvite const& invite)
+void CalendarMgr::SendCalendarEventStatus(CalendarEvent const& calendarEvent, CalendarInvite const& invite) const
{
- WorldPackets::Calendar::CalendarInviteStatus packet;
- packet.ClearPending = true; // FIXME
- packet.Date = calendarEvent.GetDate();
- packet.EventID = calendarEvent.GetEventId();
- packet.Flags = calendarEvent.GetFlags();
- packet.InviteGuid = invite.GetInviteeGUID();
- packet.ResponseTime = invite.GetResponseTime();
- packet.Status = invite.GetStatus();
+ auto packetBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Calendar::CalendarInviteStatus packet;
+ packet.ClearPending = true; // FIXME
+ packet.Date.SetUtcTimeFromUnixTime(calendarEvent.GetDate());
+ packet.Date += receiver->GetSession()->GetTimezoneOffset();
+ packet.EventID = calendarEvent.GetEventId();
+ packet.Flags = calendarEvent.GetFlags();
+ packet.InviteGuid = invite.GetInviteeGUID();
+ packet.ResponseTime.SetUtcTimeFromUnixTime(invite.GetResponseTime());
+ packet.ResponseTime += receiver->GetSession()->GetTimezoneOffset();
+ packet.Status = invite.GetStatus();
- SendPacketToAllEventRelatives(packet.Write(), calendarEvent);
+ receiver->SendDirectMessage(packet.Write());
+ };
+
+ for (Player* receiver : GetAllEventRelatives(calendarEvent))
+ packetBuilder(receiver);
}
-void CalendarMgr::SendCalendarEventRemovedAlert(CalendarEvent const& calendarEvent)
+void CalendarMgr::SendCalendarEventRemovedAlert(CalendarEvent const& calendarEvent) const
{
- WorldPackets::Calendar::CalendarEventRemovedAlert packet;
- packet.ClearPending = true; // FIXME
- packet.Date = calendarEvent.GetDate();
- packet.EventID = calendarEvent.GetEventId();
+ auto packetBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Calendar::CalendarEventRemovedAlert packet;
+ packet.ClearPending = true; // FIXME
+ packet.Date.SetUtcTimeFromUnixTime(calendarEvent.GetDate());
+ packet.Date += receiver->GetSession()->GetTimezoneOffset();
+ packet.EventID = calendarEvent.GetEventId();
- SendPacketToAllEventRelatives(packet.Write(), calendarEvent);
+ receiver->SendDirectMessage(packet.Write());
+ };
+
+ for (Player* receiver : GetAllEventRelatives(calendarEvent))
+ packetBuilder(receiver);
}
-void CalendarMgr::SendCalendarEventInviteRemove(CalendarEvent const& calendarEvent, CalendarInvite const& invite, uint32 flags)
+void CalendarMgr::SendCalendarEventInviteRemove(CalendarEvent const& calendarEvent, CalendarInvite const& invite, uint32 flags) const
{
WorldPackets::Calendar::CalendarInviteRemoved packet;
packet.ClearPending = true; // FIXME
@@ -562,7 +601,7 @@ void CalendarMgr::SendCalendarEventInviteRemove(CalendarEvent const& calendarEve
SendPacketToAllEventRelatives(packet.Write(), calendarEvent);
}
-void CalendarMgr::SendCalendarEventModeratorStatusAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite)
+void CalendarMgr::SendCalendarEventModeratorStatusAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite) const
{
WorldPackets::Calendar::CalendarModeratorStatus packet;
packet.ClearPending = true; // FIXME
@@ -573,82 +612,94 @@ void CalendarMgr::SendCalendarEventModeratorStatusAlert(CalendarEvent const& cal
SendPacketToAllEventRelatives(packet.Write(), calendarEvent);
}
-void CalendarMgr::SendCalendarEventInviteAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite)
+void CalendarMgr::SendCalendarEventInviteAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite) const
{
- WorldPackets::Calendar::CalendarInviteAlert packet;
- packet.Date = calendarEvent.GetDate();
- packet.EventID = calendarEvent.GetEventId();
- packet.EventName = calendarEvent.GetTitle();
- packet.EventType = calendarEvent.GetType();
- packet.Flags = calendarEvent.GetFlags();
- packet.InviteID = invite.GetInviteId();
- packet.InvitedByGuid = invite.GetSenderGUID();
- packet.ModeratorStatus = invite.GetRank();
- packet.OwnerGuid = calendarEvent.GetOwnerGUID();
- packet.Status = invite.GetStatus();
- packet.TextureID = calendarEvent.GetTextureId();
- packet.EventClubID = calendarEvent.GetGuildId();
+ auto packetBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Calendar::CalendarInviteAlert packet;
+ packet.Date.SetUtcTimeFromUnixTime(calendarEvent.GetDate());
+ packet.Date += receiver->GetSession()->GetTimezoneOffset();
+ packet.EventID = calendarEvent.GetEventId();
+ packet.EventName = calendarEvent.GetTitle();
+ packet.EventType = calendarEvent.GetType();
+ packet.Flags = calendarEvent.GetFlags();
+ packet.InviteID = invite.GetInviteId();
+ packet.InvitedByGuid = invite.GetSenderGUID();
+ packet.ModeratorStatus = invite.GetRank();
+ packet.OwnerGuid = calendarEvent.GetOwnerGUID();
+ packet.Status = invite.GetStatus();
+ packet.TextureID = calendarEvent.GetTextureId();
+ packet.EventClubID = calendarEvent.GetGuildId();
+
+ receiver->SendDirectMessage(packet.Write());
+ };
if (calendarEvent.IsGuildEvent() || calendarEvent.IsGuildAnnouncement())
{
if (Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId()))
- guild->BroadcastPacket(packet.Write());
+ guild->BroadcastWorker(packetBuilder);
}
else if (Player* player = ObjectAccessor::FindConnectedPlayer(invite.GetInviteeGUID()))
- player->SendDirectMessage(packet.Write());
+ packetBuilder(player);
}
-void CalendarMgr::SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarSendEventType sendType)
+void CalendarMgr::SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarSendEventType sendType) const
{
Player* player = ObjectAccessor::FindConnectedPlayer(guid);
if (!player)
return;
- CalendarInviteStore const& eventInviteeList = _invites[calendarEvent.GetEventId()];
-
WorldPackets::Calendar::CalendarSendEvent packet;
- packet.Date = calendarEvent.GetDate();
+ packet.Date.SetUtcTimeFromUnixTime(calendarEvent.GetDate());
+ packet.Date += player->GetSession()->GetTimezoneOffset();
packet.Description = calendarEvent.GetDescription();
packet.EventID = calendarEvent.GetEventId();
packet.EventName = calendarEvent.GetTitle();
packet.EventType = sendType;
packet.Flags = calendarEvent.GetFlags();
packet.GetEventType = calendarEvent.GetType();
- packet.LockDate = calendarEvent.GetLockDate(); // Always 0 ?
+ packet.LockDate.SetUtcTimeFromUnixTime(calendarEvent.GetLockDate()); // Always 0 ?
+ if (calendarEvent.GetLockDate())
+ packet.LockDate += player->GetSession()->GetTimezoneOffset();
packet.OwnerGuid = calendarEvent.GetOwnerGUID();
packet.TextureID = calendarEvent.GetTextureId();
packet.EventClubID = calendarEvent.GetGuildId();
- for (auto const& calendarInvite : eventInviteeList)
+ if (CalendarInviteStore const* eventInviteeList = Trinity::Containers::MapGetValuePtr(_invites, calendarEvent.GetEventId()))
{
- ObjectGuid inviteeGuid = calendarInvite->GetInviteeGUID();
- Player* invitee = ObjectAccessor::FindPlayer(inviteeGuid);
-
- uint8 inviteeLevel = invitee ? invitee->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(inviteeGuid);
- ObjectGuid::LowType inviteeGuildId = invitee ? invitee->GetGuildId() : sCharacterCache->GetCharacterGuildIdByGuid(inviteeGuid);
-
- WorldPackets::Calendar::CalendarEventInviteInfo inviteInfo;
- inviteInfo.Guid = inviteeGuid;
- inviteInfo.Level = inviteeLevel;
- inviteInfo.Status = calendarInvite->GetStatus();
- inviteInfo.Moderator = calendarInvite->GetRank();
- inviteInfo.InviteType = calendarEvent.IsGuildEvent() && calendarEvent.GetGuildId() == inviteeGuildId;
- inviteInfo.InviteID = calendarInvite->GetInviteId();
- inviteInfo.ResponseTime = calendarInvite->GetResponseTime();
- inviteInfo.Notes = calendarInvite->GetNote();
-
- packet.Invites.push_back(inviteInfo);
+ for (CalendarInvite const* calendarInvite : *eventInviteeList)
+ {
+ ObjectGuid inviteeGuid = calendarInvite->GetInviteeGUID();
+ Player* invitee = ObjectAccessor::FindPlayer(inviteeGuid);
+
+ uint8 inviteeLevel = invitee ? invitee->GetLevel() : sCharacterCache->GetCharacterLevelByGuid(inviteeGuid);
+ ObjectGuid::LowType inviteeGuildId = invitee ? invitee->GetGuildId() : sCharacterCache->GetCharacterGuildIdByGuid(inviteeGuid);
+
+ WorldPackets::Calendar::CalendarEventInviteInfo inviteInfo;
+ inviteInfo.Guid = inviteeGuid;
+ inviteInfo.Level = inviteeLevel;
+ inviteInfo.Status = calendarInvite->GetStatus();
+ inviteInfo.Moderator = calendarInvite->GetRank();
+ inviteInfo.InviteType = calendarEvent.IsGuildEvent() && calendarEvent.GetGuildId() == inviteeGuildId;
+ inviteInfo.InviteID = calendarInvite->GetInviteId();
+ inviteInfo.ResponseTime.SetUtcTimeFromUnixTime(calendarInvite->GetResponseTime());
+ inviteInfo.ResponseTime += player->GetSession()->GetTimezoneOffset();
+ inviteInfo.Notes = calendarInvite->GetNote();
+
+ packet.Invites.push_back(inviteInfo);
+ }
}
player->SendDirectMessage(packet.Write());
}
-void CalendarMgr::SendCalendarEventInviteRemoveAlert(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarInviteStatus status)
+void CalendarMgr::SendCalendarEventInviteRemoveAlert(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarInviteStatus status) const
{
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
{
WorldPackets::Calendar::CalendarInviteRemovedAlert packet;
- packet.Date = calendarEvent.GetDate();
+ packet.Date.SetUtcTimeFromUnixTime(calendarEvent.GetDate());
+ packet.Date += player->GetSession()->GetTimezoneOffset();
packet.EventID = calendarEvent.GetEventId();
packet.Flags = calendarEvent.GetFlags();
packet.Status = status;
@@ -657,13 +708,13 @@ void CalendarMgr::SendCalendarEventInviteRemoveAlert(ObjectGuid guid, CalendarEv
}
}
-void CalendarMgr::SendCalendarClearPendingAction(ObjectGuid guid)
+void CalendarMgr::SendCalendarClearPendingAction(ObjectGuid guid) const
{
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
player->SendDirectMessage(WorldPackets::Calendar::CalendarClearPendingAction().Write());
}
-void CalendarMgr::SendCalendarCommandResult(ObjectGuid guid, CalendarError err, char const* param /*= nullptr*/)
+void CalendarMgr::SendCalendarCommandResult(ObjectGuid guid, CalendarError err, char const* param /*= nullptr*/) const
{
if (Player* player = ObjectAccessor::FindConnectedPlayer(guid))
{
@@ -686,17 +737,35 @@ void CalendarMgr::SendCalendarCommandResult(ObjectGuid guid, CalendarError err,
}
}
-void CalendarMgr::SendPacketToAllEventRelatives(WorldPacket const* packet, CalendarEvent const& calendarEvent)
+void CalendarMgr::SendPacketToAllEventRelatives(WorldPacket const* packet, CalendarEvent const& calendarEvent) const
{
+ for (Player* player : GetAllEventRelatives(calendarEvent))
+ player->SendDirectMessage(packet);
+}
+
+std::vector<Player*> CalendarMgr::GetAllEventRelatives(CalendarEvent const& calendarEvent) const
+{
+ std::vector<Player*> relatedPlayers;
+
// Send packet to all guild members
if (calendarEvent.IsGuildEvent() || calendarEvent.IsGuildAnnouncement())
+ {
if (Guild* guild = sGuildMgr->GetGuildById(calendarEvent.GetGuildId()))
- guild->BroadcastPacket(packet);
+ {
+ auto memberCollector = [&](Player* player) { relatedPlayers.push_back(player); };
+ guild->BroadcastWorker(memberCollector);
+ }
+ }
// Send packet to all invitees if event is non-guild, in other case only to non-guild invitees (packet was broadcasted for them)
- CalendarInviteStore invites = _invites[calendarEvent.GetEventId()];
- for (CalendarInviteStore::iterator itr = invites.begin(); itr != invites.end(); ++itr)
- if (Player* player = ObjectAccessor::FindConnectedPlayer((*itr)->GetInviteeGUID()))
- if (!calendarEvent.IsGuildEvent() || player->GetGuildId() != calendarEvent.GetGuildId())
- player->SendDirectMessage(packet);
+ if (auto itr =_invites.find(calendarEvent.GetEventId()); itr != _invites.end())
+ {
+ CalendarInviteStore invites = itr->second;
+ for (CalendarInvite const* invite : invites)
+ if (Player* player = ObjectAccessor::FindConnectedPlayer(invite->GetInviteeGUID()))
+ if (!calendarEvent.IsGuildEvent() || player->GetGuildId() != calendarEvent.GetGuildId())
+ relatedPlayers.push_back(player);
+ }
+
+ return relatedPlayers;
}
diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h
index e9119fc510f..7f0a33be1bc 100644
--- a/src/server/game/Calendar/CalendarMgr.h
+++ b/src/server/game/Calendar/CalendarMgr.h
@@ -26,6 +26,7 @@
#include <set>
#include <vector>
+class Player;
class WorldPacket;
enum CalendarMailAnswers
@@ -159,7 +160,13 @@ struct TC_GAME_API CalendarInvite
CalendarInvite(uint64 inviteId, uint64 eventId, ObjectGuid invitee, ObjectGuid senderGUID, time_t responseTime,
CalendarInviteStatus status, CalendarModerationRank rank, std::string note) :
_inviteId(inviteId), _eventId(eventId), _invitee(invitee), _senderGUID(senderGUID), _responseTime(responseTime),
- _status(status), _rank(rank), _note(note) { }
+ _status(status), _rank(rank), _note(std::move(note)) { }
+
+ CalendarInvite(CalendarInvite const&) = delete;
+ CalendarInvite(CalendarInvite&&) = delete;
+
+ CalendarInvite& operator=(CalendarInvite const&) = delete;
+ CalendarInvite& operator=(CalendarInvite&&) = delete;
~CalendarInvite();
@@ -218,10 +225,16 @@ struct TC_GAME_API CalendarEvent
CalendarEvent(uint64 eventId, ObjectGuid ownerGUID, ObjectGuid::LowType guildId, CalendarEventType type, int32 textureId,
time_t date, uint32 flags, std::string title, std::string description, time_t lockDate) :
_eventId(eventId), _ownerGUID(ownerGUID), _eventGuildId(guildId), _eventType(type), _textureId(textureId),
- _date(date), _flags(flags), _title(title), _description(description), _lockDate(lockDate) { }
+ _date(date), _flags(flags), _title(std::move(title)), _description(std::move(description)), _lockDate(lockDate) { }
CalendarEvent() : _eventId(1), _ownerGUID(), _eventGuildId(UI64LIT(0)), _eventType(CALENDAR_TYPE_OTHER), _textureId(-1), _date(0),
- _flags(0), _title(""), _description(""), _lockDate(0) { }
+ _flags(0), _title(), _description(), _lockDate(0) { }
+
+ CalendarEvent(CalendarEvent const&) = delete;
+ CalendarEvent(CalendarEvent&&) = delete;
+
+ CalendarEvent& operator=(CalendarEvent const&) = delete;
+ CalendarEvent& operator=(CalendarEvent&&) = delete;
~CalendarEvent();
@@ -263,7 +276,7 @@ struct TC_GAME_API CalendarEvent
static bool IsGuildAnnouncement(uint32 flags) { return (flags & CALENDAR_FLAG_WITHOUT_INVITES) != 0; }
std::string BuildCalendarMailSubject(ObjectGuid remover) const;
- std::string BuildCalendarMailBody() const;
+ std::string BuildCalendarMailBody(Player const* invitee) const;
private:
uint64 _eventId;
@@ -296,20 +309,26 @@ class TC_GAME_API CalendarMgr
uint64 _maxInviteId;
public:
+ CalendarMgr(CalendarMgr const&) = delete;
+ CalendarMgr(CalendarMgr&&) = delete;
+
+ CalendarMgr& operator=(CalendarMgr const&) = delete;
+ CalendarMgr& operator=(CalendarMgr&&) = delete;
+
static CalendarMgr* instance();
void LoadFromDB();
CalendarEvent* GetEvent(uint64 eventId) const;
CalendarEventStore const& GetEvents() const { return _events; }
- CalendarEventStore GetEventsCreatedBy(ObjectGuid guid, bool includeGuildEvents = false);
- CalendarEventStore GetPlayerEvents(ObjectGuid guid);
- CalendarEventStore GetGuildEvents(ObjectGuid::LowType guildId);
+ CalendarEventStore GetEventsCreatedBy(ObjectGuid guid, bool includeGuildEvents = false) const;
+ CalendarEventStore GetPlayerEvents(ObjectGuid guid) const;
+ CalendarEventStore GetGuildEvents(ObjectGuid::LowType guildId) const;
CalendarInvite* GetInvite(uint64 inviteId) const;
CalendarEventInviteStore const& GetInvites() const { return _invites; }
- CalendarInviteStore const& GetEventInvites(uint64 eventId);
- CalendarInviteStore GetPlayerInvites(ObjectGuid guid);
+ CalendarInviteStore GetEventInvites(uint64 eventId) const;
+ CalendarInviteStore GetPlayerInvites(ObjectGuid guid) const;
void FreeEventId(uint64 id);
uint64 GetFreeEventId();
@@ -332,19 +351,20 @@ class TC_GAME_API CalendarMgr
void RemoveAllPlayerEventsAndInvites(ObjectGuid guid);
void RemovePlayerGuildEventsAndSignups(ObjectGuid guid, ObjectGuid::LowType guildId);
- void SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarSendEventType sendType);
- void SendCalendarEventInvite(CalendarInvite const& invite);
- void SendCalendarEventInviteAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite);
- void SendCalendarEventInviteRemove(CalendarEvent const& calendarEvent, CalendarInvite const& invite, uint32 flags);
- void SendCalendarEventInviteRemoveAlert(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarInviteStatus status);
- void SendCalendarEventUpdateAlert(CalendarEvent const& calendarEvent, time_t originalDate);
- void SendCalendarEventStatus(CalendarEvent const& calendarEvent, CalendarInvite const& invite);
- void SendCalendarEventRemovedAlert(CalendarEvent const& calendarEvent);
- void SendCalendarEventModeratorStatusAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite);
- void SendCalendarClearPendingAction(ObjectGuid guid);
- void SendCalendarCommandResult(ObjectGuid guid, CalendarError err, char const* param = nullptr);
-
- void SendPacketToAllEventRelatives(WorldPacket const* packet, CalendarEvent const& calendarEvent);
+ void SendCalendarEvent(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarSendEventType sendType) const;
+ void SendCalendarEventInvite(CalendarInvite const& invite) const;
+ void SendCalendarEventInviteAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite) const;
+ void SendCalendarEventInviteRemove(CalendarEvent const& calendarEvent, CalendarInvite const& invite, uint32 flags) const;
+ void SendCalendarEventInviteRemoveAlert(ObjectGuid guid, CalendarEvent const& calendarEvent, CalendarInviteStatus status) const;
+ void SendCalendarEventUpdateAlert(CalendarEvent const& calendarEvent, time_t originalDate) const;
+ void SendCalendarEventStatus(CalendarEvent const& calendarEvent, CalendarInvite const& invite) const;
+ void SendCalendarEventRemovedAlert(CalendarEvent const& calendarEvent) const;
+ void SendCalendarEventModeratorStatusAlert(CalendarEvent const& calendarEvent, CalendarInvite const& invite) const;
+ void SendCalendarClearPendingAction(ObjectGuid guid) const;
+ void SendCalendarCommandResult(ObjectGuid guid, CalendarError err, char const* param = nullptr) const;
+
+ void SendPacketToAllEventRelatives(WorldPacket const* packet, CalendarEvent const& calendarEvent) const;
+ std::vector<Player*> GetAllEventRelatives(CalendarEvent const& calendarEvent) const;
};
#define sCalendarMgr CalendarMgr::instance()
diff --git a/src/server/game/Conditions/ConditionMgr.cpp b/src/server/game/Conditions/ConditionMgr.cpp
index 0c59309bbb7..a7a74704a5d 100644
--- a/src/server/game/Conditions/ConditionMgr.cpp
+++ b/src/server/game/Conditions/ConditionMgr.cpp
@@ -19,12 +19,12 @@
#include "AchievementMgr.h"
#include "AreaTrigger.h"
#include "AreaTriggerDataStore.h"
-#include "Battleground.h"
#include "BattlePetMgr.h"
+#include "Battleground.h"
#include "Containers.h"
#include "ConversationDataStore.h"
-#include "DatabaseEnv.h"
#include "DB2Stores.h"
+#include "DatabaseEnv.h"
#include "GameEventMgr.h"
#include "GameObject.h"
#include "GameTime.h"
@@ -32,8 +32,8 @@
#include "InstanceScenario.h"
#include "InstanceScript.h"
#include "Item.h"
-#include "LanguageMgr.h"
#include "LFGMgr.h"
+#include "LanguageMgr.h"
#include "Log.h"
#include "LootMgr.h"
#include "Map.h"
@@ -53,6 +53,7 @@
#include "World.h"
#include "WorldSession.h"
#include "WorldStateMgr.h"
+#include "WowTime.h"
#include <random>
#include <sstream>
@@ -3239,15 +3240,18 @@ bool ConditionMgr::IsPlayerMeetingCondition(Player const* player, PlayerConditio
if (condition->Time[0])
{
- ByteBuffer unpacker;
- unpacker << condition->Time[0];
- time_t from = unpacker.ReadPackedTime();
- unpacker.rpos(0);
- unpacker.wpos(0);
- unpacker << condition->Time[1];
- time_t to = unpacker.ReadPackedTime();
+ WowTime time0;
+ time0.SetPackedTime(condition->Time[0]);
+
+ if (condition->Time[1])
+ {
+ WowTime time1;
+ time1.SetPackedTime(condition->Time[1]);
- if (GameTime::GetGameTime() < from || GameTime::GetGameTime() > to)
+ if (!GameTime::GetWowTime()->IsInRange(time0, time1))
+ return false;
+ }
+ else if (*GameTime::GetWowTime() != time0)
return false;
}
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index a93c6444d3b..531a103cc30 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -23354,8 +23354,8 @@ void Player::SendInitialPacketsBeforeAddToMap()
static float const TimeSpeed = 0.01666667f;
WorldPackets::Misc::LoginSetTimeSpeed loginSetTimeSpeed;
loginSetTimeSpeed.NewSpeed = TimeSpeed;
- loginSetTimeSpeed.GameTime = GameTime::GetGameTime();
- loginSetTimeSpeed.ServerTime = GameTime::GetGameTime();
+ loginSetTimeSpeed.GameTime = *GameTime::GetWowTime();
+ loginSetTimeSpeed.ServerTime = *GameTime::GetWowTime();
loginSetTimeSpeed.GameTimeHolidayOffset = 0; /// @todo
loginSetTimeSpeed.ServerTimeHolidayOffset = 0; /// @todo
SendDirectMessage(loginSetTimeSpeed.Write());
diff --git a/src/server/game/Guilds/Guild.cpp b/src/server/game/Guilds/Guild.cpp
index 035d8e00f3e..9874302350d 100644
--- a/src/server/game/Guilds/Guild.cpp
+++ b/src/server/game/Guilds/Guild.cpp
@@ -226,7 +226,7 @@ void Guild::NewsLogEntry::WritePacket(WorldPackets::Guild::GuildNews& newsPacket
WorldPackets::Guild::GuildNewsEvent newsEvent;
newsEvent.Id = int32(GetGUID());
newsEvent.MemberGuid = GetPlayerGuid();
- newsEvent.CompletedDate = uint32(GetTimestamp());
+ newsEvent.CompletedDate.SetUtcTimeFromUnixTime(GetTimestamp());
newsEvent.Flags = int32(GetFlags());
newsEvent.Type = int32(GetType());
@@ -1306,7 +1306,8 @@ void Guild::HandleRoster(WorldSession* session)
WorldPackets::Guild::GuildRoster roster;
roster.NumAccounts = int32(m_accountsNumber);
- roster.CreateDate = uint32(m_createdDate);
+ roster.CreateDate.SetUtcTimeFromUnixTime(m_createdDate);
+ roster.CreateDate += session->GetTimezoneOffset();
roster.GuildFlags = 0;
roster.MemberData.reserve(m_members.size());
@@ -2183,7 +2184,10 @@ void Guild::SendNewsUpdate(WorldSession* session) const
packet.NewsEvents.reserve(newsLog.size());
for (NewsLogEntry const& newsLogEntry : newsLog)
+ {
newsLogEntry.WritePacket(packet);
+ packet.NewsEvents.back().CompletedDate += session->GetTimezoneOffset();
+ }
session->SendPacket(packet.Write());
@@ -2688,12 +2692,15 @@ void Guild::BroadcastPacket(WorldPacket const* packet) const
player->SendDirectMessage(packet);
}
-void Guild::BroadcastPacketIfTrackingAchievement(WorldPacket const* packet, uint32 criteriaId) const
+std::vector<Player*> Guild::GetMembersTrackingCriteria(uint32 criteriaId) const
{
+ std::vector<Player*> members;
for (auto const& [guid, member] : m_members)
if (member.IsTrackingCriteriaId(criteriaId))
if (Player* player = member.FindPlayer())
- player->GetSession()->SendPacket(packet);
+ members.push_back(player);
+
+ return members;
}
void Guild::MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 maxLevel, GuildRankOrder minRank)
@@ -3599,10 +3606,16 @@ void Guild::AddGuildNews(uint8 type, ObjectGuid guid, uint32 flags, uint32 value
NewsLogEntry& news = m_newsLog.AddEvent(trans, m_id, m_newsLog.GetNextGUID(), GuildNews(type), guid, flags, value);
CharacterDatabase.CommitTransaction(trans);
- WorldPackets::Guild::GuildNews newsPacket;
- newsPacket.NewsEvents.reserve(1);
- news.WritePacket(newsPacket);
- BroadcastPacket(newsPacket.Write());
+ auto packetBuilder = [&](Player const* receiver)
+ {
+ WorldPackets::Guild::GuildNews newsPacket;
+ newsPacket.NewsEvents.reserve(1);
+ news.WritePacket(newsPacket);
+ newsPacket.NewsEvents.back().CompletedDate += receiver->GetSession()->GetTimezoneOffset();
+
+ receiver->SendDirectMessage(newsPacket.Write());
+ };
+ BroadcastWorker(packetBuilder);
}
bool Guild::HasAchieved(uint32 achievementId) const
@@ -3637,5 +3650,6 @@ void Guild::HandleNewsSetSticky(WorldSession* session, uint32 newsId, bool stick
WorldPackets::Guild::GuildNews newsPacket;
newsPacket.NewsEvents.reserve(1);
itr->WritePacket(newsPacket);
+ newsPacket.NewsEvents.back().CompletedDate += session->GetTimezoneOffset();
session->SendPacket(newsPacket.Write());
}
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index bdbd05503c4..071e2c881da 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -810,7 +810,6 @@ class TC_GAME_API Guild
void BroadcastAddonToGuild(WorldSession* session, bool officerOnly, std::string_view msg, std::string_view prefix, bool isLogged) const;
void BroadcastPacketToRank(WorldPacket const* packet, GuildRankId rankId) const;
void BroadcastPacket(WorldPacket const* packet) const;
- void BroadcastPacketIfTrackingAchievement(WorldPacket const* packet, uint32 criteriaId) const;
void MassInviteToEvent(WorldSession* session, uint32 minLevel, uint32 maxLevel, GuildRankOrder minRank);
@@ -831,6 +830,7 @@ class TC_GAME_API Guild
bool IsMember(ObjectGuid guid) const;
uint32 GetMembersCount() const { return uint32(m_members.size()); }
uint64 GetMemberAvailableMoneyForRepairItems(ObjectGuid guid) const;
+ std::vector<Player*> GetMembersTrackingCriteria(uint32 criteriaId) const;
// Bank
void SwapItems(Player* player, uint8 tabId, uint8 slotId, uint8 destTabId, uint8 destSlotId, uint32 splitedAmount);
diff --git a/src/server/game/Handlers/AuthHandler.cpp b/src/server/game/Handlers/AuthHandler.cpp
index 7be557d368b..13db0718450 100644
--- a/src/server/game/Handlers/AuthHandler.cpp
+++ b/src/server/game/Handlers/AuthHandler.cpp
@@ -26,6 +26,7 @@
#include "RBAC.h"
#include "Realm.h"
#include "SystemPackets.h"
+#include "Timezone.h"
#include "World.h"
void WorldSession::SendAuthResponse(uint32 code, bool queued, uint32 queuePos)
@@ -89,12 +90,14 @@ void WorldSession::SendClientCacheVersion(uint32 version)
void WorldSession::SendSetTimeZoneInformation()
{
- /// @todo: replace dummy values
- WorldPackets::System::SetTimeZoneInformation packet;
- packet.ServerTimeTZ = "Europe/Paris";
- packet.GameTimeTZ = "Europe/Paris";
- packet.ServerRegionalTZ = "Europe/Paris";
+ Minutes timezoneOffset = Trinity::Timezone::GetSystemZoneOffset(false);
+ std::string realTimezone = Trinity::Timezone::GetSystemZoneName();
+ std::string_view clientSupportedTZ = Trinity::Timezone::FindClosestClientSupportedTimezone(realTimezone, timezoneOffset);
+ WorldPackets::System::SetTimeZoneInformation packet;
+ packet.ServerTimeTZ = clientSupportedTZ;
+ packet.GameTimeTZ = clientSupportedTZ;
+ packet.ServerRegionalTZ = clientSupportedTZ;
SendPacket(packet.Write());
}
diff --git a/src/server/game/Handlers/CalendarHandler.cpp b/src/server/game/Handlers/CalendarHandler.cpp
index 209babfec10..ab512f54eec 100644
--- a/src/server/game/Handlers/CalendarHandler.cpp
+++ b/src/server/game/Handlers/CalendarHandler.cpp
@@ -39,7 +39,6 @@ Copied events should probably have a new owner
#include "CalendarPackets.h"
#include "CharacterCache.h"
#include "DatabaseEnv.h"
-#include "DB2Stores.h"
#include "GameTime.h"
#include "Guild.h"
#include "GuildMgr.h"
@@ -49,16 +48,14 @@ Copied events should probably have a new owner
#include "ObjectMgr.h"
#include "Player.h"
#include "SocialMgr.h"
-#include "Util.h"
#include "World.h"
void WorldSession::HandleCalendarGetCalendar(WorldPackets::Calendar::CalendarGetCalendar& /*calendarGetCalendar*/)
{
ObjectGuid guid = _player->GetGUID();
- time_t currTime = GameTime::GetGameTime();
WorldPackets::Calendar::CalendarSendCalendar packet;
- packet.ServerTime = currTime;
+ packet.ServerTime = *GameTime::GetWowTime();
CalendarInviteStore playerInvites = sCalendarMgr->GetPlayerInvites(guid);
for (CalendarInvite const* invite : playerInvites)
@@ -78,7 +75,8 @@ void WorldSession::HandleCalendarGetCalendar(WorldPackets::Calendar::CalendarGet
{
WorldPackets::Calendar::CalendarSendCalendarEventInfo& eventInfo = packet.Events.emplace_back();
eventInfo.EventID = event->GetEventId();
- eventInfo.Date = event->GetDate();
+ eventInfo.Date.SetUtcTimeFromUnixTime(event->GetDate());
+ eventInfo.Date += GetTimezoneOffset();
eventInfo.EventClubID = event->GetGuildId();
eventInfo.EventName = event->GetTitle();
eventInfo.EventType = event->GetType();
@@ -117,11 +115,10 @@ void WorldSession::HandleCalendarAddEvent(WorldPackets::Calendar::CalendarAddEve
{
ObjectGuid guid = _player->GetGUID();
- calendarAddEvent.EventInfo.Time = uint32(LocalTimeToUTCTime(calendarAddEvent.EventInfo.Time));
+ calendarAddEvent.EventInfo.Time -= GetTimezoneOffset();
// prevent events in the past
- // To Do: properly handle timezones and remove the "- time_t(86400L)" hack
- if (calendarAddEvent.EventInfo.Time < (GameTime::GetGameTime() - time_t(86400L)))
+ if (calendarAddEvent.EventInfo.Time < *GameTime::GetUtcWowTime())
{
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_PASSED);
return;
@@ -163,7 +160,7 @@ void WorldSession::HandleCalendarAddEvent(WorldPackets::Calendar::CalendarAddEve
SetCalendarEventCreationCooldown(GameTime::GetGameTime() + CALENDAR_CREATE_EVENT_COOLDOWN);
CalendarEvent* calendarEvent = new CalendarEvent(sCalendarMgr->GetFreeEventId(), guid, UI64LIT(0), CalendarEventType(calendarAddEvent.EventInfo.EventType), calendarAddEvent.EventInfo.TextureID,
- calendarAddEvent.EventInfo.Time, calendarAddEvent.EventInfo.Flags, calendarAddEvent.EventInfo.Title, calendarAddEvent.EventInfo.Description, time_t(0));
+ calendarAddEvent.EventInfo.Time.GetUnixTimeFromUtcTime(), calendarAddEvent.EventInfo.Flags, calendarAddEvent.EventInfo.Title, calendarAddEvent.EventInfo.Description, time_t(0));
if (calendarEvent->IsGuildEvent() || calendarEvent->IsGuildAnnouncement())
calendarEvent->SetGuildId(_player->GetGuildId());
@@ -201,11 +198,10 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPackets::Calendar::CalendarUpd
ObjectGuid guid = _player->GetGUID();
time_t oldEventTime = time_t(0);
- calendarUpdateEvent.EventInfo.Time = uint32(LocalTimeToUTCTime(calendarUpdateEvent.EventInfo.Time));
+ calendarUpdateEvent.EventInfo.Time -= GetTimezoneOffset();
// prevent events in the past
- // To Do: properly handle timezones and remove the "- time_t(86400L)" hack
- if (calendarUpdateEvent.EventInfo.Time < (GameTime::GetGameTime() - time_t(86400L)))
+ if (calendarUpdateEvent.EventInfo.Time < *GameTime::GetUtcWowTime())
return;
if (CalendarEvent* calendarEvent = sCalendarMgr->GetEvent(calendarUpdateEvent.EventInfo.EventID))
@@ -214,7 +210,7 @@ void WorldSession::HandleCalendarUpdateEvent(WorldPackets::Calendar::CalendarUpd
calendarEvent->SetType(CalendarEventType(calendarUpdateEvent.EventInfo.EventType));
calendarEvent->SetFlags(calendarUpdateEvent.EventInfo.Flags);
- calendarEvent->SetDate(calendarUpdateEvent.EventInfo.Time);
+ calendarEvent->SetDate(calendarUpdateEvent.EventInfo.Time.GetUnixTimeFromUtcTime());
calendarEvent->SetTextureId(calendarUpdateEvent.EventInfo.TextureID);
calendarEvent->SetTitle(calendarUpdateEvent.EventInfo.Title);
calendarEvent->SetDescription(calendarUpdateEvent.EventInfo.Description);
@@ -236,11 +232,10 @@ void WorldSession::HandleCalendarCopyEvent(WorldPackets::Calendar::CalendarCopyE
{
ObjectGuid guid = _player->GetGUID();
- calendarCopyEvent.Date = uint32(LocalTimeToUTCTime(calendarCopyEvent.Date));
+ calendarCopyEvent.Date -= GetTimezoneOffset();
// prevent events in the past
- // To Do: properly handle timezones and remove the "- time_t(86400L)" hack
- if (calendarCopyEvent.Date < (GameTime::GetGameTime() - time_t(86400L)))
+ if (calendarCopyEvent.Date < *GameTime::GetUtcWowTime())
{
sCalendarMgr->SendCalendarCommandResult(guid, CALENDAR_ERROR_EVENT_PASSED);
return;
@@ -292,7 +287,7 @@ void WorldSession::HandleCalendarCopyEvent(WorldPackets::Calendar::CalendarCopyE
SetCalendarEventCreationCooldown(GameTime::GetGameTime() + CALENDAR_CREATE_EVENT_COOLDOWN);
CalendarEvent* newEvent = new CalendarEvent(*oldEvent, sCalendarMgr->GetFreeEventId());
- newEvent->SetDate(calendarCopyEvent.Date);
+ newEvent->SetDate(calendarCopyEvent.Date.GetUnixTimeFromUtcTime());
sCalendarMgr->AddEvent(newEvent, CALENDAR_SENDTYPE_COPY);
CalendarInviteStore invites = sCalendarMgr->GetEventInvites(calendarCopyEvent.EventID);
@@ -550,7 +545,7 @@ void WorldSession::HandleSetSavedInstanceExtend(WorldPackets::Calendar::SetSaved
return;
WorldPackets::Calendar::CalendarRaidLockoutUpdated calendarRaidLockoutUpdated;
- calendarRaidLockoutUpdated.ServerTime = GameTime::GetGameTime();
+ calendarRaidLockoutUpdated.ServerTime = *GameTime::GetWowTime();
calendarRaidLockoutUpdated.MapID = setSavedInstanceExtend.MapID;
calendarRaidLockoutUpdated.DifficultyID = setSavedInstanceExtend.DifficultyID;
calendarRaidLockoutUpdated.OldTimeRemaining = std::max(std::chrono::duration_cast<Seconds>(expiryTimes.first - GameTime::GetSystemTime()).count(), SI64LIT(0));
diff --git a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
index a72c213a042..798e90e6b26 100644
--- a/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
+++ b/src/server/game/Quests/QuestObjectiveCriteriaMgr.cpp
@@ -25,6 +25,7 @@
#include "Map.h"
#include "ObjectMgr.h"
#include "Player.h"
+#include "WorldSession.h"
QuestObjectiveCriteriaMgr::QuestObjectiveCriteriaMgr(Player* owner) : _owner(owner)
{
@@ -187,7 +188,8 @@ void QuestObjectiveCriteriaMgr::SendAllData(Player const* /*receiver*/) const
criteriaUpdate.PlayerGUID = _owner->GetGUID();
criteriaUpdate.Flags = 0;
- criteriaUpdate.CurrentTime = criteriaProgres.second.Date;
+ criteriaUpdate.CurrentTime.SetUtcTimeFromUnixTime(criteriaProgres.second.Date);
+ criteriaUpdate.CurrentTime += _owner->GetSession()->GetTimezoneOffset();
criteriaUpdate.CreationTime = 0;
SendPacket(criteriaUpdate.Write());
@@ -222,7 +224,8 @@ void QuestObjectiveCriteriaMgr::SendCriteriaUpdate(Criteria const* criteria, Cri
if (criteria->Entry->StartTimer)
criteriaUpdate.Flags = timedCompleted ? 1 : 0; // 1 is for keeping the counter at 0 in client
- criteriaUpdate.CurrentTime = progress->Date;
+ criteriaUpdate.CurrentTime.SetUtcTimeFromUnixTime(progress->Date);
+ criteriaUpdate.CurrentTime += _owner->GetSession()->GetTimezoneOffset();
criteriaUpdate.ElapsedTime = timeElapsed;
criteriaUpdate.CreationTime = 0;
diff --git a/src/server/game/Scenarios/Scenario.cpp b/src/server/game/Scenarios/Scenario.cpp
index 3366781ba39..ce994618d62 100644
--- a/src/server/game/Scenarios/Scenario.cpp
+++ b/src/server/game/Scenarios/Scenario.cpp
@@ -23,6 +23,7 @@
#include "Player.h"
#include "ScenarioMgr.h"
#include "ScenarioPackets.h"
+#include "WorldSession.h"
Scenario::Scenario(Map* map, ScenarioData const* scenarioData) : _map(map), _data(scenarioData),
_guid(ObjectGuid::Create<HighGuid::Scenario>(map->GetId(), scenarioData->Entry->ID, map->GenerateLowGuid<HighGuid::Scenario>())),
@@ -100,9 +101,12 @@ void Scenario::SetStep(ScenarioStepEntry const* step)
player->StartCriteria(CriteriaStartEvent::BeginScenarioStep, step->ID);
}
- WorldPackets::Scenario::ScenarioState scenarioState;
- BuildScenarioState(&scenarioState);
- SendPacket(scenarioState.Write());
+ DoForAllPlayers([&](Player const* receiver)
+ {
+ WorldPackets::Scenario::ScenarioState scenarioState;
+ BuildScenarioStateFor(receiver, &scenarioState);
+ receiver->SendDirectMessage(scenarioState.Write());
+ });
}
void Scenario::OnPlayerEnter(Player* player)
@@ -117,7 +121,7 @@ void Scenario::OnPlayerExit(Player* player)
SendBootPlayer(player);
}
-bool Scenario::IsComplete()
+bool Scenario::IsComplete() const
{
for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
{
@@ -136,7 +140,7 @@ ScenarioEntry const* Scenario::GetEntry() const
return _data->Entry;
}
-ScenarioStepState Scenario::GetStepState(ScenarioStepEntry const* step)
+ScenarioStepState Scenario::GetStepState(ScenarioStepEntry const* step) const
{
auto itr = _stepStates.find(step);
if (itr == _stepStates.end())
@@ -145,20 +149,24 @@ ScenarioStepState Scenario::GetStepState(ScenarioStepEntry const* step)
return itr->second;
}
-void Scenario::SendCriteriaUpdate(Criteria const * criteria, CriteriaProgress const * progress, Seconds timeElapsed, bool timedCompleted) const
+void Scenario::SendCriteriaUpdate(Criteria const* criteria, CriteriaProgress const* progress, Seconds timeElapsed, bool timedCompleted) const
{
- WorldPackets::Scenario::ScenarioProgressUpdate progressUpdate;
- progressUpdate.CriteriaProgress.Id = criteria->ID;
- progressUpdate.CriteriaProgress.Quantity = progress->Counter;
- progressUpdate.CriteriaProgress.Player = progress->PlayerGUID;
- progressUpdate.CriteriaProgress.Date = progress->Date;
- if (criteria->Entry->StartTimer)
- progressUpdate.CriteriaProgress.Flags = timedCompleted ? 1 : 0;
-
- progressUpdate.CriteriaProgress.TimeFromStart = timeElapsed;
- progressUpdate.CriteriaProgress.TimeFromCreate = Seconds::zero();
-
- SendPacket(progressUpdate.Write());
+ DoForAllPlayers([=](Player const* receiver)
+ {
+ WorldPackets::Scenario::ScenarioProgressUpdate progressUpdate;
+ progressUpdate.CriteriaProgress.Id = criteria->ID;
+ progressUpdate.CriteriaProgress.Quantity = progress->Counter;
+ progressUpdate.CriteriaProgress.Player = progress->PlayerGUID;
+ progressUpdate.CriteriaProgress.Date.SetUtcTimeFromUnixTime(progress->Date);
+ progressUpdate.CriteriaProgress.Date += receiver->GetSession()->GetTimezoneOffset();
+ if (criteria->Entry->StartTimer)
+ progressUpdate.CriteriaProgress.Flags = timedCompleted ? 1 : 0;
+
+ progressUpdate.CriteriaProgress.TimeFromStart = timeElapsed;
+ progressUpdate.CriteriaProgress.TimeFromCreate = Seconds::zero();
+
+ receiver->SendDirectMessage(progressUpdate.Write());
+ });
}
bool Scenario::CanUpdateCriteriaTree(Criteria const * /*criteria*/, CriteriaTree const * tree, Player * /*referencePlayer*/) const
@@ -220,20 +228,28 @@ bool Scenario::IsCompletedStep(ScenarioStepEntry const* step)
return IsCompletedCriteriaTree(tree);
}
-void Scenario::SendPacket(WorldPacket const* data) const
+void Scenario::DoForAllPlayers(std::function<void(Player*)> const& worker) const
{
for (ObjectGuid guid : _players)
if (Player* player = ObjectAccessor::GetPlayer(_map, guid))
- player->SendDirectMessage(data);
+ worker(player);
}
-void Scenario::BuildScenarioState(WorldPackets::Scenario::ScenarioState* scenarioState)
+void Scenario::SendPacket(WorldPacket const* data) const
+{
+ DoForAllPlayers([data](Player const* player)
+ {
+ player->SendDirectMessage(data);
+ });
+}
+
+void Scenario::BuildScenarioStateFor(Player const* player, WorldPackets::Scenario::ScenarioState* scenarioState) const
{
scenarioState->ScenarioGUID = _guid;
scenarioState->ScenarioID = _data->Entry->ID;
if (ScenarioStepEntry const* step = GetStep())
scenarioState->CurrentStep = step->ID;
- scenarioState->CriteriaProgress = GetCriteriasProgress();
+ scenarioState->CriteriaProgress = GetCriteriasProgressFor(player);
scenarioState->BonusObjectives = GetBonusObjectivesData();
// Don't know exactly what this is for, but seems to contain list of scenario steps that we're either on or that are completed
for (std::pair<ScenarioStepEntry const* const, ScenarioStepState> const& state : _stepStates)
@@ -288,14 +304,14 @@ ScenarioStepEntry const* Scenario::GetLastStep() const
return lastStep;
}
-void Scenario::SendScenarioState(Player* player)
+void Scenario::SendScenarioState(Player const* player) const
{
WorldPackets::Scenario::ScenarioState scenarioState;
- BuildScenarioState(&scenarioState);
+ BuildScenarioStateFor(player, &scenarioState);
player->SendDirectMessage(scenarioState.Write());
}
-std::vector<WorldPackets::Scenario::BonusObjectiveData> Scenario::GetBonusObjectivesData()
+std::vector<WorldPackets::Scenario::BonusObjectiveData> Scenario::GetBonusObjectivesData() const
{
std::vector<WorldPackets::Scenario::BonusObjectiveData> bonusObjectivesData;
for (std::pair<uint8 const, ScenarioStepEntry const*> const& scenarioStep : _data->Steps)
@@ -315,21 +331,18 @@ std::vector<WorldPackets::Scenario::BonusObjectiveData> Scenario::GetBonusObject
return bonusObjectivesData;
}
-std::vector<WorldPackets::Achievement::CriteriaProgress> Scenario::GetCriteriasProgress()
+std::vector<WorldPackets::Achievement::CriteriaProgress> Scenario::GetCriteriasProgressFor(Player const* player) const
{
std::vector<WorldPackets::Achievement::CriteriaProgress> criteriasProgress;
- if (!_criteriaProgress.empty())
+ for (auto const& [criteriaId, progress] : _criteriaProgress)
{
- for (std::pair<uint32 const, CriteriaProgress> const& progressPair : _criteriaProgress)
- {
- WorldPackets::Achievement::CriteriaProgress criteriaProgress;
- criteriaProgress.Id = progressPair.first;
- criteriaProgress.Quantity = progressPair.second.Counter;
- criteriaProgress.Date = progressPair.second.Date;
- criteriaProgress.Player = progressPair.second.PlayerGUID;
- criteriasProgress.push_back(criteriaProgress);
- }
+ WorldPackets::Achievement::CriteriaProgress& criteriaProgress = criteriasProgress.emplace_back();
+ criteriaProgress.Id = criteriaId;
+ criteriaProgress.Quantity = progress.Counter;
+ criteriaProgress.Date.SetUtcTimeFromUnixTime(progress.Date);
+ criteriaProgress.Date += player->GetSession()->GetTimezoneOffset();
+ criteriaProgress.Player = progress.PlayerGUID;
}
return criteriasProgress;
@@ -340,7 +353,7 @@ CriteriaList const& Scenario::GetCriteriaByType(CriteriaType type, uint32 /*asse
return sCriteriaMgr->GetScenarioCriteriaByTypeAndScenario(type, _data->Entry->ID);
}
-void Scenario::SendBootPlayer(Player* player)
+void Scenario::SendBootPlayer(Player const* player) const
{
WorldPackets::Scenario::ScenarioVacate scenarioBoot;
scenarioBoot.ScenarioGUID = _guid;
diff --git a/src/server/game/Scenarios/Scenario.h b/src/server/game/Scenarios/Scenario.h
index 7c632eca0cb..d70331adbdc 100644
--- a/src/server/game/Scenarios/Scenario.h
+++ b/src/server/game/Scenarios/Scenario.h
@@ -65,17 +65,17 @@ class TC_GAME_API Scenario : public CriteriaHandler
virtual void OnPlayerExit(Player* player);
virtual void Update(uint32 /*diff*/) { }
- bool IsComplete();
+ bool IsComplete() const;
bool IsCompletedStep(ScenarioStepEntry const* step);
void SetStepState(ScenarioStepEntry const* step, ScenarioStepState state) { _stepStates[step] = state; }
ScenarioEntry const* GetEntry() const;
- ScenarioStepState GetStepState(ScenarioStepEntry const* step);
+ ScenarioStepState GetStepState(ScenarioStepEntry const* step) const;
ScenarioStepEntry const* GetStep() const { return _currentstep; }
ScenarioStepEntry const* GetFirstStep() const;
ScenarioStepEntry const* GetLastStep() const;
- void SendScenarioState(Player* player);
- void SendBootPlayer(Player* player);
+ void SendScenarioState(Player const* player) const;
+ void SendBootPlayer(Player const* player) const;
protected:
Map const* _map;
@@ -89,14 +89,15 @@ class TC_GAME_API Scenario : public CriteriaHandler
void CompletedCriteriaTree(CriteriaTree const* tree, Player* referencePlayer) override;
void AfterCriteriaTreeUpdate(CriteriaTree const* /*tree*/, Player* /*referencePlayer*/) override { }
+ void DoForAllPlayers(std::function<void(Player*)> const& worker) const;
void SendPacket(WorldPacket const* data) const override;
void SendAllData(Player const* /*receiver*/) const override { }
- void BuildScenarioState(WorldPackets::Scenario::ScenarioState* scenarioState);
+ void BuildScenarioStateFor(Player const* player, WorldPackets::Scenario::ScenarioState* scenarioState) const;
- std::vector<WorldPackets::Scenario::BonusObjectiveData> GetBonusObjectivesData();
- std::vector<WorldPackets::Achievement::CriteriaProgress> GetCriteriasProgress();
+ std::vector<WorldPackets::Scenario::BonusObjectiveData> GetBonusObjectivesData() const;
+ std::vector<WorldPackets::Achievement::CriteriaProgress> GetCriteriasProgressFor(Player const* player) const;
CriteriaList const& GetCriteriaByType(CriteriaType type, uint32 asset) const override;
ScenarioData const* _data;
diff --git a/src/server/game/Server/Packets/AchievementPackets.cpp b/src/server/game/Server/Packets/AchievementPackets.cpp
index d158db68e60..cf8111ba8b4 100644
--- a/src/server/game/Server/Packets/AchievementPackets.cpp
+++ b/src/server/game/Server/Packets/AchievementPackets.cpp
@@ -17,24 +17,26 @@
#include "AchievementPackets.h"
-ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::EarnedAchievement const& earned)
+namespace WorldPackets::Achievement
+{
+ByteBuffer& operator<<(ByteBuffer& data, EarnedAchievement const& earned)
{
data << uint32(earned.Id);
- data.AppendPackedTime(earned.Date);
+ data << earned.Date;
data << earned.Owner;
data << uint32(earned.VirtualRealmAddress);
data << uint32(earned.NativeRealmAddress);
return data;
}
-ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::CriteriaProgress const& criteria)
+ByteBuffer& operator<<(ByteBuffer& data, CriteriaProgress const& criteria)
{
data << uint32(criteria.Id);
data << uint64(criteria.Quantity);
data << criteria.Player;
data << uint32(criteria.Unused_10_1_5);
data << uint32(criteria.Flags);
- data.AppendPackedTime(criteria.Date);
+ data << criteria.Date;
data << criteria.TimeFromStart;
data << criteria.TimeFromCreate;
data.WriteBit(criteria.RafAcceptanceID.has_value());
@@ -46,37 +48,37 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::CriteriaProg
return data;
}
-ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::AllAchievements const& allAchievements)
+ByteBuffer& operator<<(ByteBuffer& data, AllAchievements const& allAchievements)
{
data << uint32(allAchievements.Earned.size());
data << uint32(allAchievements.Progress.size());
- for (WorldPackets::Achievement::EarnedAchievement const& earned : allAchievements.Earned)
+ for (EarnedAchievement const& earned : allAchievements.Earned)
data << earned;
- for (WorldPackets::Achievement::CriteriaProgress const& progress : allAchievements.Progress)
+ for (CriteriaProgress const& progress : allAchievements.Progress)
data << progress;
return data;
}
-WorldPacket const* WorldPackets::Achievement::AllAchievementData::Write()
+WorldPacket const* AllAchievementData::Write()
{
_worldPacket << Data;
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::AllAccountCriteria::Write()
+WorldPacket const* AllAccountCriteria::Write()
{
_worldPacket << uint32(Progress.size());
- for (WorldPackets::Achievement::CriteriaProgress const& progress : Progress)
+ for (CriteriaProgress const& progress : Progress)
_worldPacket << progress;
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::RespondInspectAchievements::Write()
+WorldPacket const* RespondInspectAchievements::Write()
{
_worldPacket << Player;
_worldPacket << Data;
@@ -84,14 +86,14 @@ WorldPacket const* WorldPackets::Achievement::RespondInspectAchievements::Write(
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::CriteriaUpdate::Write()
+WorldPacket const* CriteriaUpdate::Write()
{
_worldPacket << uint32(CriteriaID);
_worldPacket << uint64(Quantity);
_worldPacket << PlayerGUID;
_worldPacket << uint32(Unused_10_1_5);
_worldPacket << uint32(Flags);
- _worldPacket.AppendPackedTime(CurrentTime);
+ _worldPacket << CurrentTime;
_worldPacket << ElapsedTime;
_worldPacket << CreationTime;
_worldPacket.WriteBit(RafAcceptanceID.has_value());
@@ -103,21 +105,21 @@ WorldPacket const* WorldPackets::Achievement::CriteriaUpdate::Write()
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::AccountCriteriaUpdate::Write()
+WorldPacket const* AccountCriteriaUpdate::Write()
{
_worldPacket << Progress;
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::CriteriaDeleted::Write()
+WorldPacket const* CriteriaDeleted::Write()
{
_worldPacket << uint32(CriteriaID);
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::AchievementDeleted::Write()
+WorldPacket const* AchievementDeleted::Write()
{
_worldPacket << uint32(AchievementID);
_worldPacket << uint32(Immunities);
@@ -125,12 +127,12 @@ WorldPacket const* WorldPackets::Achievement::AchievementDeleted::Write()
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::AchievementEarned::Write()
+WorldPacket const* AchievementEarned::Write()
{
_worldPacket << Sender;
_worldPacket << Earner;
_worldPacket << uint32(AchievementID);
- _worldPacket.AppendPackedTime(Time);
+ _worldPacket << Time;
_worldPacket << uint32(EarnerNativeRealm);
_worldPacket << uint32(EarnerVirtualRealm);
_worldPacket.WriteBit(Initial);
@@ -139,7 +141,7 @@ WorldPacket const* WorldPackets::Achievement::AchievementEarned::Write()
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::BroadcastAchievement::Write()
+WorldPacket const* BroadcastAchievement::Write()
{
_worldPacket.WriteBits(Name.length(), 7);
_worldPacket.WriteBit(GuildAchievement);
@@ -150,7 +152,7 @@ WorldPacket const* WorldPackets::Achievement::BroadcastAchievement::Write()
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::GuildCriteriaUpdate::Write()
+WorldPacket const* GuildCriteriaUpdate::Write()
{
_worldPacket << uint32(Progress.size());
@@ -159,8 +161,7 @@ WorldPacket const* WorldPackets::Achievement::GuildCriteriaUpdate::Write()
_worldPacket << int32(progress.CriteriaID);
_worldPacket << progress.DateCreated;
_worldPacket << progress.DateStarted;
- _worldPacket.AppendPackedTime(progress.DateUpdated);
- _worldPacket << uint32(0); // this is a hack. this is a packed time written as int64 (progress.DateUpdated)
+ _worldPacket << int64(progress.DateUpdated.GetPackedTime());
_worldPacket << uint64(progress.Quantity);
_worldPacket << progress.PlayerGUID;
_worldPacket << int32(progress.Unused_10_1_5);
@@ -170,7 +171,7 @@ WorldPacket const* WorldPackets::Achievement::GuildCriteriaUpdate::Write()
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::GuildCriteriaDeleted::Write()
+WorldPacket const* GuildCriteriaDeleted::Write()
{
_worldPacket << GuildGUID;
_worldPacket << int32(CriteriaID);
@@ -178,30 +179,30 @@ WorldPacket const* WorldPackets::Achievement::GuildCriteriaDeleted::Write()
return &_worldPacket;
}
-void WorldPackets::Achievement::GuildSetFocusedAchievement::Read()
+void GuildSetFocusedAchievement::Read()
{
_worldPacket >> AchievementID;
}
-WorldPacket const* WorldPackets::Achievement::GuildAchievementDeleted::Write()
+WorldPacket const* GuildAchievementDeleted::Write()
{
_worldPacket << GuildGUID;
_worldPacket << uint32(AchievementID);
- _worldPacket.AppendPackedTime(TimeDeleted);
+ _worldPacket << TimeDeleted;
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::GuildAchievementEarned::Write()
+WorldPacket const* GuildAchievementEarned::Write()
{
_worldPacket << GuildGUID;
_worldPacket << uint32(AchievementID);
- _worldPacket.AppendPackedTime(TimeEarned);
+ _worldPacket << TimeEarned;
return &_worldPacket;
}
-WorldPacket const* WorldPackets::Achievement::AllGuildAchievements::Write()
+WorldPacket const* AllGuildAchievements::Write()
{
_worldPacket << uint32(Earned.size());
@@ -211,20 +212,20 @@ WorldPacket const* WorldPackets::Achievement::AllGuildAchievements::Write()
return &_worldPacket;
}
-void WorldPackets::Achievement::GuildGetAchievementMembers::Read()
+void GuildGetAchievementMembers::Read()
{
_worldPacket >> PlayerGUID;
_worldPacket >> GuildGUID;
_worldPacket >> AchievementID;
}
-ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::GuildAchievementMember const& guildAchievementMember)
+ByteBuffer& operator<<(ByteBuffer& data, GuildAchievementMember const& guildAchievementMember)
{
data << guildAchievementMember.MemberGUID;
return data;
}
-WorldPacket const* WorldPackets::Achievement::GuildAchievementMembers::Write()
+WorldPacket const* GuildAchievementMembers::Write()
{
_worldPacket << GuildGUID;
_worldPacket << int32(AchievementID);
@@ -234,3 +235,4 @@ WorldPacket const* WorldPackets::Achievement::GuildAchievementMembers::Write()
return &_worldPacket;
}
+}
diff --git a/src/server/game/Server/Packets/AchievementPackets.h b/src/server/game/Server/Packets/AchievementPackets.h
index 39aa72aba16..8e2bbf14dfb 100644
--- a/src/server/game/Server/Packets/AchievementPackets.h
+++ b/src/server/game/Server/Packets/AchievementPackets.h
@@ -22,6 +22,7 @@
#include "ObjectGuid.h"
#include "Optional.h"
#include "PacketUtilities.h"
+#include "WowTime.h"
namespace WorldPackets
{
@@ -30,7 +31,7 @@ namespace WorldPackets
struct EarnedAchievement
{
uint32 Id = 0;
- time_t Date = time_t(0);
+ WowTime Date;
ObjectGuid Owner;
uint32 VirtualRealmAddress = 0;
uint32 NativeRealmAddress = 0;
@@ -43,7 +44,7 @@ namespace WorldPackets
ObjectGuid Player;
uint32 Unused_10_1_5 = 0;
uint32 Flags = 0;
- time_t Date = time_t(0);
+ WowTime Date;
Duration<Seconds> TimeFromStart;
Duration<Seconds> TimeFromCreate;
Optional<uint64> RafAcceptanceID;
@@ -98,7 +99,7 @@ namespace WorldPackets
ObjectGuid PlayerGUID;
uint32 Unused_10_1_5 = 0;
uint32 Flags = 0;
- time_t CurrentTime = time_t(0);
+ WowTime CurrentTime;
Duration<Seconds> ElapsedTime;
Timestamp<> CreationTime;
Optional<uint64> RafAcceptanceID;
@@ -146,7 +147,7 @@ namespace WorldPackets
uint32 EarnerNativeRealm = 0;
uint32 EarnerVirtualRealm = 0;
uint32 AchievementID = 0;
- time_t Time = time_t(0);
+ WowTime Time;
bool Initial = false;
ObjectGuid Sender;
};
@@ -169,7 +170,7 @@ namespace WorldPackets
int32 CriteriaID = 0;
Timestamp<> DateCreated;
Timestamp<> DateStarted;
- time_t DateUpdated = 0;
+ WowTime DateUpdated;
uint64 Quantity = 0;
ObjectGuid PlayerGUID;
int32 Unused_10_1_5 = 0;
@@ -216,7 +217,7 @@ namespace WorldPackets
ObjectGuid GuildGUID;
uint32 AchievementID = 0;
- time_t TimeDeleted = time_t(0);
+ WowTime TimeDeleted;
};
class GuildAchievementEarned final : public ServerPacket
@@ -228,7 +229,7 @@ namespace WorldPackets
uint32 AchievementID = 0;
ObjectGuid GuildGUID;
- time_t TimeEarned = time_t(0);
+ WowTime TimeEarned;
};
class AllGuildAchievements final : public ServerPacket
@@ -272,9 +273,9 @@ namespace WorldPackets
int32 AchievementID = 0;
std::vector<GuildAchievementMember> Member;
};
+
+ ByteBuffer& operator<<(ByteBuffer& data, CriteriaProgress const& criteria);
}
}
-ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Achievement::CriteriaProgress const& criteria);
-
#endif // game_AchievementPackets_h__
diff --git a/src/server/game/Server/Packets/CalendarPackets.cpp b/src/server/game/Server/Packets/CalendarPackets.cpp
index 27a67d416a3..cd0e1d3d7be 100644
--- a/src/server/game/Server/Packets/CalendarPackets.cpp
+++ b/src/server/game/Server/Packets/CalendarPackets.cpp
@@ -21,7 +21,7 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Calendar::CalendarSendCal
{
data << uint64(eventInfo.EventID);
data << uint8(eventInfo.EventType);
- data.AppendPackedTime(eventInfo.Date);
+ data << eventInfo.Date;
data << uint32(eventInfo.Flags);
data << int32(eventInfo.TextureID);
data << uint64(eventInfo.EventClubID);
@@ -67,8 +67,7 @@ ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Calendar::CalendarEventIn
data << uint8(inviteInfo.Status);
data << uint8(inviteInfo.Moderator);
data << uint8(inviteInfo.InviteType);
-
- data.AppendPackedTime(inviteInfo.ResponseTime);
+ data << inviteInfo.ResponseTime;
data.WriteBits(inviteInfo.Notes.size(), 8);
data.FlushBits();
@@ -121,7 +120,7 @@ ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Calendar::CalendarAddEv
buffer >> addEventInfo.ClubID;
buffer >> addEventInfo.EventType;
buffer >> addEventInfo.TextureID;
- addEventInfo.Time = buffer.ReadPackedTime();
+ buffer >> addEventInfo.Time;
buffer >> addEventInfo.Flags;
addEventInfo.Invites.resize(buffer.read<uint32>());
@@ -150,7 +149,7 @@ ByteBuffer& operator>>(ByteBuffer& buffer, WorldPackets::Calendar::CalendarUpdat
buffer >> updateEventInfo.ModeratorID;
buffer >> updateEventInfo.EventType;
buffer >> updateEventInfo.TextureID;
- updateEventInfo.Time = buffer.ReadPackedTime();
+ buffer >> updateEventInfo.Time;
buffer >> updateEventInfo.Flags;
uint8 titleLen = buffer.ReadBits(8);
@@ -181,7 +180,7 @@ void WorldPackets::Calendar::CalendarCopyEvent::Read()
_worldPacket >> EventID;
_worldPacket >> ModeratorID;
_worldPacket >> EventClubID;
- Date = _worldPacket.ReadPackedTime();
+ _worldPacket >> Date;
}
void WorldPackets::Calendar::CalendarRSVP::Read()
@@ -252,7 +251,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarInviteAdded::Write()
_worldPacket << uint8(Level);
_worldPacket << uint8(Status);
_worldPacket << uint8(Type);
- _worldPacket.AppendPackedTime(ResponseTime);
+ _worldPacket << ResponseTime;
_worldPacket.WriteBit(ClearPending);
_worldPacket.FlushBits();
@@ -262,7 +261,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarInviteAdded::Write()
WorldPacket const* WorldPackets::Calendar::CalendarSendCalendar::Write()
{
- _worldPacket.AppendPackedTime(ServerTime);
+ _worldPacket << ServerTime;
_worldPacket << uint32(Invites.size());
_worldPacket << uint32(Events.size());
_worldPacket << uint32(RaidLockouts.size());
@@ -287,8 +286,8 @@ WorldPacket const* WorldPackets::Calendar::CalendarSendEvent::Write()
_worldPacket << uint8(GetEventType);
_worldPacket << int32(TextureID);
_worldPacket << uint32(Flags);
- _worldPacket.AppendPackedTime(Date);
- _worldPacket << uint32(LockDate);
+ _worldPacket << Date;
+ _worldPacket << LockDate;
_worldPacket << uint64(EventClubID);
_worldPacket << uint32(Invites.size());
_worldPacket.WriteBits(EventName.size(), 8);
@@ -307,7 +306,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarSendEvent::Write()
WorldPacket const* WorldPackets::Calendar::CalendarInviteAlert::Write()
{
_worldPacket << uint64(EventID);
- _worldPacket.AppendPackedTime(Date);
+ _worldPacket << Date;
_worldPacket << uint32(Flags);
_worldPacket << uint8(EventType);
_worldPacket << int32(TextureID);
@@ -331,10 +330,10 @@ WorldPacket const* WorldPackets::Calendar::CalendarInviteStatus::Write()
{
_worldPacket << InviteGuid;
_worldPacket << uint64(EventID);
- _worldPacket.AppendPackedTime(Date);
+ _worldPacket << Date;
_worldPacket << uint32(Flags);
_worldPacket << uint8(Status);
- _worldPacket.AppendPackedTime(ResponseTime);
+ _worldPacket << ResponseTime;
_worldPacket.WriteBit(ClearPending);
_worldPacket.FlushBits();
@@ -369,7 +368,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarModeratorStatus::Write()
WorldPacket const* WorldPackets::Calendar::CalendarInviteRemovedAlert::Write()
{
_worldPacket << uint64(EventID);
- _worldPacket.AppendPackedTime(Date);
+ _worldPacket << Date;
_worldPacket << uint32(Flags);
_worldPacket << uint8(Status);
@@ -381,9 +380,9 @@ WorldPacket const* WorldPackets::Calendar::CalendarEventUpdatedAlert::Write()
_worldPacket << uint64(EventClubID);
_worldPacket << uint64(EventID);
- _worldPacket.AppendPackedTime(OriginalDate);
- _worldPacket.AppendPackedTime(Date);
- _worldPacket << uint32(LockDate);
+ _worldPacket << OriginalDate;
+ _worldPacket << Date;
+ _worldPacket << LockDate;
_worldPacket << uint32(Flags);
_worldPacket << uint32(TextureID);
_worldPacket << uint8(EventType);
@@ -402,7 +401,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarEventUpdatedAlert::Write()
WorldPacket const* WorldPackets::Calendar::CalendarEventRemovedAlert::Write()
{
_worldPacket << uint64(EventID);
- _worldPacket.AppendPackedTime(Date);
+ _worldPacket << Date;
_worldPacket.WriteBit(ClearPending);
_worldPacket.FlushBits();
@@ -450,7 +449,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarRaidLockoutRemoved::Write()
WorldPacket const* WorldPackets::Calendar::CalendarRaidLockoutUpdated::Write()
{
- _worldPacket.AppendPackedTime(ServerTime);
+ _worldPacket << ServerTime;
_worldPacket << int32(MapID);
_worldPacket << uint32(DifficultyID);
_worldPacket << int32(OldTimeRemaining);
@@ -474,7 +473,7 @@ WorldPacket const* WorldPackets::Calendar::CalendarCommunityInvite::Write()
WorldPacket const* WorldPackets::Calendar::CalendarInviteStatusAlert::Write()
{
_worldPacket << uint64(EventID);
- _worldPacket.AppendPackedTime(Date);
+ _worldPacket << Date;
_worldPacket << uint32(Flags);
_worldPacket << uint8(Status);
diff --git a/src/server/game/Server/Packets/CalendarPackets.h b/src/server/game/Server/Packets/CalendarPackets.h
index 7ef1a4976f8..4ac9b9b8a3b 100644
--- a/src/server/game/Server/Packets/CalendarPackets.h
+++ b/src/server/game/Server/Packets/CalendarPackets.h
@@ -23,6 +23,7 @@
#include "ObjectGuid.h"
#include "Optional.h"
#include "PacketUtilities.h"
+#include "WowTime.h"
namespace WorldPackets
{
@@ -76,7 +77,7 @@ namespace WorldPackets
std::string Description;
uint8 EventType = 0;
int32 TextureID = 0;
- time_t Time = time_t(0);
+ WowTime Time;
uint32 Flags = 0;
Array<CalendarAddEventInviteInfo, CALENDAR_MAX_INVITES> Invites;
};
@@ -101,7 +102,7 @@ namespace WorldPackets
std::string Description;
uint8 EventType = 0;
uint32 TextureID = 0;
- time_t Time = time_t(0);
+ WowTime Time;
uint32 Flags = 0;
};
@@ -139,7 +140,7 @@ namespace WorldPackets
uint64 ModeratorID = 0;
uint64 EventID = 0;
uint64 EventClubID = 0;
- time_t Date = time_t(0);
+ WowTime Date;
};
class CalendarInviteAdded final : public ServerPacket
@@ -150,7 +151,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
uint64 InviteID = 0;
- time_t ResponseTime = time_t(0);
+ WowTime ResponseTime;
uint8 Level = 100;
ObjectGuid InviteGuid;
uint64 EventID = 0;
@@ -183,7 +184,7 @@ namespace WorldPackets
uint64 EventID = 0;
std::string EventName;
uint8 EventType = 0;
- time_t Date = time_t(0);
+ WowTime Date;
uint32 Flags = 0;
int32 TextureID = 0;
uint64 EventClubID = 0;
@@ -197,7 +198,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
- time_t ServerTime = time_t(0);
+ WowTime ServerTime;
std::vector<CalendarSendCalendarInviteInfo> Invites;
std::vector<CalendarSendCalendarRaidLockoutInfo> RaidLockouts;
std::vector<CalendarSendCalendarEventInfo> Events;
@@ -207,7 +208,7 @@ namespace WorldPackets
{
ObjectGuid Guid;
uint64 InviteID = 0;
- time_t ResponseTime = time_t(0);
+ WowTime ResponseTime;
uint8 Level = 1;
uint8 Status = 0;
uint8 Moderator = 0;
@@ -225,8 +226,8 @@ namespace WorldPackets
ObjectGuid OwnerGuid;
uint64 EventClubID = 0;
uint64 EventID = 0;
- time_t Date = time_t(0);
- time_t LockDate = time_t(0);
+ WowTime Date;
+ WowTime LockDate;
uint32 Flags = 0;
int32 TextureID = 0;
uint8 GetEventType = 0;
@@ -249,7 +250,7 @@ namespace WorldPackets
uint64 InviteID = 0;
uint64 EventID = 0;
uint32 Flags = 0;
- time_t Date = time_t(0);
+ WowTime Date;
int32 TextureID = 0;
uint8 Status = 0;
uint8 EventType = 0;
@@ -295,8 +296,8 @@ namespace WorldPackets
uint64 EventID = 0;
uint8 Status = 0;
bool ClearPending = false;
- time_t ResponseTime = time_t(0);
- time_t Date = time_t(0);
+ WowTime ResponseTime;
+ WowTime Date;
ObjectGuid InviteGuid;
};
@@ -334,7 +335,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
uint64 EventID = 0;
- time_t Date = time_t(0);
+ WowTime Date;
uint32 Flags = 0;
uint8 Status = 0;
};
@@ -356,10 +357,10 @@ namespace WorldPackets
uint64 EventClubID = 0;
uint64 EventID = 0;
- time_t Date = time_t(0);
+ WowTime Date;
uint32 Flags = 0;
- time_t LockDate = time_t(0);
- time_t OriginalDate = time_t(0);
+ WowTime LockDate;
+ WowTime OriginalDate;
int32 TextureID = 0;
uint8 EventType = 0;
bool ClearPending = false;
@@ -375,7 +376,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
uint64 EventID = 0;
- time_t Date = time_t(0);
+ WowTime Date;
bool ClearPending = false;
};
@@ -509,7 +510,7 @@ namespace WorldPackets
WorldPacket const* Write() override;
- time_t ServerTime = 0;
+ WowTime ServerTime;
int32 MapID = 0;
uint32 DifficultyID = 0;
int32 NewTimeRemaining = 0;
@@ -543,7 +544,7 @@ namespace WorldPackets
uint64 EventID = 0;
uint32 Flags = 0;
- time_t Date = time_t(0);
+ WowTime Date;
uint8 Status = 0;
};
diff --git a/src/server/game/Server/Packets/GuildPackets.cpp b/src/server/game/Server/Packets/GuildPackets.cpp
index aa59ebfc986..fe80b31595d 100644
--- a/src/server/game/Server/Packets/GuildPackets.cpp
+++ b/src/server/game/Server/Packets/GuildPackets.cpp
@@ -64,7 +64,7 @@ WorldPacket const* WorldPackets::Guild::QueryGuildInfoResponse::Write()
WorldPacket const* WorldPackets::Guild::GuildRoster::Write()
{
_worldPacket << int32(NumAccounts);
- _worldPacket.AppendPackedTime(CreateDate);
+ _worldPacket << CreateDate;
_worldPacket << int32(GuildFlags);
_worldPacket << uint32(MemberData.size());
_worldPacket.WriteBits(WelcomeText.length(), 11);
@@ -871,7 +871,7 @@ void WorldPackets::Guild::GuildQueryNews::Read()
ByteBuffer& operator<<(ByteBuffer& data, WorldPackets::Guild::GuildNewsEvent const& newsEvent)
{
data << int32(newsEvent.Id);
- data.AppendPackedTime(newsEvent.CompletedDate);
+ data << newsEvent.CompletedDate;
data << int32(newsEvent.Type);
data << int32(newsEvent.Flags);
diff --git a/src/server/game/Server/Packets/GuildPackets.h b/src/server/game/Server/Packets/GuildPackets.h
index bd80498061e..31f9c6ba62d 100644
--- a/src/server/game/Server/Packets/GuildPackets.h
+++ b/src/server/game/Server/Packets/GuildPackets.h
@@ -24,6 +24,7 @@
#include "MythicPlusPacketsCommon.h"
#include "ObjectGuid.h"
#include "PacketUtilities.h"
+#include "WowTime.h"
namespace WorldPackets
{
@@ -130,7 +131,7 @@ namespace WorldPackets
std::vector<GuildRosterMemberData> MemberData;
std::string WelcomeText;
std::string InfoText;
- uint32 CreateDate = 0;
+ WowTime CreateDate;
int32 NumAccounts = 0;
int32 GuildFlags = 0;
};
@@ -1073,7 +1074,7 @@ namespace WorldPackets
struct GuildNewsEvent
{
int32 Id = 0;
- uint32 CompletedDate = 0;
+ WowTime CompletedDate;
int32 Type = 0;
int32 Flags = 0;
std::array<int32, 2> Data = { };
diff --git a/src/server/game/Server/Packets/MiscPackets.cpp b/src/server/game/Server/Packets/MiscPackets.cpp
index 9c6687075af..21395173965 100644
--- a/src/server/game/Server/Packets/MiscPackets.cpp
+++ b/src/server/game/Server/Packets/MiscPackets.cpp
@@ -36,8 +36,8 @@ WorldPacket const* WorldPackets::Misc::InvalidatePlayer::Write()
WorldPacket const* WorldPackets::Misc::LoginSetTimeSpeed::Write()
{
- _worldPacket.AppendPackedTime(ServerTime);
- _worldPacket.AppendPackedTime(GameTime);
+ _worldPacket << ServerTime;
+ _worldPacket << GameTime;
_worldPacket << float(NewSpeed);
_worldPacket << uint32(ServerTimeHolidayOffset);
_worldPacket << uint32(GameTimeHolidayOffset);
diff --git a/src/server/game/Server/Packets/MiscPackets.h b/src/server/game/Server/Packets/MiscPackets.h
index ef5de8330d6..b1469847788 100644
--- a/src/server/game/Server/Packets/MiscPackets.h
+++ b/src/server/game/Server/Packets/MiscPackets.h
@@ -28,6 +28,7 @@
#include "Player.h"
#include "Position.h"
#include "SharedDefines.h"
+#include "WowTime.h"
#include <array>
#include <map>
@@ -81,8 +82,8 @@ namespace WorldPackets
float NewSpeed = 0.0f;
int32 ServerTimeHolidayOffset = 0;
- uint32 GameTime = 0;
- uint32 ServerTime = 0;
+ WowTime GameTime;
+ WowTime ServerTime;
int32 GameTimeHolidayOffset = 0;
};
diff --git a/src/server/game/Server/Packets/SystemPackets.h b/src/server/game/Server/Packets/SystemPackets.h
index 5c173e7d3ac..afb0600db98 100644
--- a/src/server/game/Server/Packets/SystemPackets.h
+++ b/src/server/game/Server/Packets/SystemPackets.h
@@ -234,9 +234,9 @@ namespace WorldPackets
WorldPacket const* Write() override;
- std::string ServerTimeTZ;
- std::string GameTimeTZ;
- std::string ServerRegionalTZ;
+ std::string_view ServerTimeTZ;
+ std::string_view GameTimeTZ;
+ std::string_view ServerRegionalTZ;
};
}
}
diff --git a/src/server/game/Server/WorldSession.cpp b/src/server/game/Server/WorldSession.cpp
index c4c46c044d9..2f4a333529f 100644
--- a/src/server/game/Server/WorldSession.cpp
+++ b/src/server/game/Server/WorldSession.cpp
@@ -106,7 +106,7 @@ bool WorldSessionFilter::Process(WorldPacket* packet)
/// WorldSession constructor
WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time,
- std::string os, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
+ std::string os, Minutes timezoneOffset, LocaleConstant locale, uint32 recruiter, bool isARecruiter):
m_muteTime(mute_time),
m_timeOutTime(0),
AntiDOS(this),
@@ -118,7 +118,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
_battlenetAccountId(battlenetAccountId),
m_accountExpansion(expansion),
m_expansion(std::min<uint8>(expansion, sWorld->getIntConfig(CONFIG_EXPANSION))),
- _os(os),
+ _os(std::move(os)),
_battlenetRequestToken(0),
_logoutTime(0),
m_inQueue(false),
@@ -127,6 +127,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
m_playerSave(false),
m_sessionDbcLocale(sWorld->GetAvailableDbcLocale(locale)),
m_sessionDbLocaleIndex(locale),
+ _timezoneOffset(timezoneOffset),
m_latency(0),
_tutorialsChanged(TUTORIALS_FLAG_NONE),
_filterAddonMessages(false),
@@ -153,7 +154,7 @@ WorldSession::WorldSession(uint32 id, std::string&& name, uint32 battlenetAccoun
LoginDatabase.PExecute("UPDATE account SET online = 1 WHERE id = {};", GetAccountId()); // One-time query
}
- m_Socket[CONNECTION_TYPE_REALM] = sock;
+ m_Socket[CONNECTION_TYPE_REALM] = std::move(sock);
_instanceConnectKey.Raw = UI64LIT(0);
}
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index 2971a6f59ef..296eda86e61 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -948,7 +948,7 @@ class TC_GAME_API WorldSession
{
public:
WorldSession(uint32 id, std::string&& name, uint32 battlenetAccountId, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time,
- std::string os, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
+ std::string os, Minutes timezoneOffset, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
~WorldSession();
bool PlayerLoading() const { return !m_playerLoading.IsEmpty(); }
@@ -1131,6 +1131,9 @@ class TC_GAME_API WorldSession
// Locales
LocaleConstant GetSessionDbcLocale() const { return m_sessionDbcLocale; }
LocaleConstant GetSessionDbLocaleIndex() const { return m_sessionDbLocaleIndex; }
+
+ Minutes GetTimezoneOffset() const { return _timezoneOffset; }
+
char const* GetTrinityString(uint32 entry) const;
uint32 GetLatency() const { return m_latency; }
@@ -1916,6 +1919,7 @@ class TC_GAME_API WorldSession
bool m_playerSave;
LocaleConstant m_sessionDbcLocale;
LocaleConstant m_sessionDbLocaleIndex;
+ Minutes _timezoneOffset;
std::atomic<uint32> m_latency;
AccountData _accountData[NUM_ACCOUNT_DATA_TYPES];
uint32 _tutorials[MAX_ACCOUNT_TUTORIAL_VALUES];
diff --git a/src/server/game/Server/WorldSocket.cpp b/src/server/game/Server/WorldSocket.cpp
index c92b8d03c8f..0161974879a 100644
--- a/src/server/game/Server/WorldSocket.cpp
+++ b/src/server/game/Server/WorldSocket.cpp
@@ -626,6 +626,7 @@ struct AccountInfo
int64 MuteTime;
uint32 Recruiter;
std::string OS;
+ Minutes TimezoneOffset;
bool IsRectuiter;
AccountTypes Security;
bool IsBanned;
@@ -633,11 +634,11 @@ struct AccountInfo
bool IsBanned() const { return BattleNet.IsBanned || Game.IsBanned; }
- explicit AccountInfo(Field* fields)
+ explicit AccountInfo(Field const* fields)
{
- // 0 1 2 3 4 5 6 7 8 9 10 11
- // SELECT a.id, a.session_key, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, ba.id, aa.SecurityLevel,
- // 12 13 14
+ // 0 1 2 3 4 5 6 7 8 9 10 11 12
+ // SELECT a.id, a.session_key, ba.last_ip, ba.locked, ba.lock_country, a.expansion, a.mutetime, ba.locale, a.recruiter, a.os, a.timezone_offset, ba.id, aa.SecurityLevel,
+ // 13 14 15
// bab.unbandate > UNIX_TIMESTAMP() OR bab.unbandate = bab.bandate, ab.unbandate > UNIX_TIMESTAMP() OR ab.unbandate = ab.bandate, r.id
// FROM account a LEFT JOIN battlenet_accounts ba ON a.battlenet_account = ba.id LEFT JOIN account_access aa ON a.id = aa.AccountID AND aa.RealmID IN (-1, ?)
// LEFT JOIN battlenet_account_bans bab ON ba.id = bab.id LEFT JOIN account_banned ab ON a.id = ab.id LEFT JOIN account r ON a.id = r.recruiter
@@ -652,11 +653,12 @@ struct AccountInfo
BattleNet.Locale = LocaleConstant(fields[7].GetUInt8());
Game.Recruiter = fields[8].GetUInt32();
Game.OS = fields[9].GetString();
- BattleNet.Id = fields[10].GetUInt32();
- Game.Security = AccountTypes(fields[11].GetUInt8());
- BattleNet.IsBanned = fields[12].GetUInt32() != 0;
- Game.IsBanned = fields[13].GetUInt32() != 0;
- Game.IsRectuiter = fields[14].GetUInt32() != 0;
+ Game.TimezoneOffset = Minutes(fields[10].GetInt16());
+ BattleNet.Id = fields[11].GetUInt32();
+ Game.Security = AccountTypes(fields[12].GetUInt8());
+ BattleNet.IsBanned = fields[13].GetUInt32() != 0;
+ Game.IsBanned = fields[14].GetUInt32() != 0;
+ Game.IsRectuiter = fields[15].GetUInt32() != 0;
if (BattleNet.Locale >= TOTAL_LOCALES)
BattleNet.Locale = LOCALE_enUS;
@@ -670,7 +672,10 @@ void WorldSocket::HandleAuthSession(std::shared_ptr<WorldPackets::Auth::AuthSess
stmt->setInt32(0, int32(realm.Id.Realm));
stmt->setString(1, authSession->RealmJoinTicket);
- _queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback(std::bind(&WorldSocket::HandleAuthSessionCallback, this, authSession, std::placeholders::_1)));
+ _queryProcessor.AddCallback(LoginDatabase.AsyncQuery(stmt).WithPreparedCallback([this, authSession = std::move(authSession)](PreparedQueryResult result) mutable
+ {
+ HandleAuthSessionCallback(std::move(authSession), std::move(result));
+ }));
}
void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::AuthSession> authSession, PreparedQueryResult result)
@@ -868,7 +873,7 @@ void WorldSocket::HandleAuthSessionCallback(std::shared_ptr<WorldPackets::Auth::
_authed = true;
_worldSession = new WorldSession(account.Game.Id, std::move(authSession->RealmJoinTicket), account.BattleNet.Id, shared_from_this(), account.Game.Security,
- account.Game.Expansion, mutetime, account.Game.OS, account.BattleNet.Locale, account.Game.Recruiter, account.Game.IsRectuiter);
+ account.Game.Expansion, mutetime, account.Game.OS, account.Game.TimezoneOffset, account.BattleNet.Locale, account.Game.Recruiter, account.Game.IsRectuiter);
// Initialize Warden system only if it is enabled by config
if (wardenActive)
diff --git a/src/server/game/Services/WorldserverService.cpp b/src/server/game/Services/WorldserverService.cpp
index 61a13011f4b..213ffbbad8f 100644
--- a/src/server/game/Services/WorldserverService.cpp
+++ b/src/server/game/Services/WorldserverService.cpp
@@ -126,7 +126,7 @@ uint32 Battlenet::GameUtilitiesService::HandleRealmJoinRequest(std::unordered_ma
{
if (Variant const* realmAddress = GetParam(params, "Param_RealmAddress"))
return sRealmList->JoinRealm(uint32(realmAddress->uint_value()), realm.Build, Trinity::Net::make_address(_session->GetRemoteAddress()), _session->GetRealmListSecret(),
- _session->GetSessionDbcLocale(), _session->GetOS(), _session->GetAccountName(), response);
+ _session->GetSessionDbcLocale(), _session->GetOS(), _session->GetTimezoneOffset(), _session->GetAccountName(), response);
return ERROR_WOW_SERVICES_INVALID_JOIN_TICKET;
}
diff --git a/src/server/game/Time/GameTime.cpp b/src/server/game/Time/GameTime.cpp
index 399be3196b3..3175c0e5571 100644
--- a/src/server/game/Time/GameTime.cpp
+++ b/src/server/game/Time/GameTime.cpp
@@ -17,7 +17,9 @@
#include "GameTime.h"
#include "Timer.h"
+#include "Timezone.h"
#include "Util.h"
+#include "WowTime.h"
namespace GameTime
{
@@ -31,6 +33,9 @@ namespace GameTime
tm DateTime;
+ WowTime UtcWow;
+ WowTime Wow;
+
time_t GetStartTime()
{
return StartTime;
@@ -84,6 +89,16 @@ namespace GameTime
return &DateTime;
}
+ WowTime const* GetUtcWowTime()
+ {
+ return &UtcWow;
+ }
+
+ WowTime const* GetWowTime()
+ {
+ return &Wow;
+ }
+
void UpdateGameTimers()
{
GameTime = time(nullptr);
@@ -91,5 +106,7 @@ namespace GameTime
GameTimeSystemPoint = std::chrono::system_clock::now();
GameTimeSteadyPoint = std::chrono::steady_clock::now();
localtime_r(&GameTime, &DateTime);
+ UtcWow.SetUtcTimeFromUnixTime(GameTime);
+ Wow = UtcWow + Trinity::Timezone::GetSystemZoneOffsetAt(GameTimeSystemPoint);
}
}
diff --git a/src/server/game/Time/GameTime.h b/src/server/game/Time/GameTime.h
index 4229872e016..7b18b030d2c 100644
--- a/src/server/game/Time/GameTime.h
+++ b/src/server/game/Time/GameTime.h
@@ -21,6 +21,8 @@
#include "Define.h"
#include "Duration.h"
+class WowTime;
+
namespace GameTime
{
// Server start time
@@ -47,6 +49,10 @@ namespace GameTime
TC_GAME_API tm const* GetDateAndTime();
+ TC_GAME_API WowTime const* GetUtcWowTime();
+
+ TC_GAME_API WowTime const* GetWowTime();
+
void UpdateGameTimers();
}
diff --git a/src/server/game/Time/WowTime.cpp b/src/server/game/Time/WowTime.cpp
new file mode 100644
index 00000000000..b88f0c56a8e
--- /dev/null
+++ b/src/server/game/Time/WowTime.cpp
@@ -0,0 +1,219 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "WowTime.h"
+#include "ByteBuffer.h"
+#include "Errors.h"
+#include "Util.h"
+
+uint32 WowTime::GetPackedTime() const
+{
+ return ((_year % 100) & 0x1F) << 24
+ | (_month & 0xF) << 20
+ | (_monthDay & 0x3F) << 14
+ | (_weekDay & 0x7) << 11
+ | (_hour & 0x1F) << 6
+ | (_minute & 0x3F)
+ | (_flags & 0x3) << 29;
+}
+
+void WowTime::SetPackedTime(uint32 packedTime)
+{
+ _year = (packedTime >> 24) & 0x1F;
+ if (_year == 31)
+ _year = -1;
+
+ _month = (packedTime >> 20) & 0xF;
+ if (_month == 15)
+ _month = -1;
+
+ _monthDay = (packedTime >> 14) & 0x3F;
+ if (_monthDay == 63)
+ _monthDay = -1;
+
+ _weekDay = (packedTime >> 11) & 0x7;
+ if (_weekDay == 7)
+ _weekDay = -1;
+
+ _hour = (packedTime >> 6) & 0x1F;
+ if (_hour == 31)
+ _hour = -1;
+
+ _minute = packedTime & 0x3F;
+ if (_minute == 63)
+ _minute = -1;
+
+ _flags = (packedTime >> 29) & 0x3;
+ if (_flags == 3)
+ _flags = -1;
+}
+
+std::time_t WowTime::GetUnixTimeFromUtcTime() const
+{
+ if (_year < 0 || _month < 0 || _monthDay < 0)
+ return 0;
+
+ std::tm buf{};
+ buf.tm_year = _year + 100;
+ buf.tm_mon = _month;
+ buf.tm_mday = _monthDay + 1;
+ if (_hour >= 0)
+ {
+ buf.tm_hour = _hour;
+ if (_minute >= 0)
+ buf.tm_min = _minute;
+ }
+ buf.tm_isdst = -1;
+ buf.tm_wday = _weekDay;
+
+ return timegm(&buf);
+}
+
+void WowTime::SetUtcTimeFromUnixTime(std::time_t unixTime)
+{
+ std::tm buf;
+ if (!::gmtime_r(&unixTime, &buf))
+ return;
+
+ _year = (buf.tm_year - 100) % 100;
+ _month = buf.tm_mon;
+ _monthDay = buf.tm_mday - 1;
+ _weekDay = buf.tm_wday;
+ _hour = buf.tm_hour;
+ _minute = buf.tm_min;
+}
+
+void WowTime::SetYear(int32 year)
+{
+ ASSERT(year == -1 || (year >= 0 && year < 32));
+ _year = year;
+}
+
+void WowTime::SetMonth(int8 month)
+{
+ ASSERT(month == -1 || (month >= 0 && month < 12));
+ _month = month;
+}
+
+void WowTime::SetMonthDay(int8 monthDay)
+{
+ ASSERT(monthDay == -1 || (monthDay >= 0 && monthDay < 32));
+ _monthDay = monthDay;
+}
+
+void WowTime::SetWeekDay(int8 weekDay)
+{
+ ASSERT(weekDay == -1 || (weekDay >= 0 && weekDay < 7));
+ _weekDay = weekDay;
+}
+
+void WowTime::SetHour(int8 hour)
+{
+ ASSERT(hour == -1 || (hour >= 0 && hour < 24));
+ _hour = hour;
+}
+
+void WowTime::SetMinute(int8 minute)
+{
+ ASSERT(minute == -1 || (minute >= 0 && minute < 60));
+ _minute = minute;
+}
+
+void WowTime::SetFlags(int8 flags)
+{
+ ASSERT(flags == -1 || (flags >= 0 && flags < 3));
+ _flags = flags;
+}
+
+std::strong_ordering operator<=>(WowTime const& left, WowTime const& right)
+{
+ auto compareFieldIfSet = [&]<typename T>(T WowTime::*field) -> std::strong_ordering
+ {
+ if (left.*field < 0 || right.*field < 0)
+ return std::strong_ordering::equal;
+
+ return left.*field <=> right.*field;
+ };
+
+ if (std::strong_ordering cmp = compareFieldIfSet(&WowTime::_year); advstd::is_neq(cmp))
+ return cmp;
+
+ if (std::strong_ordering cmp = compareFieldIfSet(&WowTime::_month); advstd::is_neq(cmp))
+ return cmp;
+
+ if (std::strong_ordering cmp = compareFieldIfSet(&WowTime::_monthDay); advstd::is_neq(cmp))
+ return cmp;
+
+ if (std::strong_ordering cmp = compareFieldIfSet(&WowTime::_weekDay); advstd::is_neq(cmp))
+ return cmp;
+
+ if (std::strong_ordering cmp = compareFieldIfSet(&WowTime::_year); advstd::is_neq(cmp))
+ return cmp;
+
+ if (std::strong_ordering cmp = compareFieldIfSet(&WowTime::_hour); advstd::is_neq(cmp))
+ return cmp;
+
+ return std::strong_ordering::equal;
+}
+
+bool WowTime::IsInRange(WowTime const& from, WowTime const& to) const
+{
+ if (from > to)
+ return *this >= from || *this < to;
+
+ return *this >= from && *this < to;
+}
+
+WowTime& WowTime::operator+=(Seconds seconds)
+{
+ time_t unixTime = GetUnixTimeFromUtcTime();
+ unixTime += seconds.count();
+ SetUtcTimeFromUnixTime(unixTime);
+ return *this;
+}
+
+WowTime WowTime::operator+(Seconds seconds) const
+{
+ return WowTime(*this) += seconds;
+}
+
+WowTime& WowTime::operator-=(Seconds seconds)
+{
+ time_t unixTime = GetUnixTimeFromUtcTime();
+ unixTime -= seconds.count();
+ SetUtcTimeFromUnixTime(unixTime);
+ return *this;
+}
+
+WowTime WowTime::operator-(Seconds seconds) const
+{
+ return WowTime(*this) -= seconds;
+}
+
+ByteBuffer& operator<<(ByteBuffer& data, WowTime const& wowTime)
+{
+ data << uint32(wowTime.GetPackedTime());
+ return data;
+}
+
+ByteBuffer& operator>>(ByteBuffer& data, WowTime& wowTime)
+{
+ uint32 packedTime = 0;
+ data >> packedTime;
+ wowTime.SetPackedTime(packedTime);
+ return data;
+}
diff --git a/src/server/game/Time/WowTime.h b/src/server/game/Time/WowTime.h
new file mode 100644
index 00000000000..a273d210d6a
--- /dev/null
+++ b/src/server/game/Time/WowTime.h
@@ -0,0 +1,90 @@
+/*
+ * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef TRINITYCORE_WOWTIME_H
+#define TRINITYCORE_WOWTIME_H
+
+#include "Define.h"
+#include "Duration.h"
+#include "advstd.h"
+#include <compare>
+#include <ctime>
+
+class ByteBuffer;
+
+class WowTime
+{
+public:
+ uint32 GetPackedTime() const;
+ void SetPackedTime(uint32 packedTime);
+
+ std::time_t GetUnixTimeFromUtcTime() const;
+ void SetUtcTimeFromUnixTime(std::time_t unixTime);
+
+ int32 GetYear() const { return _year; }
+ void SetYear(int32 year);
+
+ int8 GetMonth() const { return _month; }
+ void SetMonth(int8 month);
+
+ int8 GetMonthDay() const { return _monthDay; }
+ void SetMonthDay(int8 monthDay);
+
+ int8 GetWeekDay() const { return _weekDay; }
+ void SetWeekDay(int8 weekDay);
+
+ int8 GetHour() const { return _hour; }
+ void SetHour(int8 hour);
+
+ int8 GetMinute() const { return _minute; }
+ void SetMinute(int8 minute);
+
+ int8 GetFlags() const { return _flags; }
+ void SetFlags(int8 flags);
+
+ int8 GetHolidayOffset() const { return _holidayOffset; }
+ void SetHolidayOffset(int8 holidayOffset) { _holidayOffset = holidayOffset; }
+
+ friend TC_GAME_API std::strong_ordering operator<=>(WowTime const& left, WowTime const& right);
+ friend TC_GAME_API bool operator==(WowTime const& left, WowTime const& right)
+ {
+ return advstd::is_eq(left <=> right);
+ }
+
+ bool IsInRange(WowTime const& from, WowTime const& to) const;
+
+ WowTime& operator+=(Seconds seconds);
+ WowTime operator+(Seconds seconds) const;
+
+ WowTime& operator-=(Seconds seconds);
+ WowTime operator-(Seconds seconds) const;
+
+ friend TC_GAME_API ByteBuffer& operator<<(ByteBuffer& data, WowTime const& wowTime);
+ friend TC_GAME_API ByteBuffer& operator>>(ByteBuffer& data, WowTime& wowTime);
+
+private:
+ int32 _year = -1;
+ int8 _month = -1;
+ int8 _monthDay = -1;
+ int8 _weekDay = -1;
+ int8 _hour = -1;
+ int8 _minute = -1;
+ int8 _flags = -1;
+ int8 _holidayOffset = 0;
+};
+
+#endif // TRINITYCORE_WOWTIME_H
diff --git a/src/server/shared/Packets/ByteBuffer.cpp b/src/server/shared/Packets/ByteBuffer.cpp
index 1775192227a..104ba96d9d0 100644
--- a/src/server/shared/Packets/ByteBuffer.cpp
+++ b/src/server/shared/Packets/ByteBuffer.cpp
@@ -23,7 +23,6 @@
#include <utf8.h>
#include <sstream>
#include <cmath>
-#include <ctime>
ByteBuffer::ByteBuffer(MessageBuffer&& buffer) : _rpos(0), _wpos(0), _bitpos(InitialBitPos), _curbitval(0), _storage(buffer.Move())
{
@@ -92,21 +91,6 @@ std::string ByteBuffer::ReadString(uint32 length, bool requireValidUtf8 /*= true
return value;
}
-uint32 ByteBuffer::ReadPackedTime()
-{
- uint32 packedDate = read<uint32>();
- tm lt = tm();
-
- lt.tm_min = packedDate & 0x3F;
- lt.tm_hour = (packedDate >> 6) & 0x1F;
- //lt.tm_wday = (packedDate >> 11) & 7;
- lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1;
- lt.tm_mon = (packedDate >> 20) & 0xF;
- lt.tm_year = ((packedDate >> 24) & 0x1F) + 100;
-
- return uint32(mktime(&lt));
-}
-
void ByteBuffer::append(uint8 const* src, size_t cnt)
{
ASSERT(src, "Attempted to put a NULL-pointer in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", _wpos, size());
@@ -134,13 +118,6 @@ void ByteBuffer::append(uint8 const* src, size_t cnt)
_wpos = newSize;
}
-void ByteBuffer::AppendPackedTime(time_t time)
-{
- tm lt;
- localtime_r(&time, &lt);
- append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min);
-}
-
void ByteBuffer::put(size_t pos, uint8 const* src, size_t cnt)
{
ASSERT(pos + cnt <= size(), "Attempted to put value with size: " SZFMTD " in ByteBuffer (pos: " SZFMTD " size: " SZFMTD ")", cnt, pos, size());
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index 76b521b9358..de0adf54341 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -519,8 +519,6 @@ class TC_SHARED_API ByteBuffer
std::string ReadString(uint32 length, bool requireValidUtf8 = true);
- uint32 ReadPackedTime();
-
uint8* contents()
{
if (_storage.empty())
@@ -624,8 +622,6 @@ class TC_SHARED_API ByteBuffer
return resultSize;
}
- void AppendPackedTime(time_t time);
-
void put(size_t pos, uint8 const* src, size_t cnt);
void print_storage() const;
diff --git a/src/server/shared/Realm/RealmList.cpp b/src/server/shared/Realm/RealmList.cpp
index 3d72418c10b..779bb6fca09 100644
--- a/src/server/shared/Realm/RealmList.cpp
+++ b/src/server/shared/Realm/RealmList.cpp
@@ -369,7 +369,7 @@ std::vector<uint8> RealmList::GetRealmList(uint32 build, std::string const& subR
}
uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::address const& clientAddress, std::array<uint8, 32> const& clientSecret,
- LocaleConstant locale, std::string const& os, std::string accountName, bgs::protocol::game_utilities::v1::ClientResponse* response) const
+ LocaleConstant locale, std::string const& os, Minutes timezoneOffset, std::string const& accountName, bgs::protocol::game_utilities::v1::ClientResponse* response) const
{
std::shared_lock<std::shared_mutex> lock(_realmsMutex);
if (Realm const* realm = GetRealm(Battlenet::RealmHandle(realmAddress)))
@@ -400,15 +400,17 @@ uint32 RealmList::JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::
std::array<uint8, 32> serverSecret = Trinity::Crypto::GetRandomBytes<32>();
std::array<uint8, 64> keyData;
- memcpy(&keyData[0], clientSecret.data(), 32);
- memcpy(&keyData[32], serverSecret.data(), 32);
+ auto keyDestItr = keyData.begin();
+ keyDestItr = std::copy(clientSecret.begin(), clientSecret.end(), keyDestItr);
+ keyDestItr = std::copy(serverSecret.begin(), serverSecret.end(), keyDestItr);
LoginDatabasePreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_GAME_ACCOUNT_LOGIN_INFO);
stmt->setBinary(0, keyData);
stmt->setString(1, clientAddress.to_string());
stmt->setUInt8(2, locale);
stmt->setString(3, os);
- stmt->setString(4, accountName);
+ stmt->setInt16(4, timezoneOffset.count());
+ stmt->setString(5, accountName);
LoginDatabase.DirectExecute(stmt);
bgs::protocol::Attribute* attribute = response->add_attribute();
diff --git a/src/server/shared/Realm/RealmList.h b/src/server/shared/Realm/RealmList.h
index 973dd913d7a..a1262d7e913 100644
--- a/src/server/shared/Realm/RealmList.h
+++ b/src/server/shared/Realm/RealmList.h
@@ -19,6 +19,7 @@
#define _REALMLIST_H
#include "Define.h"
+#include "Duration.h"
#include "Realm.h"
#include <array>
#include <map>
@@ -91,7 +92,8 @@ public:
std::vector<uint8> GetRealmEntryJSON(Battlenet::RealmHandle const& id, uint32 build) const;
std::vector<uint8> GetRealmList(uint32 build, std::string const& subRegion) const;
uint32 JoinRealm(uint32 realmAddress, uint32 build, boost::asio::ip::address const& clientAddress, std::array<uint8, 32> const& clientSecret,
- LocaleConstant locale, std::string const& os, std::string accountName, bgs::protocol::game_utilities::v1::ClientResponse* response) const;
+ LocaleConstant locale, std::string const& os, Minutes timezoneOffset, std::string const& accountName,
+ bgs::protocol::game_utilities::v1::ClientResponse* response) const;
private:
RealmList();