1 /*
2  *  Copyright (C) 2011-2016  OpenDungeons Team
3  *
4  *  This program is free software: you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation, either version 3 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "modes/MenuModeLoad.h"
19 
20 #include "utils/Helper.h"
21 #include "render/Gui.h"
22 #include "modes/ModeManager.h"
23 #include "sound/MusicPlayer.h"
24 #include "gamemap/GameMap.h"
25 #include "render/ODFrameListener.h"
26 #include "network/ODServer.h"
27 #include "network/ODClient.h"
28 #include "network/ServerMode.h"
29 #include "network/ServerNotification.h"
30 #include "utils/LogManager.h"
31 #include "gamemap/MapHandler.h"
32 #include "utils/ConfigManager.h"
33 #include "utils/ResourceManager.h"
34 
35 #include <CEGUI/CEGUI.h>
36 #include "boost/filesystem.hpp"
37 
38 const std::string SAVEGAME_EXTENSION = ".level";
39 
MenuModeLoad(ModeManager * modeManager)40 MenuModeLoad::MenuModeLoad(ModeManager *modeManager):
41     AbstractApplicationMode(modeManager, ModeManager::MENU_LOAD_SAVEDGAME)
42 {
43     CEGUI::Window* window = modeManager->getGui().getGuiSheet(Gui::guiSheet::loadSavedGameMenu);
44     addEventConnection(
45         window->getChild("LevelWindowFrame/BackButton")->subscribeEvent(
46             CEGUI::PushButton::EventClicked,
47             CEGUI::Event::Subscriber(&AbstractApplicationMode::goBack,
48                                      static_cast<AbstractApplicationMode*>(this))
49         )
50     );
51     addEventConnection(
52         window->getChild("LevelWindowFrame/LaunchButton")->subscribeEvent(
53             CEGUI::PushButton::EventClicked,
54             CEGUI::Event::Subscriber(&MenuModeLoad::launchSelectedButtonPressed, this)
55         )
56     );
57     addEventConnection(
58         window->getChild("LevelWindowFrame/DeleteButton")->subscribeEvent(
59             CEGUI::PushButton::EventClicked,
60             CEGUI::Event::Subscriber(&MenuModeLoad::deleteSelectedButtonPressed, this)
61         )
62     );
63     addEventConnection(
64         window->getChild("LevelWindowFrame/SaveGameSelect")->subscribeEvent(
65             CEGUI::Listbox::EventMouseClick,
66             CEGUI::Event::Subscriber(&MenuModeLoad::updateDescription, this)
67         )
68     );
69     addEventConnection(
70         window->getChild("LevelWindowFrame/SaveGameSelect")->subscribeEvent(
71             CEGUI::Listbox::EventMouseDoubleClick,
72             CEGUI::Event::Subscriber(&MenuModeLoad::launchSelectedButtonPressed, this)
73         )
74     );
75     addEventConnection(
76         window->getChild("LevelWindowFrame")->subscribeEvent(
77             CEGUI::FrameWindow::EventCloseClicked,
78             CEGUI::Event::Subscriber(&AbstractApplicationMode::goBack,
79                                      static_cast<AbstractApplicationMode*>(this))
80         )
81     );
82 }
83 
activate()84 void MenuModeLoad::activate()
85 {
86     // Loads the corresponding Gui sheet.
87     getModeManager().getGui().loadGuiSheet(Gui::guiSheet::loadSavedGameMenu);
88 
89     giveFocus();
90 
91     // Play the main menu music
92     MusicPlayer::getSingleton().play(ConfigManager::getSingleton().getMainMenuMusic());
93 
94 
95     GameMap* gameMap = ODFrameListener::getSingleton().getClientGameMap();
96     gameMap->clearAll();
97     gameMap->setGamePaused(true);
98 
99     CEGUI::Window* tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LevelWindowFrame/SaveGameSelect");
100     CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(tmpWin);
101 
102     tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LoadingText");
103     tmpWin->hide();
104     mFilesList.clear();
105     levelSelectList->resetList();
106 
107     std::string levelPath = ResourceManager::getSingleton().getSaveGamePath();
108     if(Helper::fillFilesList(levelPath, mFilesList, SAVEGAME_EXTENSION))
109     {
110         for (uint32_t n = 0; n < mFilesList.size(); ++n)
111         {
112             std::string filename = boost::filesystem::path(mFilesList[n]).filename().string();
113             CEGUI::ListboxTextItem* item = new CEGUI::ListboxTextItem(filename);
114             item->setID(n);
115             item->setSelectionBrushImage("OpenDungeonsSkin/SelectionBrush");
116             levelSelectList->addItem(item);
117         }
118     }
119 }
120 
launchSelectedButtonPressed(const CEGUI::EventArgs &)121 bool MenuModeLoad::launchSelectedButtonPressed(const CEGUI::EventArgs&)
122 {
123     CEGUI::Window* tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LevelWindowFrame/SaveGameSelect");
124     CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(tmpWin);
125 
126     if(levelSelectList->getSelectedCount() == 0)
127     {
128         tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LoadingText");
129         tmpWin->setText("Please select a saved game first.");
130         tmpWin->show();
131         return true;
132     }
133 
134     std::string nickname = ConfigManager::getSingleton().getGameValue(Config::NICKNAME, std::string(), false);
135     if (!nickname.empty())
136         ODFrameListener::getSingleton().getClientGameMap()->setLocalPlayerNick(nickname);
137 
138     tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LoadingText");
139     tmpWin->setText("Loading...");
140     tmpWin->show();
141 
142     CEGUI::ListboxItem* selItem = levelSelectList->getFirstSelectedItem();
143     int id = selItem->getID();
144 
145     const std::string& level = mFilesList[id];
146     // In single player mode, we act as a server
147     if(!ODServer::getSingleton().startServer(nickname, level, ServerMode::ModeGameLoaded, false))
148     {
149         OD_LOG_ERR("Could not start server for single player game !!!");
150         tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LoadingText");
151         tmpWin->setText("ERROR: Could not start server for single player game !!!");
152         tmpWin->show();
153         return true;
154     }
155 
156     int port = ODServer::getSingleton().getNetworkPort();
157     uint32_t timeout = ConfigManager::getSingleton().getClientConnectionTimeout();
158     std::string replayFilename = ResourceManager::getSingleton().getReplayDataPath()
159         + ResourceManager::getSingleton().buildReplayFilename();
160     if(!ODClient::getSingleton().connect("localhost", port, timeout, replayFilename))
161     {
162         OD_LOG_ERR("Could not connect to server for single player game !!!");
163         tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LoadingText");
164         tmpWin->setText("Error: Couldn't connect to local server!");
165         tmpWin->show();
166         return true;
167     }
168     return true;
169 }
170 
deleteSelectedButtonPressed(const CEGUI::EventArgs &)171 bool MenuModeLoad::deleteSelectedButtonPressed(const CEGUI::EventArgs&)
172 {
173     CEGUI::Window* tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LevelWindowFrame/SaveGameSelect");
174     CEGUI::Listbox* selectList = static_cast<CEGUI::Listbox*>(tmpWin);
175 
176     if(selectList->getSelectedCount() == 0)
177     {
178         tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LoadingText");
179         tmpWin->setText("Please select a saved game first.");
180         tmpWin->show();
181         return true;
182     }
183 
184     CEGUI::ListboxItem* selItem = selectList->getFirstSelectedItem();
185     int id = selItem->getID();
186 
187     const std::string& levelFile = mFilesList[id];
188     if(!boost::filesystem::remove(levelFile))
189     {
190         OD_LOG_ERR("Could not delete saved game !!!");
191         tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LoadingText");
192         tmpWin->setText("Error: Couldn't delete saved game!");
193         tmpWin->show();
194         return true;
195     }
196 
197     activate();
198     return true;
199 }
200 
updateDescription(const CEGUI::EventArgs &)201 bool MenuModeLoad::updateDescription(const CEGUI::EventArgs&)
202 {
203     // Get the level corresponding id
204     CEGUI::Window* tmpWin = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LevelWindowFrame/SaveGameSelect");
205     CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(tmpWin);
206 
207     CEGUI::Window* descTxt = getModeManager().getGui().getGuiSheet(Gui::loadSavedGameMenu)->getChild("LevelWindowFrame/MapDescriptionText");
208 
209     if(levelSelectList->getSelectedCount() == 0)
210     {
211         descTxt->setText("");
212         return true;
213     }
214 
215     getModeManager().getGui().playButtonClickSound();
216 
217     CEGUI::ListboxItem* selItem = levelSelectList->getFirstSelectedItem();
218     int id = selItem->getID();
219 
220     std::string filename = mFilesList[id];
221 
222     LevelInfo levelInfo;
223     std::string mapDescription;
224     if(MapHandler::getMapInfo(filename, levelInfo))
225         mapDescription = levelInfo.mLevelDescription;
226     else
227         mapDescription = "invalid map";
228 
229     descTxt->setText(mapDescription);
230 
231     return true;
232 }
233