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