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/MenuModeSkirmish.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 "utils/LogManager.h"
30 #include "gamemap/MapHandler.h"
31 #include "utils/ConfigManager.h"
32 #include "utils/ResourceManager.h"
33
34 #include <CEGUI/CEGUI.h>
35 #include "boost/filesystem.hpp"
36
MenuModeSkirmish(ModeManager * modeManager)37 MenuModeSkirmish::MenuModeSkirmish(ModeManager* modeManager):
38 AbstractApplicationMode(modeManager, ModeManager::MENU_SKIRMISH)
39 {
40 CEGUI::Window* window = modeManager->getGui().getGuiSheet(Gui::guiSheet::skirmishMenu);
41
42 // Fills the Level type combo box with the available level types.
43 const CEGUI::Image* selImg = &CEGUI::ImageManager::getSingleton().get("OpenDungeonsSkin/SelectionBrush");
44 CEGUI::Combobox* levelTypeCb = static_cast<CEGUI::Combobox*>(window->getChild(Gui::SKM_LIST_LEVEL_TYPES));
45 levelTypeCb->resetList();
46
47 CEGUI::ListboxTextItem* item = new CEGUI::ListboxTextItem("Official Skirmish Levels", 0);
48 item->setSelectionBrushImage(selImg);
49 levelTypeCb->addItem(item);
50
51 item = new CEGUI::ListboxTextItem("Official Multiplayer Levels", 1);
52 item->setSelectionBrushImage(selImg);
53 levelTypeCb->addItem(item);
54
55 item = new CEGUI::ListboxTextItem("Custom Skirmish Levels", 2);
56 item->setSelectionBrushImage(selImg);
57 levelTypeCb->addItem(item);
58
59 item = new CEGUI::ListboxTextItem("Custom Multiplayer Levels", 3);
60 item->setSelectionBrushImage(selImg);
61 levelTypeCb->addItem(item);
62
63 addEventConnection(
64 window->getChild(Gui::SKM_BUTTON_LAUNCH)->subscribeEvent(
65 CEGUI::PushButton::EventClicked,
66 CEGUI::Event::Subscriber(&MenuModeSkirmish::launchSelectedButtonPressed, this)
67 )
68 );
69 addEventConnection(
70 window->getChild(Gui::SKM_LIST_LEVELS)->subscribeEvent(
71 CEGUI::Listbox::EventMouseDoubleClick,
72 CEGUI::Event::Subscriber(&MenuModeSkirmish::launchSelectedButtonPressed, this)
73 )
74 );
75 addEventConnection(
76 window->getChild(Gui::SKM_LIST_LEVELS)->subscribeEvent(
77 CEGUI::Listbox::EventMouseClick,
78 CEGUI::Event::Subscriber(&MenuModeSkirmish::updateDescription, this)
79 )
80 );
81 addEventConnection(
82 window->getChild(Gui::SKM_BUTTON_BACK)->subscribeEvent(
83 CEGUI::PushButton::EventClicked,
84 CEGUI::Event::Subscriber(&AbstractApplicationMode::goBack,
85 static_cast<AbstractApplicationMode*>(this))
86 )
87 );
88 addEventConnection(
89 window->getChild("LevelWindowFrame")->subscribeEvent(
90 CEGUI::FrameWindow::EventCloseClicked,
91 CEGUI::Event::Subscriber(&AbstractApplicationMode::goBack,
92 static_cast<AbstractApplicationMode*>(this))
93 )
94 );
95
96 addEventConnection(
97 window->getChild(Gui::SKM_LIST_LEVEL_TYPES)->subscribeEvent(
98 CEGUI::Combobox::EventListSelectionAccepted,
99 CEGUI::Event::Subscriber(&MenuModeSkirmish::updateFilesList, this)
100 )
101 );
102 }
103
activate()104 void MenuModeSkirmish::activate()
105 {
106 // Loads the corresponding Gui sheet.
107 getModeManager().getGui().loadGuiSheet(Gui::guiSheet::skirmishMenu);
108
109 giveFocus();
110
111 // Play the main menu music
112 MusicPlayer::getSingleton().play(ConfigManager::getSingleton().getMainMenuMusic());
113
114 GameMap* gameMap = ODFrameListener::getSingleton().getClientGameMap();
115 gameMap->clearAll();
116 gameMap->setGamePaused(true);
117
118 // Select skirmish
119 CEGUI::Combobox* levelTypeCb = static_cast<CEGUI::Combobox*>(getModeManager().getGui().
120 getGuiSheet(Gui::skirmishMenu)->getChild(Gui::SKM_LIST_LEVEL_TYPES));
121 levelTypeCb->setItemSelectState(static_cast<size_t>(0), true);
122 updateFilesList();
123
124 // Set the player name if valid. (Will use the defaut one if not.)
125 ConfigManager& config = ConfigManager::getSingleton();
126 std::string nickname = config.getGameValue(Config::NICKNAME, std::string(), false);
127 if (!nickname.empty())
128 ODFrameListener::getSingleton().getClientGameMap()->setLocalPlayerNick(nickname);
129 }
130
updateFilesList(const CEGUI::EventArgs &)131 bool MenuModeSkirmish::updateFilesList(const CEGUI::EventArgs&)
132 {
133 CEGUI::Window* window = getModeManager().getGui().getGuiSheet(Gui::guiSheet::skirmishMenu);
134 CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(window->getChild(Gui::SKM_LIST_LEVELS));
135
136 CEGUI::Combobox* levelTypeCb = static_cast<CEGUI::Combobox*>(window->getChild(Gui::SKM_LIST_LEVEL_TYPES));
137
138 CEGUI::Window* loadText = window->getChild(Gui::SKM_TEXT_LOADING);
139 loadText->setText("");
140 mFilesList.clear();
141 mDescriptionList.clear();
142 levelSelectList->resetList();
143
144 std::string levelPath;
145 size_t selection = levelTypeCb->getItemIndex(levelTypeCb->getSelectedItem());
146 switch (selection)
147 {
148 default:
149 case 0:
150 levelPath = ResourceManager::getSingleton().getGameLevelPathSkirmish();
151 break;
152 case 1:
153 levelPath = ResourceManager::getSingleton().getGameLevelPathMultiplayer();
154 break;
155 case 2:
156 levelPath = ResourceManager::getSingleton().getUserLevelPathSkirmish();
157 break;
158 case 3:
159 levelPath = ResourceManager::getSingleton().getUserLevelPathMultiplayer();
160 break;
161 }
162
163 if(Helper::fillFilesList(levelPath, mFilesList, MapHandler::LEVEL_EXTENSION))
164 {
165 for (uint32_t n = 0; n < mFilesList.size(); ++n)
166 {
167 std::string filename = mFilesList[n];
168
169 LevelInfo levelInfo;
170 std::string mapName;
171 std::string mapDescription;
172 if(MapHandler::getMapInfo(filename, levelInfo))
173 {
174 mapName = levelInfo.mLevelName;
175 mapDescription = levelInfo.mLevelDescription;
176 }
177 else
178 {
179 mapName = "invalid map";
180 mapDescription = "invalid map";
181 }
182
183 mDescriptionList.push_back(mapDescription);
184 CEGUI::ListboxTextItem* item = new CEGUI::ListboxTextItem(mapName);
185 item->setID(n);
186 item->setSelectionBrushImage("OpenDungeonsSkin/SelectionBrush");
187 levelSelectList->addItem(item);
188 }
189 }
190
191 updateDescription();
192 return true;
193 }
194
launchSelectedButtonPressed(const CEGUI::EventArgs &)195 bool MenuModeSkirmish::launchSelectedButtonPressed(const CEGUI::EventArgs&)
196 {
197 CEGUI::Window* mainWin = getModeManager().getGui().getGuiSheet(Gui::skirmishMenu);
198 CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(mainWin->getChild(Gui::SKM_LIST_LEVELS));
199
200 if(levelSelectList->getSelectedCount() == 0)
201 {
202 mainWin->getChild(Gui::SKM_TEXT_LOADING)->setText("Please select a level first.");
203 return true;
204 }
205
206 mainWin->getChild(Gui::SKM_TEXT_LOADING)->setText("Loading...");
207
208 CEGUI::ListboxItem* selItem = levelSelectList->getFirstSelectedItem();
209 int id = selItem->getID();
210
211 const std::string& level = mFilesList[id];
212 // In single player mode, we act as a server
213 const std::string& nickname = ODFrameListener::getSingleton().getClientGameMap()->getLocalPlayerNick();
214 if(!ODServer::getSingleton().startServer(nickname, level, ServerMode::ModeGameSinglePlayer, false))
215 {
216 OD_LOG_ERR("Could not start server for single player game !!!");
217 mainWin->getChild(Gui::SKM_TEXT_LOADING)->setText("ERROR: Could not start server for single player game !!!");
218 return true;
219 }
220
221 int port = ODServer::getSingleton().getNetworkPort();
222 uint32_t timeout = ConfigManager::getSingleton().getClientConnectionTimeout();
223 std::string replayFilename = ResourceManager::getSingleton().getReplayDataPath()
224 + ResourceManager::getSingleton().buildReplayFilename();
225 if(!ODClient::getSingleton().connect("localhost", port, timeout, replayFilename))
226 {
227 OD_LOG_ERR("Could not connect to server for single player game !!!");
228 mainWin->getChild(Gui::SKM_TEXT_LOADING)->setText("Error: Couldn't connect to local server!");
229 return true;
230 }
231 return true;
232 }
233
updateDescription(const CEGUI::EventArgs &)234 bool MenuModeSkirmish::updateDescription(const CEGUI::EventArgs&)
235 {
236 // Get the level corresponding id
237 CEGUI::Window* mainWin = getModeManager().getGui().getGuiSheet(Gui::skirmishMenu);
238 CEGUI::Listbox* levelSelectList = static_cast<CEGUI::Listbox*>(mainWin->getChild(Gui::SKM_LIST_LEVELS));
239
240 CEGUI::Window* descTxt = mainWin->getChild("LevelWindowFrame/MapDescriptionText");
241
242 if(levelSelectList->getSelectedCount() == 0)
243 {
244 descTxt->setText("");
245 return true;
246 }
247
248 getModeManager().getGui().playButtonClickSound();
249
250 CEGUI::ListboxItem* selItem = levelSelectList->getFirstSelectedItem();
251 int id = selItem->getID();
252
253 std::string description = mDescriptionList[id];
254 descTxt->setText(reinterpret_cast<const CEGUI::utf8*>(description.c_str()));
255
256 return true;
257 }
258