lleventnotifier.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  1. /**
  2. * @file lleventnotifier.cpp
  3. * @brief Viewer code for managing event notifications
  4. *
  5. * $LicenseInfo:firstyear=2004&license=viewergpl$
  6. *
  7. * Copyright (c) 2004-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "lleventnotifier.h"
  34. #include "llmessage.h"
  35. #include "lltrans.h"
  36. #include "llagent.h"
  37. #include "hbfloatersearch.h"
  38. #include "llfloaterworldmap.h"
  39. #include "llgridmanager.h"
  40. #include "llviewercontrol.h"
  41. // Helper function
  42. static std::string get_timestamp(time_t utc_time)
  43. {
  44. static LLCachedControl<std::string> date_fmt(gSavedSettings,
  45. "TimestampFormat");
  46. return LLGridManager::getTimeStamp(utc_time, date_fmt);
  47. }
  48. ///////////////////////////////////////////////////////////////////////////////
  49. // LLEventInfo class
  50. ///////////////////////////////////////////////////////////////////////////////
  51. LLEventInfo::map_t LLEventInfo::sCategories;
  52. void LLEventInfo::unpack(LLMessageSystem* msg)
  53. {
  54. U32 event_id;
  55. msg->getU32("EventData", "EventID", event_id);
  56. mID = event_id;
  57. msg->getString("EventData", "Name", mName);
  58. msg->getString("EventData", "Category", mCategoryStr);
  59. #if 0
  60. msg->getString("EventData", "Date", mTimeStr);
  61. #endif
  62. U32 duration;
  63. msg->getU32("EventData","Duration",duration);
  64. mDuration = duration;
  65. U32 date;
  66. msg->getU32("EventData", "DateUTC", date);
  67. mUnixTime = date;
  68. mTimeStr = get_timestamp(mUnixTime);
  69. msg->getString("EventData", "Desc", mDesc);
  70. std::string buffer;
  71. msg->getString("EventData", "Creator", buffer);
  72. mRunByID = LLUUID(buffer);
  73. U32 foo;
  74. msg->getU32("EventData", "Cover", foo);
  75. mHasCover = foo != 0;
  76. if (mHasCover)
  77. {
  78. U32 cover;
  79. msg->getU32("EventData", "Amount", cover);
  80. mCover = cover;
  81. }
  82. msg->getString("EventData", "SimName", mSimName);
  83. msg->getVector3d("EventData", "GlobalPos", mPosGlobal);
  84. // Mature content
  85. U32 event_flags;
  86. msg->getU32("EventData", "EventFlags", event_flags);
  87. mEventFlags = event_flags;
  88. }
  89. //static
  90. void LLEventInfo::loadCategories(const LLSD& event_options)
  91. {
  92. for (LLSD::array_const_iterator it = event_options.beginArray(),
  93. end = event_options.endArray();
  94. it != end; ++it)
  95. {
  96. const LLSD& entry = *it;
  97. if (entry.has("category_name") && entry.has("category_id"))
  98. {
  99. U32 id = entry["category_id"].asInteger();
  100. sCategories[id] = entry["category_name"].asString();
  101. }
  102. }
  103. }
  104. ///////////////////////////////////////////////////////////////////////////////
  105. // LLEventNotification class
  106. ///////////////////////////////////////////////////////////////////////////////
  107. LLEventNotification::LLEventNotification()
  108. : mEventID(0)
  109. {
  110. }
  111. bool LLEventNotification::handleResponse(const LLSD& notification,
  112. const LLSD& response)
  113. {
  114. S32 option = LLNotification::getSelectedOption(notification, response);
  115. switch (option)
  116. {
  117. case 0:
  118. gAgent.teleportViaLocation(getEventPosGlobal());
  119. if (gFloaterWorldMapp)
  120. {
  121. gFloaterWorldMapp->trackLocation(getEventPosGlobal());
  122. }
  123. break;
  124. case 1:
  125. gDisplayEventHack = true;
  126. HBFloaterSearch::showEvents(getEventID());
  127. break;
  128. default:
  129. break;
  130. }
  131. // We could clean up the notification on the server now if we really wanted
  132. // to.
  133. return false;
  134. }
  135. bool LLEventNotification::load(const LLSD& response)
  136. {
  137. bool event_ok = true;
  138. if (response.has("event_id"))
  139. {
  140. mEventID = response["event_id"].asInteger();
  141. }
  142. else
  143. {
  144. event_ok = false;
  145. }
  146. if (response.has("event_name"))
  147. {
  148. mEventName = response["event_name"].asString();
  149. llinfos << "Event: " << mEventName << llendl;
  150. }
  151. else
  152. {
  153. event_ok = false;
  154. }
  155. mEventDateStr.clear();
  156. if (response.has("event_date"))
  157. {
  158. const LLSD& llsddate = response["event_date"];
  159. LLDate date;
  160. bool is_iso8601_date = false;
  161. if (llsddate.isDate())
  162. {
  163. date = llsddate.asDate();
  164. is_iso8601_date = true;
  165. }
  166. else if (date.fromString(llsddate.asString()))
  167. {
  168. is_iso8601_date = true;
  169. }
  170. if (is_iso8601_date)
  171. {
  172. mEventDateStr = "[" + LLTrans::getString("LTimeYear") + "]-[" +
  173. LLTrans::getString("LTimeMthNum") + "]-[" +
  174. LLTrans::getString("LTimeDay") + "] [" +
  175. LLTrans::getString("LTimeHour") + "]:[" +
  176. LLTrans::getString("LTimeMin") + "]:[" +
  177. LLTrans::getString("LTimeSec") + "]";
  178. LLSD substitution;
  179. substitution["datetime"] = date;
  180. LLStringUtil::format(mEventDateStr, substitution);
  181. }
  182. else
  183. {
  184. mEventDateStr = llsddate.asString();
  185. }
  186. llinfos << "EventDate: " << mEventDateStr << llendl;
  187. }
  188. if (response.has("event_date_ut"))
  189. {
  190. std::string date = response["event_date_ut"].asString();
  191. llinfos << "EventDate: " << date << llendl;
  192. mEventDate = strtoul(date.c_str(), NULL, 10);
  193. if (mEventDateStr.empty())
  194. {
  195. mEventDateStr = get_timestamp(mEventDate);
  196. }
  197. }
  198. else
  199. {
  200. event_ok = false;
  201. }
  202. S32 grid_x = 0;
  203. if (response.has("grid_x"))
  204. {
  205. grid_x = response["grid_x"].asInteger();
  206. llinfos << "GridX: " << grid_x << llendl;
  207. }
  208. else
  209. {
  210. event_ok = false;
  211. }
  212. S32 grid_y = 0;
  213. if (response.has("grid_y"))
  214. {
  215. grid_y = response["grid_y"].asInteger();
  216. llinfos << "GridY: " << grid_y << llendl;
  217. }
  218. else
  219. {
  220. event_ok = false;
  221. }
  222. S32 x_region = 0;
  223. if (response.has("x_region"))
  224. {
  225. x_region = response["x_region"].asInteger();
  226. llinfos << "RegionX: " << x_region << llendl;
  227. }
  228. else
  229. {
  230. event_ok = false;
  231. }
  232. S32 y_region = 0;
  233. if (response.has("y_region"))
  234. {
  235. y_region = response["y_region"].asInteger();
  236. llinfos << "RegionY: " << y_region << llendl;
  237. }
  238. else
  239. {
  240. event_ok = false;
  241. }
  242. mEventPosGlobal.mdV[VX] = grid_x * 256 + x_region;
  243. mEventPosGlobal.mdV[VY] = grid_y * 256 + y_region;
  244. mEventPosGlobal.mdV[VZ] = 0.f;
  245. return event_ok;
  246. }
  247. bool LLEventNotification::load(const LLEventInfo& event_info)
  248. {
  249. mEventID = event_info.mID;
  250. mEventName = event_info.mName;
  251. mEventDateStr = event_info.mTimeStr;
  252. mEventDate = event_info.mUnixTime;
  253. mEventPosGlobal = event_info.mPosGlobal;
  254. return true;
  255. }
  256. ///////////////////////////////////////////////////////////////////////////////
  257. // LLEventNotifier class
  258. ///////////////////////////////////////////////////////////////////////////////
  259. LLEventNotifier gEventNotifier;
  260. LLEventNotifier::LLEventNotifier()
  261. {
  262. }
  263. LLEventNotifier::~LLEventNotifier()
  264. {
  265. map_t::iterator iter;
  266. for (map_t::iterator iter = mEventNotifications.begin(),
  267. end = mEventNotifications.end();
  268. iter != end; ++iter)
  269. {
  270. delete iter->second;
  271. }
  272. }
  273. void LLEventNotifier::update()
  274. {
  275. if (mNotificationTimer.getElapsedTimeF32() > 30.f)
  276. {
  277. // Check our notifications again and send out updates if they happen.
  278. time_t alert_time = time_corrected() + 5 * 60;
  279. map_t::iterator iter;
  280. for (iter = mEventNotifications.begin();
  281. iter != mEventNotifications.end();)
  282. {
  283. LLEventNotification* np = iter->second;
  284. if (np && np->getEventDate() < alert_time)
  285. {
  286. LLSD args;
  287. args["NAME"] = np->getEventName();
  288. args["DATE"] = np->getEventDateStr();
  289. gNotifications.add("EventNotification", args, LLSD(),
  290. boost::bind(&LLEventNotification::handleResponse,
  291. np, _1, _2));
  292. mEventNotifications.erase(iter++);
  293. }
  294. else
  295. {
  296. ++iter;
  297. }
  298. }
  299. mNotificationTimer.reset();
  300. }
  301. }
  302. void LLEventNotifier::load(const LLSD& event_options)
  303. {
  304. for (LLSD::array_const_iterator it = event_options.beginArray(),
  305. end = event_options.endArray();
  306. it != end; ++it)
  307. {
  308. LLEventNotification* new_enp = new LLEventNotification();
  309. if (new_enp->load(*it))
  310. {
  311. mEventNotifications[new_enp->getEventID()] = new_enp;
  312. }
  313. else
  314. {
  315. delete new_enp;
  316. }
  317. }
  318. }
  319. bool LLEventNotifier::hasNotification(U32 event_id)
  320. {
  321. return mEventNotifications.count(event_id) != 0;
  322. }
  323. void LLEventNotifier::add(LLEventInfo& event_info)
  324. {
  325. // We need to tell the simulator that we want to pay attention to
  326. // this event, as well as add it to our list.
  327. if (mEventNotifications.count(event_info.mID) != 0)
  328. {
  329. // We already have a notification for this event, don't bother.
  330. return;
  331. }
  332. // Push up a message to tell the server we have this notification.
  333. LLMessageSystem* msg = gMessageSystemp;
  334. msg->newMessage("EventNotificationAddRequest");
  335. msg->nextBlockFast(_PREHASH_AgentData);
  336. msg->addUUIDFast(_PREHASH_AgentID, gAgentID );
  337. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  338. msg->nextBlock("EventData");
  339. msg->addU32("EventID", event_info.mID);
  340. gAgent.sendReliableMessage();
  341. LLEventNotification* enp = new LLEventNotification;
  342. enp->load(event_info);
  343. mEventNotifications[event_info.mID] = enp;
  344. }
  345. void LLEventNotifier::remove(U32 event_id)
  346. {
  347. map_t::iterator iter;
  348. iter = mEventNotifications.find(event_id);
  349. if (iter == mEventNotifications.end())
  350. {
  351. // We do not have a notification for this event, do not bother.
  352. return;
  353. }
  354. // Push up a message to tell the server to remove this notification.
  355. LLMessageSystem* msg = gMessageSystemp;
  356. msg->newMessage("EventNotificationRemoveRequest");
  357. msg->nextBlockFast(_PREHASH_AgentData);
  358. msg->addUUIDFast(_PREHASH_AgentID, gAgentID );
  359. msg->addUUIDFast(_PREHASH_SessionID, gAgentSessionID);
  360. msg->nextBlock("EventData");
  361. msg->addU32("EventID", event_id);
  362. gAgent.sendReliableMessage();
  363. delete iter->second;
  364. mEventNotifications.erase(iter);
  365. }