From 954b420446812705d81bda48eb2026a1ff3b9365 Mon Sep 17 00:00:00 2001 From: hikerstk Date: Wed, 23 Mar 2011 03:57:49 +0000 Subject: [PATCH] Started to add support for downloading news from the addon server at a specified interval only (e.g. only download every 2nd day). Not fully working yet, might not work on linux/mac atm. git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@8030 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/Makefile.am | 1 + src/addons/network_http.cpp | 27 +++++++++++-- src/config/user_config.cpp | 65 +++++++++++++++++++++++++++++++ src/config/user_config.hpp | 47 +++++++++++++++++++++- src/ide/vc9/supertuxkart.vcproj | 4 ++ src/io/xml_node.cpp | 16 ++++++++ src/io/xml_node.hpp | 6 ++- src/utils/time.hpp | 69 +++++++++++++++++++++++++++++++++ 8 files changed, 228 insertions(+), 7 deletions(-) create mode 100644 src/utils/time.hpp diff --git a/src/Makefile.am b/src/Makefile.am index e87c91678..c857057d7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -431,6 +431,7 @@ supertuxkart_SOURCES = \ utils/random_generator.hpp \ utils/string_utils.cpp \ utils/string_utils.hpp \ + utils/time.hpp \ utils/translation.cpp \ utils/translation.hpp \ utils/vec3.cpp \ diff --git a/src/addons/network_http.cpp b/src/addons/network_http.cpp index 741ff387f..2264973ae 100644 --- a/src/addons/network_http.cpp +++ b/src/addons/network_http.cpp @@ -23,8 +23,10 @@ #include #if defined(WIN32) && !defined(__CYGWIN__) +# include # define isnan _isnan #else +# include # include #endif @@ -34,6 +36,7 @@ #include "states_screens/addons_screen.hpp" #include "states_screens/main_menu_screen.hpp" #include "utils/string_utils.hpp" +#include "utils/time.hpp" #if defined(WIN32) && !defined(__CYGWIN__) // Use Sleep, which takes time in msecs. It must be defined after the @@ -79,13 +82,29 @@ void *NetworkHttp::mainLoop(void *obj) { NetworkHttp *me=(NetworkHttp*)obj; - // Initialise the online portion of the addons manager. - if(UserConfigParams::m_verbosity>=3) + // The news message must be updated if either it has never been updated, + // or if the time of the last update was more than news_frequency ago. + bool download = UserConfigParams::m_news_last_updated==0 || + UserConfigParams::m_news_last_updated + +UserConfigParams::m_news_frequency + > Time::getTimeSinceEpoch(); + + if(!download) + { + // If there is no old news message file, force a new download + std::string xml_file = file_manager->getAddonsFile("news.xml"); + if(xml_file=="") + download=true; + } + + // Initialise the online portion of the addons manager. + if(download && UserConfigParams::m_verbosity>=3) printf("[addons] Downloading list.\n"); - if(me->downloadFileSynchron("news.xml")) + if(!download || me->downloadFileSynchron("news.xml")) { std::string xml_file = file_manager->getAddonsFile("news.xml"); - + if(download) + UserConfigParams::m_news_last_updated = Time::getTimeSinceEpoch(); const XMLNode *xml = new XMLNode(xml_file); me->checkNewServer(xml); me->updateNews(xml); diff --git a/src/config/user_config.cpp b/src/config/user_config.cpp index ddd893d57..e1bce9064 100644 --- a/src/config/user_config.cpp +++ b/src/config/user_config.cpp @@ -170,6 +170,71 @@ void IntUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node) // --------------------------------------------------------------------------------------- +TimeUserConfigParam::TimeUserConfigParam(Time::TimeType default_value, + const char* param_name, + const char* comment) +{ + m_value = default_value; + m_default_value = default_value; + + this->paramName = param_name; + all_params.push_back(this); + if(comment != NULL) this->comment = comment; +} + +TimeUserConfigParam::TimeUserConfigParam(Time::TimeType defaultValue, + const char* paramName, + GroupUserConfigParam* group, + const char* comment) +{ + m_value = defaultValue; + m_default_value = defaultValue; + + this->paramName = paramName; + group->addChild(this); + if(comment != NULL) this->comment = comment; +} + +void TimeUserConfigParam::write(XMLWriter& stream) const +{ + if(comment.size() > 0) stream << L" \n"; + std::ostringstream o; + o<\n\n"; +} + +irr::core::stringw TimeUserConfigParam::toString() const +{ + // irrString does not have a += with a 64-bit int type, so + // we can't use an irrlicht's stringw directly. Since it's only a + // number, we can use std::string, and convert to stringw + + std::string tmp; + std::ostringstream o; + o<getNode( paramName ); + if(child == NULL) + { + //std::cout << "Couldn't find int parameter " << paramName << std::endl; + return; + } + + child->get( "value", &m_value ); + //std::cout << "read int " << paramName << ", value=" << value << std::endl; +} +void TimeUserConfigParam::findYourDataInAnAttributeOf(const XMLNode* node) +{ + node->get( paramName, &m_value ); +} + +// --------------------------------------------------------------------------------------- + StringUserConfigParam::StringUserConfigParam(const char* defaultValue, const char* paramName, const char* comment) { diff --git a/src/config/user_config.hpp b/src/config/user_config.hpp index a8195a6e9..18046a24a 100644 --- a/src/config/user_config.hpp +++ b/src/config/user_config.hpp @@ -53,6 +53,7 @@ using irr::core::stringw; #include "utils/constants.hpp" #include "utils/no_copy.hpp" #include "utils/ptr_vector.hpp" +#include "utils/time.hpp" class XMLNode; class XMLWriter; @@ -110,6 +111,32 @@ public: int& operator=(const IntUserConfigParam& v) { m_value = (int)v; return m_value; } }; +class TimeUserConfigParam : public UserConfigParam +{ + Time::TimeType m_value; + Time::TimeType m_default_value; + +public: + + TimeUserConfigParam(Time::TimeType defaultValue, const char* paramName, + const char* comment = NULL); + TimeUserConfigParam(Time::TimeType defaultValue, const char* paramName, + GroupUserConfigParam* group, const char* comment=NULL); + + void write(XMLWriter& stream) const; + void findYourDataInAChildOf(const XMLNode* node); + void findYourDataInAnAttributeOf(const XMLNode* node); + + irr::core::stringw toString() const; + void revertToDefaults() { m_value = m_default_value; } + operator Time::TimeType() const { return m_value; } + Time::TimeType& operator=(const Time::TimeType& v) + { m_value = v; return m_value; } + Time::TimeType& operator=(const TimeUserConfigParam& v) + { m_value = (int)v; return m_value; } +}; + + class StringUserConfigParam : public UserConfigParam { std::string m_value; @@ -384,8 +411,26 @@ namespace UserConfigParams PARAM_PREFIX StringUserConfigParam m_skin_file PARAM_DEFAULT( StringUserConfigParam("Peach.stkskin", "skin_file", "Name of the skin to use") ); + // ---- Addon server related entries + PARAM_PREFIX GroupUserConfigParam m_addon_group + PARAM_DEFAULT( GroupUserConfigParam("AddonAndNews", + "Addon and news related settings") ); + PARAM_PREFIX StringUserConfigParam m_server_addons - PARAM_DEFAULT( StringUserConfigParam("http://download.tuxfamily.org/stkaddons/0.7/", "server_addons", "The server used for addon.") ); + PARAM_DEFAULT( StringUserConfigParam("http://stkaddons.tuxfamily.org/dl/xml", + "server_addons", + &m_addon_group, + "The server used for addon.") ); + + PARAM_PREFIX TimeUserConfigParam m_news_last_updated + PARAM_DEFAULT( TimeUserConfigParam(0, "last_updated", + &m_addon_group, + "Time news was updated last.") ); + + PARAM_PREFIX IntUserConfigParam m_news_frequency + PARAM_DEFAULT( IntUserConfigParam(0, "news_frequency", + &m_addon_group, + "How often news should be updated.") ); PARAM_PREFIX StringUserConfigParam m_language PARAM_DEFAULT( StringUserConfigParam("system", "language", "Which language to use (language code or 'system')") ); diff --git a/src/ide/vc9/supertuxkart.vcproj b/src/ide/vc9/supertuxkart.vcproj index 985ee65ff..162f21520 100644 --- a/src/ide/vc9/supertuxkart.vcproj +++ b/src/ide/vc9/supertuxkart.vcproj @@ -1436,6 +1436,10 @@ RelativePath="..\..\utils\synchronised.hpp" > + + diff --git a/src/io/xml_node.cpp b/src/io/xml_node.cpp index 7974e0093..4697d93e9 100644 --- a/src/io/xml_node.cpp +++ b/src/io/xml_node.cpp @@ -302,6 +302,22 @@ int XMLNode::get(const std::string &attribute, int *value) const return 1; } // get(int) +// ---------------------------------------------------------------------------- +int XMLNode::get(const std::string &attribute, Time::TimeType *value) const +{ + std::string s; + if(!get(attribute, &s)) return 0; + + if (!StringUtils::parseString(s, value)) + { + fprintf(stderr, "[XMLNode] WARNING: Expected int but found '%s' for attribute '%s' of node '%s' in file %s\n", + s.c_str(), attribute.c_str(), m_name.c_str(), m_file_name.c_str()); + return 0; + } + + return 1; +} // get(TimeType) + // ---------------------------------------------------------------------------- int XMLNode::get(const std::string &attribute, unsigned int *value) const { diff --git a/src/io/xml_node.hpp b/src/io/xml_node.hpp index d725238b2..015618657 100644 --- a/src/io/xml_node.hpp +++ b/src/io/xml_node.hpp @@ -20,14 +20,15 @@ #ifndef HEADER_XML_NODE_HPP #define HEADER_XML_NODE_HPP -#include "utils/no_copy.hpp" - #include #include #include #include "irrlicht.h" using namespace irr; +#include "utils/no_copy.hpp" +#include "utils/time.hpp" + class Vec3; /** @@ -64,6 +65,7 @@ public: int get(const std::string &attribute, core::stringw *value) const; int get(const std::string &attribute, int *value) const; int get(const std::string &attribute, unsigned int *value) const; + int get(const std::string &attribute, Time::TimeType *value) const; int get(const std::string &attribute, float *value) const; int get(const std::string &attribute, bool *value) const; int get(const std::string &attribute, Vec3 *value) const; diff --git a/src/utils/time.hpp b/src/utils/time.hpp new file mode 100644 index 000000000..93eb26b48 --- /dev/null +++ b/src/utils/time.hpp @@ -0,0 +1,69 @@ +// $Id$ +// +// SuperTuxKart - a fun racing game with go-kart +// Copyright (C) 2004 Steve Baker +// +// 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 3 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +#ifndef HEADER_TIME_HPP +#define HEADER_TIME_HPP + +#ifdef WIN32 +# define _WINSOCKAPI_ +# include +#else +# include +#endif + +class Time +{ +public: + +#ifdef WIN32 + typedef unsigned __int64 TimeType; +#else + typedef uint_least64_t TimeType; +#endif + + static TimeType getTimeSinceEpoch() + { +#ifdef WIN32 + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + TimeType t = ft.dwHighDateTime; + t <<= 32; + t /= 10; + // The Unix epoch starts on Jan 1 1970. Need to subtract + // the difference in seconds from Jan 1 1601. +# if defined(_MSC_VER) || defined(_MSC_EXTENSIONS) +# define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64 +# else +# define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL +# endif + t -= DELTA_EPOCH_IN_MICROSECS; + + t |= ft.dwLowDateTime; + // Convert to seconds since epoch + t /= 1000000UL; + return t; +#else + struct timeval tv; + gettimeofday(&tv, NULL); + return tv.tv_sec; +#endif + }; // getTimeSinceEpoch + +}; // class time +#endif \ No newline at end of file