OMG! Main Menu!

This commit is contained in:
Perttu Ahola 2011-01-23 17:29:15 +02:00
parent c0a1bcf473
commit c914cbb0a0
25 changed files with 897 additions and 272 deletions

@ -15,7 +15,6 @@
#viewing_range_nodes_min = 35 #viewing_range_nodes_min = 35
#screenW = 800 #screenW = 800
#screenH = 600 #screenH = 600
#host_game =
#port = 30000 #port = 30000
#address = kray.dy.fi #address = kray.dy.fi
#name = #name =

@ -136,7 +136,7 @@
/> />
<Tool <Tool
Name="VCLinkerTool" Name="VCLinkerTool"
AdditionalLibraryDirectories="&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&quot;;&quot;..\jthread\jthread-1.2.1\Release&quot;;&quot;..\irrlicht\irrlicht-1.7.1\lib\Win32-visualstudio&quot;;..\zlib125dll\dll32" AdditionalLibraryDirectories="&quot;C:\Program Files\Microsoft Platform SDK for Windows Server 2003 R2\Lib&quot;;&quot;..\irrlicht\irrlicht-1.7.1\lib\Win32-visualstudio&quot;;..\zlib125dll\dll32"
IgnoreDefaultLibraryNames="libcmtd.lib" IgnoreDefaultLibraryNames="libcmtd.lib"
GenerateDebugInformation="false" GenerateDebugInformation="false"
LinkTimeCodeGeneration="1" LinkTimeCodeGeneration="1"
@ -203,6 +203,10 @@
RelativePath=".\src\guiInventoryMenu.cpp" RelativePath=".\src\guiInventoryMenu.cpp"
> >
</File> </File>
<File
RelativePath=".\src\guiMainMenu.cpp"
>
</File>
<File <File
RelativePath=".\src\guiMessageMenu.cpp" RelativePath=".\src\guiMessageMenu.cpp"
> >
@ -227,6 +231,14 @@
RelativePath=".\src\irrlichtwrapper.cpp" RelativePath=".\src\irrlichtwrapper.cpp"
> >
</File> </File>
<File
RelativePath=".\src\jthread\win32\jmutex.cpp"
>
</File>
<File
RelativePath=".\src\jthread\win32\jthread.cpp"
>
</File>
<File <File
RelativePath=".\src\light.cpp" RelativePath=".\src\light.cpp"
> >

@ -10,7 +10,7 @@ add_definitions ( -DUSE_CMAKE_CONFIG_H )
if(WIN32) if(WIN32)
# Windows # Windows
# Surpress some warnings # Surpress some useless warnings
add_definitions ( /D "_CRT_SECURE_NO_DEPRECATE" /W1 ) add_definitions ( /D "_CRT_SECURE_NO_DEPRECATE" /W1 )
# Zlib stuff # Zlib stuff
set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5" set(ZLIB_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/../../zlib/zlib-1.2.5"
@ -39,6 +39,7 @@ configure_file(
) )
set(minetest_SRCS set(minetest_SRCS
guiMainMenu.cpp
porting.cpp porting.cpp
guiMessageMenu.cpp guiMessageMenu.cpp
materials.cpp materials.cpp
@ -108,8 +109,11 @@ include_directories(
set(EXECUTABLE_OUTPUT_PATH ../bin) set(EXECUTABLE_OUTPUT_PATH ../bin)
set(JTHREAD_LIBRARIES "jthread")
set(JTHREAD_SRCS "")
if(BUILD_CLIENT) if(BUILD_CLIENT)
add_executable(minetest ${minetest_SRCS}) add_executable(minetest ${minetest_SRCS} ${JTHREAD_SRCS})
target_link_libraries( target_link_libraries(
minetest minetest
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
@ -119,18 +123,18 @@ if(BUILD_CLIENT)
${BZIP2_LIBRARIES} ${BZIP2_LIBRARIES}
${PNG_LIBRARIES} ${PNG_LIBRARIES}
${X11_LIBRARIES} ${X11_LIBRARIES}
jthread ${JTHREAD_LIBRARIES}
${PLATFORM_LIBS} ${PLATFORM_LIBS}
${CLIENT_PLATFORM_LIBS} ${CLIENT_PLATFORM_LIBS}
) )
endif(BUILD_CLIENT) endif(BUILD_CLIENT)
if(BUILD_SERVER) if(BUILD_SERVER)
add_executable(minetestserver ${minetestserver_SRCS}) add_executable(minetestserver ${minetestserver_SRCS} ${JTHREAD_SRCS})
target_link_libraries( target_link_libraries(
minetestserver minetestserver
${ZLIB_LIBRARIES} ${ZLIB_LIBRARIES}
jthread ${JTHREAD_LIBRARIES}
${PLATFORM_LIBS} ${PLATFORM_LIBS}
) )
endif(BUILD_SERVER) endif(BUILD_SERVER)
@ -143,7 +147,11 @@ if(MSVC)
# Visual Studio # Visual Studio
# EHa enables SEH exceptions (used for catching segfaults) # EHa enables SEH exceptions (used for catching segfaults)
set(CMAKE_CXX_FLAGS_RELEASE "/EHa /MD /O2 /Ob2 /Oi /Ot /Oy /GL /FD /MT /GS- /arch:SSE /fp:fast /D NDEBUG") set(CMAKE_CXX_FLAGS_RELEASE "/EHa /MD /O2 /Ob2 /Oi /Ot /Oy /GL /FD /MT /GS- /arch:SSE /fp:fast /D NDEBUG /D _HAS_ITERATOR_DEBUGGING=0 /TP")
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "/LTCG /NODEFAULTLIB:\"libcmtd.lib\"")
# Debug build doesn't catch exceptions by itself
# Add some optimizations because otherwise it's VERY slow
set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1") set(CMAKE_CXX_FLAGS_DEBUG "/MDd /Zi /Ob0 /Od /RTC1")
if(BUILD_SERVER) if(BUILD_SERVER)

@ -1209,8 +1209,8 @@ bool Client::AsyncProcessPacket()
} //try } //try
catch(con::PeerNotFoundException &e) catch(con::PeerNotFoundException &e)
{ {
dout_client<<DTIME<<"Client::AsyncProcessData(): Cancelling: The server" /*dout_client<<DTIME<<"Client::AsyncProcessData(): Cancelling: The server"
" connection doesn't exist (a timeout or not yet connected?)"<<std::endl; " connection doesn't exist (a timeout or not yet connected?)"<<std::endl;*/
return false; return false;
} }
} }

@ -1317,7 +1317,7 @@ Peer* Connection::GetPeer(u16 peer_id)
if(node == NULL){ if(node == NULL){
// Peer not found // Peer not found
throw PeerNotFoundException("Peer not found (possible timeout)"); throw PeerNotFoundException("GetPeer: Peer not found (possible timeout)");
} }
// Error checking // Error checking

@ -30,7 +30,6 @@ void set_default_settings()
g_settings.setDefault("viewing_range_nodes_min", "35"); g_settings.setDefault("viewing_range_nodes_min", "35");
g_settings.setDefault("screenW", "800"); g_settings.setDefault("screenW", "800");
g_settings.setDefault("screenH", "600"); g_settings.setDefault("screenH", "600");
g_settings.setDefault("host_game", "");
g_settings.setDefault("port", ""); g_settings.setDefault("port", "");
g_settings.setDefault("address", ""); g_settings.setDefault("address", "");
g_settings.setDefault("name", ""); g_settings.setDefault("name", "");

@ -190,9 +190,16 @@ Map & Environment::getMap()
void Environment::addPlayer(Player *player) void Environment::addPlayer(Player *player)
{ {
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
//Check that only one local player exists and peer_ids are unique /*
Check that only one local player exists and peer_ids are unique.
Exception: there can be multiple players with peer_id=0
*/
#ifndef SERVER #ifndef SERVER
assert(player->isLocal() == false || getLocalPlayer() == NULL); /*
It is a failure if player is local and there already is a local
player
*/
assert(!(player->isLocal() == true && getLocalPlayer() != NULL));
#endif #endif
if(player->peer_id != 0) if(player->peer_id != 0)
assert(getPlayer(player->peer_id) == NULL); assert(getPlayer(player->peer_id) == NULL);

@ -79,8 +79,8 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
Inventory *inventory, Inventory *inventory,
Queue<InventoryAction*> *actions, Queue<InventoryAction*> *actions,
int *active_menu_count): IMenuManager *menumgr):
GUIModalMenu(env, parent, id, active_menu_count) GUIModalMenu(env, parent, id, menumgr)
{ {
m_inventory = inventory; m_inventory = inventory;
m_selected_item = NULL; m_selected_item = NULL;

@ -74,7 +74,7 @@ public:
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
Inventory *inventory, Inventory *inventory,
Queue<InventoryAction*> *actions, Queue<InventoryAction*> *actions,
int *active_menu_count); IMenuManager *menumgr);
~GUIInventoryMenu(); ~GUIInventoryMenu();
void removeChildren(); void removeChildren();

275
src/guiMainMenu.cpp Normal file

@ -0,0 +1,275 @@
/*
Minetest-c55
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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 2 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "guiMainMenu.h"
#include "debug.h"
#include "serialization.h"
#include <string>
GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
MainMenuData *data,
IGameCallback *gamecallback
):
GUIModalMenu(env, parent, id, menumgr),
m_data(data),
m_accepted(false),
m_gamecallback(gamecallback)
{
assert(m_data);
}
GUIMainMenu::~GUIMainMenu()
{
removeChildren();
}
void GUIMainMenu::removeChildren()
{
const core::list<gui::IGUIElement*> &children = getChildren();
core::list<gui::IGUIElement*> children_copy;
for(core::list<gui::IGUIElement*>::ConstIterator
i = children.begin(); i != children.end(); i++)
{
children_copy.push_back(*i);
}
for(core::list<gui::IGUIElement*>::Iterator
i = children_copy.begin();
i != children_copy.end(); i++)
{
(*i)->remove();
}
}
void GUIMainMenu::regenerateGui(v2u32 screensize)
{
std::wstring text_name;
std::wstring text_address;
std::wstring text_port;
bool creative_mode;
{
gui::IGUIElement *e = getElementFromId(258);
if(e != NULL)
text_name = e->getText();
else
text_name = m_data->name;
}
{
gui::IGUIElement *e = getElementFromId(256);
if(e != NULL)
text_address = e->getText();
else
text_address = m_data->address;
}
{
gui::IGUIElement *e = getElementFromId(257);
if(e != NULL)
text_port = e->getText();
else
text_port = m_data->port;
}
{
gui::IGUIElement *e = getElementFromId(259);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
else
creative_mode = m_data->creative_mode;
}
/*
Remove stuff
*/
removeChildren();
/*
Calculate new sizes and positions
*/
core::rect<s32> rect(
screensize.X/2 - 580/2,
screensize.Y/2 - 300/2,
screensize.X/2 + 580/2,
screensize.Y/2 + 300/2
);
DesiredRect = rect;
recalculateAbsolutePosition(false);
v2s32 size = rect.getSize();
/*
Add stuff
*/
// Nickname
{
core::rect<s32> rect(0, 0, 100, 20);
rect = rect + v2s32(size.X/2 - 250, size.Y/2 - 100 + 6);
const wchar_t *text = L"Nickname";
Environment->addStaticText(text, rect, false, true, this, -1);
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect = rect + v2s32(size.X/2 - 130, size.Y/2 - 100);
gui::IGUIElement *e =
Environment->addEditBox(text_name.c_str(), rect, true, this, 258);
if(text_name == L"")
Environment->setFocus(e);
}
// Address + port
{
core::rect<s32> rect(0, 0, 100, 20);
rect = rect + v2s32(size.X/2 - 250, size.Y/2 - 50 + 6);
const wchar_t *text = L"Address + Port";
Environment->addStaticText(text, rect, false, true, this, -1);
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect = rect + v2s32(size.X/2 - 130, size.Y/2 - 50);
gui::IGUIElement *e =
Environment->addEditBox(text_address.c_str(), rect, true, this, 256);
if(text_name != L"")
Environment->setFocus(e);
}
{
core::rect<s32> rect(0, 0, 100, 30);
rect = rect + v2s32(size.X/2 - 130 + 250 + 20, size.Y/2 - 50);
Environment->addEditBox(text_port.c_str(), rect, true, this, 257);
}
{
core::rect<s32> rect(0, 0, 400, 20);
rect = rect + v2s32(size.X/2 - 130, size.Y/2 - 50 + 35);
const wchar_t *text = L"Leave address blank to start a local server.";
Environment->addStaticText(text, rect, false, true, this, -1);
}
// Server parameters
{
core::rect<s32> rect(0, 0, 100, 20);
rect = rect + v2s32(size.X/2 - 250, size.Y/2 + 25 + 6);
const wchar_t *text = L"Server params";
Environment->addStaticText(text, rect, false, true, this, -1);
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect = rect + v2s32(size.X/2 - 130, size.Y/2 + 25);
Environment->addCheckBox(creative_mode, rect, this, 259, L"Creative Mode");
}
// Start game button
{
core::rect<s32> rect(0, 0, 180, 30);
rect = rect + v2s32(size.X/2-180/2, size.Y/2-30/2 + 100);
Environment->addButton(rect, this, 257, L"Start Game / Connect");
}
}
void GUIMainMenu::drawMenu()
{
gui::IGUISkin* skin = Environment->getSkin();
if (!skin)
return;
video::IVideoDriver* driver = Environment->getVideoDriver();
video::SColor bgcolor(140,0,0,0);
driver->draw2DRectangle(bgcolor, AbsoluteRect, &AbsoluteClippingRect);
gui::IGUIElement::draw();
}
void GUIMainMenu::acceptInput()
{
{
gui::IGUIElement *e = getElementFromId(258);
if(e != NULL)
m_data->name = e->getText();
}
{
gui::IGUIElement *e = getElementFromId(256);
if(e != NULL)
m_data->address = e->getText();
}
{
gui::IGUIElement *e = getElementFromId(257);
if(e != NULL)
m_data->port = e->getText();
}
{
gui::IGUIElement *e = getElementFromId(259);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
}
m_accepted = true;
}
bool GUIMainMenu::OnEvent(const SEvent& event)
{
if(event.EventType==EET_KEY_INPUT_EVENT)
{
if(event.KeyInput.Key==KEY_ESCAPE && event.KeyInput.PressedDown)
{
m_gamecallback->exitToOS();
quitMenu();
return true;
}
if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown)
{
acceptInput();
quitMenu();
return true;
}
}
if(event.EventType==EET_GUI_EVENT)
{
if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST
&& isVisible())
{
if(!canTakeFocus(event.GUIEvent.Element))
{
dstream<<"GUIMainMenu: Not allowing focus change."
<<std::endl;
// Returning true disables focus change
return true;
}
}
if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED)
{
switch(event.GUIEvent.Caller->getID())
{
case 257:
acceptInput();
quitMenu();
break;
}
}
if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
{
switch(event.GUIEvent.Caller->getID())
{
case 256: case 257: case 258:
acceptInput();
quitMenu();
break;
}
}
}
return Parent ? Parent->OnEvent(event) : false;
}

73
src/guiMainMenu.h Normal file

@ -0,0 +1,73 @@
/*
Minetest-c55
Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
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 2 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.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef GUIMAINMENU_HEADER
#define GUIMAINMENU_HEADER
#include "common_irrlicht.h"
#include "modalMenu.h"
#include "utility.h"
#include <string>
// For IGameCallback
#include "guiPauseMenu.h"
struct MainMenuData
{
// These are in the native format of the gui elements
std::wstring address;
std::wstring port;
std::wstring name;
bool creative_mode;
};
class GUIMainMenu : public GUIModalMenu
{
public:
GUIMainMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
MainMenuData *data,
IGameCallback *gamecallback);
~GUIMainMenu();
void removeChildren();
/*
Remove and re-add (or reposition) stuff
*/
void regenerateGui(v2u32 screensize);
void drawMenu();
void acceptInput();
bool getStatus()
{
return m_accepted;
}
bool OnEvent(const SEvent& event);
private:
MainMenuData *m_data;
bool m_accepted;
IGameCallback *m_gamecallback;
};
#endif

@ -24,10 +24,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
GUIMessageMenu::GUIMessageMenu(gui::IGUIEnvironment* env, GUIMessageMenu::GUIMessageMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
int *active_menu_count, IMenuManager *menumgr,
std::wstring message_text std::wstring message_text
): ):
GUIModalMenu(env, parent, id, active_menu_count), GUIModalMenu(env, parent, id, menumgr),
m_message_text(message_text), m_message_text(message_text),
m_status(false) m_status(false)
{ {

@ -30,7 +30,7 @@ class GUIMessageMenu : public GUIModalMenu
public: public:
GUIMessageMenu(gui::IGUIEnvironment* env, GUIMessageMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
int *active_menu_count, IMenuManager *menumgr,
std::wstring message_text); std::wstring message_text);
~GUIMessageMenu(); ~GUIMessageMenu();

@ -25,11 +25,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env, GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
IrrlichtDevice *dev, IGameCallback *gamecallback,
int *active_menu_count): IMenuManager *menumgr):
GUIModalMenu(env, parent, id, active_menu_count) GUIModalMenu(env, parent, id, menumgr)
{ {
m_dev = dev; m_gamecallback = gamecallback;
} }
GUIPauseMenu::~GUIPauseMenu() GUIPauseMenu::~GUIPauseMenu()
@ -59,6 +59,11 @@ void GUIPauseMenu::removeChildren()
if(e != NULL) if(e != NULL)
e->remove(); e->remove();
} }
{
gui::IGUIElement *e = getElementFromId(260);
if(e != NULL)
e->remove();
}
} }
void GUIPauseMenu::regenerateGui(v2u32 screensize) void GUIPauseMenu::regenerateGui(v2u32 screensize)
@ -88,13 +93,18 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
*/ */
{ {
core::rect<s32> rect(0, 0, 140, 30); core::rect<s32> rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2-25); rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2-50);
Environment->addButton(rect, this, 256, L"Continue"); Environment->addButton(rect, this, 256, L"Continue");
} }
{ {
core::rect<s32> rect(0, 0, 140, 30); core::rect<s32> rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25); rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+0);
Environment->addButton(rect, this, 257, L"Exit"); Environment->addButton(rect, this, 260, L"Disconnect");
}
{
core::rect<s32> rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+50);
Environment->addButton(rect, this, 257, L"Exit to OS");
} }
{ {
core::rect<s32> rect(0, 0, 180, 240); core::rect<s32> rect(0, 0, 180, 240);
@ -183,8 +193,13 @@ bool GUIPauseMenu::OnEvent(const SEvent& event)
case 256: // continue case 256: // continue
quitMenu(); quitMenu();
break; break;
case 260: // disconnect
m_gamecallback->disconnect();
quitMenu();
break;
case 257: // exit case 257: // exit
m_dev->closeDevice(); m_gamecallback->exitToOS();
quitMenu();
break; break;
} }
} }

@ -23,13 +23,20 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include "modalMenu.h" #include "modalMenu.h"
class IGameCallback
{
public:
virtual void exitToOS() = 0;
virtual void disconnect() = 0;
};
class GUIPauseMenu : public GUIModalMenu class GUIPauseMenu : public GUIModalMenu
{ {
public: public:
GUIPauseMenu(gui::IGUIEnvironment* env, GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
IrrlichtDevice *dev, IGameCallback *gamecallback,
int *active_menu_count); IMenuManager *menumgr);
~GUIPauseMenu(); ~GUIPauseMenu();
void removeChildren(); void removeChildren();
@ -43,7 +50,7 @@ public:
bool OnEvent(const SEvent& event); bool OnEvent(const SEvent& event);
private: private:
IrrlichtDevice *m_dev; IGameCallback *m_gamecallback;
}; };
#endif #endif

@ -24,11 +24,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
GUITextInputMenu::GUITextInputMenu(gui::IGUIEnvironment* env, GUITextInputMenu::GUITextInputMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
int *active_menu_count, IMenuManager *menumgr,
TextDest *dest, TextDest *dest,
std::wstring initial_text std::wstring initial_text
): ):
GUIModalMenu(env, parent, id, active_menu_count), GUIModalMenu(env, parent, id, menumgr),
m_dest(dest), m_dest(dest),
m_initial_text(initial_text) m_initial_text(initial_text)
{ {

@ -35,7 +35,7 @@ class GUITextInputMenu : public GUIModalMenu
public: public:
GUITextInputMenu(gui::IGUIEnvironment* env, GUITextInputMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
int *active_menu_count, IMenuManager *menumgr,
TextDest *dest, TextDest *dest,
std::wstring initial_text); std::wstring initial_text);
~GUITextInputMenu(); ~GUITextInputMenu();

@ -104,6 +104,16 @@ SUGG: Meshes of blocks could be split into 6 meshes facing into
different directions and then only those drawn that need to be different directions and then only those drawn that need to be
- Also an 1-dimensional tile map would be nice probably - Also an 1-dimensional tile map would be nice probably
Gaming ideas:
-------------
- How would some GTA-style ideas work?
- Cars? Stealing? Unlawful stuff and cops? Lots of guns?
- RPG style?
- Space racer style?
Documentation: Documentation:
-------------- --------------
@ -289,7 +299,7 @@ Doing now:
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib") #pragma comment(lib, "Irrlicht.lib")
#pragma comment(lib, "jthread.lib") //#pragma comment(lib, "jthread.lib")
#pragma comment(lib, "zlibwapi.lib") #pragma comment(lib, "zlibwapi.lib")
// This would get rid of the console window // This would get rid of the console window
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") //#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
@ -322,6 +332,7 @@ Doing now:
#include "guiMessageMenu.h" #include "guiMessageMenu.h"
#include "filesys.h" #include "filesys.h"
#include "config.h" #include "config.h"
#include "guiMainMenu.h"
IrrlichtWrapper *g_irrlicht; IrrlichtWrapper *g_irrlicht;
@ -346,15 +357,87 @@ Client *g_client = NULL;
/* /*
GUI Stuff GUI Stuff
*/ */
gui::IGUIEnvironment* guienv = NULL; gui::IGUIEnvironment* guienv = NULL;
gui::IGUIStaticText *guiroot = NULL; gui::IGUIStaticText *guiroot = NULL;
int g_active_menu_count = 0;
class MainMenuManager : public IMenuManager
{
public:
virtual void createdMenu(GUIModalMenu *menu)
{
for(core::list<GUIModalMenu*>::Iterator
i = m_stack.begin();
i != m_stack.end(); i++)
{
assert(*i != menu);
}
if(m_stack.size() != 0)
(*m_stack.getLast())->setVisible(false);
m_stack.push_back(menu);
}
virtual void deletingMenu(GUIModalMenu *menu)
{
// Remove all entries if there are duplicates
bool removed_entry;
do{
removed_entry = false;
for(core::list<GUIModalMenu*>::Iterator
i = m_stack.begin();
i != m_stack.end(); i++)
{
if(*i == menu)
{
m_stack.erase(i);
removed_entry = true;
break;
}
}
}while(removed_entry);
/*core::list<GUIModalMenu*>::Iterator i = m_stack.getLast();
assert(*i == menu);
m_stack.erase(i);*/
if(m_stack.size() != 0)
(*m_stack.getLast())->setVisible(true);
}
u32 menuCount()
{
return m_stack.size();
}
core::list<GUIModalMenu*> m_stack;
};
MainMenuManager g_menumgr;
bool noMenuActive() bool noMenuActive()
{ {
return (g_active_menu_count == 0); return (g_menumgr.menuCount() == 0);
} }
bool g_disconnect_requested = false;
class MainGameCallback : public IGameCallback
{
public:
virtual void exitToOS()
{
g_device->closeDevice();
}
virtual void disconnect()
{
g_disconnect_requested = true;
}
};
MainGameCallback g_gamecallback;
// Inventory actions from the menu are buffered here before sending // Inventory actions from the menu are buffered here before sending
Queue<InventoryAction*> inventory_action_queue; Queue<InventoryAction*> inventory_action_queue;
// This is a copy of the inventory that the client's environment has // This is a copy of the inventory that the client's environment has
@ -472,8 +555,8 @@ public:
dstream<<DTIME<<"MyEventReceiver: " dstream<<DTIME<<"MyEventReceiver: "
<<"Launching pause menu"<<std::endl; <<"Launching pause menu"<<std::endl;
// It will delete itself by itself // It will delete itself by itself
(new GUIPauseMenu(guienv, guiroot, -1, g_device, (new GUIPauseMenu(guienv, guiroot, -1, &g_gamecallback,
&g_active_menu_count))->drop(); &g_menumgr))->drop();
return true; return true;
} }
if(event.KeyInput.Key == irr::KEY_KEY_I) if(event.KeyInput.Key == irr::KEY_KEY_I)
@ -482,7 +565,7 @@ public:
<<"Launching inventory"<<std::endl; <<"Launching inventory"<<std::endl;
(new GUIInventoryMenu(guienv, guiroot, -1, (new GUIInventoryMenu(guienv, guiroot, -1,
&local_inventory, &inventory_action_queue, &local_inventory, &inventory_action_queue,
&g_active_menu_count))->drop(); &g_menumgr))->drop();
return true; return true;
} }
if(event.KeyInput.Key == irr::KEY_KEY_T) if(event.KeyInput.Key == irr::KEY_KEY_T)
@ -490,7 +573,7 @@ public:
TextDest *dest = new TextDestChat(g_client); TextDest *dest = new TextDestChat(g_client);
(new GUITextInputMenu(guienv, guiroot, -1, (new GUITextInputMenu(guienv, guiroot, -1,
&g_active_menu_count, dest, &g_menumgr, dest,
L""))->drop(); L""))->drop();
} }
} }
@ -1067,6 +1150,18 @@ public:
} }
} }
~GUIQuickInventory()
{
for(u32 i=0; i<m_texts.size(); i++)
{
m_texts[i]->remove();
}
for(u32 i=0; i<m_images.size(); i++)
{
m_images[i]->remove();
}
}
virtual bool OnEvent(const SEvent& event) virtual bool OnEvent(const SEvent& event)
{ {
return false; return false;
@ -1179,9 +1274,6 @@ int main(int argc, char *argv[])
<<", "<<BUILD_INFO <<", "<<BUILD_INFO
<<std::endl; <<std::endl;
try
{
/* /*
Parse command line Parse command line
*/ */
@ -1315,137 +1407,63 @@ int main(int argc, char *argv[])
map_params.ravines_amount = g_settings.getFloat("ravines_amount"); map_params.ravines_amount = g_settings.getFloat("ravines_amount");
/* /*
Ask some stuff Some parameters
*/ */
std::cout<<std::endl<<std::endl; // Port
std::cout
<<" .__ __ __ "<<std::endl
<<" _____ |__| ____ _____/ |_ ____ _______/ |_ "<<std::endl
<<" / \\| |/ \\_/ __ \\ __\\/ __ \\ / ___/\\ __\\"<<std::endl
<<"| Y Y \\ | | \\ ___/| | \\ ___/ \\___ \\ | | "<<std::endl
<<"|__|_| /__|___| /\\___ >__| \\___ >____ > |__| "<<std::endl
<<" \\/ \\/ \\/ \\/ \\/ "<<std::endl
<<std::endl;
std::cout<<std::endl;
//char templine[100];
// Port?
u16 port = 30000; u16 port = 30000;
if(cmd_args.exists("port")) if(cmd_args.exists("port"))
{
port = cmd_args.getU16("port"); port = cmd_args.getU16("port");
} else if(cmd_args.exists("port"))
else port = g_settings.getU16("port");
{
port = g_settings.getU16Ask("port", "Port", 30000);
std::cout<<"-> "<<port<<std::endl;
}
//Map directory // Map directory
std::string map_dir = porting::path_userdata+"/map"; std::string map_dir = porting::path_userdata+"/map";
if(cmd_args.exists("map-dir")) if(cmd_args.exists("map-dir"))
map_dir = cmd_args.get("map-dir"); map_dir = cmd_args.get("map-dir");
else if(g_settings.exists("map-dir")) else if(g_settings.exists("map-dir"))
map_dir = g_settings.get("map-dir"); map_dir = g_settings.get("map-dir");
// Run dedicated server if asked to
if(cmd_args.getFlag("server")) if(cmd_args.getFlag("server"))
{ {
DSTACK("Dedicated server branch"); DSTACK("Dedicated server branch");
std::cout<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<"Running dedicated server"<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<std::endl;
Server server(map_dir, hm_params, map_params); // Create server
Server server(map_dir.c_str(), hm_params, map_params);
server.start(port); server.start(port);
for(;;) // Run server
{ dedicated_server_loop(server);
// This is kind of a hack but can be done like this
// because server.step() is very light
sleep_ms(30);
server.step(0.030);
static int counter = 0;
counter--;
if(counter <= 0)
{
counter = 10;
core::list<PlayerInfo> list = server.getPlayerInfo();
core::list<PlayerInfo>::Iterator i;
static u32 sum_old = 0;
u32 sum = PIChecksum(list);
if(sum != sum_old)
{
std::cout<<DTIME<<"Player info:"<<std::endl;
for(i=list.begin(); i!=list.end(); i++)
{
i->PrintLine(&std::cout);
}
}
sum_old = sum;
}
}
return 0; return 0;
} }
bool hosting = false; /*
char connect_name[100] = ""; More parameters
*/
// Address to connect to
std::string address = "";
if(cmd_args.exists("address")) if(cmd_args.exists("address"))
{ {
snprintf(connect_name, 100, "%s", cmd_args.get("address").c_str()); address = cmd_args.get("address");
}
else if(is_yes(g_settings.get("host_game")) == false)
{
if(g_settings.get("address") != "")
{
std::cout<<g_settings.get("address")<<std::endl;
snprintf(connect_name, 100, "%s", g_settings.get("address").c_str());
}
else
{
std::cout<<"Address to connect to [empty = host a game]: ";
std::cin.getline(connect_name, 100);
}
}
if(connect_name[0] == 0){
snprintf(connect_name, 100, "127.0.0.1");
hosting = true;
}
if(hosting)
std::cout<<"> Hosting game"<<std::endl;
else
std::cout<<"> Connecting to "<<connect_name<<std::endl;
char playername[PLAYERNAME_SIZE] = "";
if(g_settings.get("name") != "")
{
snprintf(playername, PLAYERNAME_SIZE, "%s", g_settings.get("name").c_str());
} }
else else
{ {
std::cout<<"Name of player: "; address = g_settings.get("address");
std::cin.getline(playername, PLAYERNAME_SIZE);
} }
std::cout<<"-> \""<<playername<<"\""<<std::endl;
std::string playername = g_settings.get("name");
/* /*
Resolution selection Resolution selection
*/ */
bool fullscreen = false; bool fullscreen = false;
u16 screenW = atoi(g_settings.get("screenW").c_str()); u16 screenW = g_settings.getU16("screenW");
u16 screenH = atoi(g_settings.get("screenH").c_str()); u16 screenH = g_settings.getU16("screenH");
// //
@ -1520,6 +1538,172 @@ int main(int argc, char *argv[])
skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0));
skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0));
/*
Preload some textures
*/
init_content_inventory_texture_paths();
init_tile_texture_paths();
tile_materials_preload(g_irrlicht);
/*
GUI stuff
*/
/*
We need some kind of a root node to be able to add
custom gui elements directly on the screen.
Otherwise they won't be automatically drawn.
*/
guiroot = guienv->addStaticText(L"",
core::rect<s32>(0, 0, 10000, 10000));
// First line of debug text
gui::IGUIStaticText *guitext = guienv->addStaticText(
L"",
core::rect<s32>(5, 5, 795, 5+text_height),
false, false);
// Second line of debug text
gui::IGUIStaticText *guitext2 = guienv->addStaticText(
L"",
core::rect<s32>(5, 5+(text_height+5)*1, 795, (5+text_height)*2),
false, false);
// At the middle of the screen
// Object infos are shown in this
gui::IGUIStaticText *guitext_info = guienv->addStaticText(
L"",
core::rect<s32>(100, 70, 100+400, 70+(text_height+5)),
false, false);
// Chat text
gui::IGUIStaticText *guitext_chat = guienv->addStaticText(
L"",
core::rect<s32>(0,0,0,0),
false, true);
guitext_chat->setBackgroundColor(video::SColor(96,0,0,0));
core::list<ChatLine> chat_lines;
/*
If an error occurs, this is set to something and the
menu-game loop is restarted. It is then displayed before
the menu.
*/
std::wstring error_message = L"";
/*
Menu-game loop
*/
while(g_device->run())
{
// This is used for catching disconnects
try
{
/*
Out-of-game menu loop
*/
// Wait for proper parameters
for(;;)
{
// Cursor can be non-visible when coming from the game
device->getCursorControl()->setVisible(true);
// Some stuff are left to scene manager when coming from the game
// (map at least?)
smgr->clear();
// Reset or hide the debug gui texts
guitext->setText(L"Minetest-c55");
guitext2->setVisible(false);
guitext_info->setVisible(false);
guitext_chat->setVisible(false);
// Initialize menu data
MainMenuData menudata;
menudata.address = narrow_to_wide(address);
menudata.name = narrow_to_wide(playername);
menudata.port = narrow_to_wide(itos(port));
menudata.creative_mode = g_settings.getBool("creative_mode");
GUIMainMenu *menu =
new GUIMainMenu(guienv, guiroot, -1,
&g_menumgr, &menudata, &g_gamecallback);
menu->allowFocusRemoval(true);
if(error_message != L"")
{
GUIMessageMenu *menu2 =
new GUIMessageMenu(guienv, guiroot, -1,
&g_menumgr, error_message.c_str());
menu2->drop();
error_message = L"";
}
video::IVideoDriver* driver = g_device->getVideoDriver();
dstream<<"Created main menu"<<std::endl;
while(g_device->run())
{
// Run global IrrlichtWrapper's main thread processing stuff
g_irrlicht->Run();
if(menu->getStatus() == true)
break;
//driver->beginScene(true, true, video::SColor(255,0,0,0));
driver->beginScene(true, true, video::SColor(255,128,128,128));
guienv->drawAll();
driver->endScene();
}
// Break out of menu-game loop to shut down cleanly
if(g_device->run() == false)
break;
dstream<<"Dropping main menu"<<std::endl;
menu->drop();
playername = wide_to_narrow(menudata.name);
address = wide_to_narrow(menudata.address);
port = stoi(wide_to_narrow(menudata.port));
g_settings.set("creative_mode", itos(menudata.creative_mode));
// Check for valid parameters, restart menu if invalid.
if(playername == "")
{
error_message = L"Name required.";
continue;
}
// Save settings
g_settings.set("name", playername);
g_settings.set("address", address);
g_settings.set("port", itos(port));
// Update configuration file
if(configpath != "")
g_settings.updateConfigFile(configpath.c_str());
// Continue to game
break;
}
// Break out of menu-game loop to shut down cleanly
if(g_device->run() == false)
break;
/*
Make a scope here so that the client and the server and other
stuff gets removed when disconnected or the irrlicht device
is removed.
*/
{
/*
Draw "Loading" screen
*/
const wchar_t *text = L"Loading and connecting..."; const wchar_t *text = L"Loading and connecting...";
core::vector2d<s32> center(screenW/2, screenH/2); core::vector2d<s32> center(screenW/2, screenH/2);
core::vector2d<s32> textsize(300, text_height); core::vector2d<s32> textsize(300, text_height);
@ -1533,27 +1717,14 @@ int main(int argc, char *argv[])
guienv->drawAll(); guienv->drawAll();
driver->endScene(); driver->endScene();
/*
Preload some textures
*/
init_content_inventory_texture_paths();
init_tile_texture_paths();
tile_materials_preload(g_irrlicht);
/*
Make a scope here for the client so that it gets removed
before the irrlicht device
*/
{
std::cout<<DTIME<<"Creating server and client"<<std::endl; std::cout<<DTIME<<"Creating server and client"<<std::endl;
/* /*
Create server Create server.
SharedPtr will delete it when it goes out of scope.
*/ */
SharedPtr<Server> server; SharedPtr<Server> server;
if(hosting){ if(address == ""){
server = new Server(map_dir, hm_params, map_params); server = new Server(map_dir, hm_params, map_params);
server->start(port); server->start(port);
} }
@ -1562,18 +1733,24 @@ int main(int argc, char *argv[])
Create client Create client
*/ */
Client client(device, playername, draw_control); Client client(device, playername.c_str(), draw_control);
g_client = &client; g_client = &client;
Address connect_address(0,0,0,0, port); Address connect_address(0,0,0,0, port);
try{ try{
connect_address.Resolve(connect_name); if(address == "")
connect_address.Resolve("localhost");
else
connect_address.Resolve(address.c_str());
} }
catch(ResolveError &e) catch(ResolveError &e)
{ {
std::cout<<DTIME<<"Couldn't resolve address"<<std::endl; std::cout<<DTIME<<"Couldn't resolve address"<<std::endl;
return 0; //return 0;
error_message = L"Couldn't resolve address";
gui_loadingtext->remove();
continue;
} }
std::cout<<DTIME<<"Connecting to server..."<<std::endl; std::cout<<DTIME<<"Connecting to server..."<<std::endl;
@ -1582,17 +1759,29 @@ int main(int argc, char *argv[])
try{ try{
while(client.connectedAndInitialized() == false) while(client.connectedAndInitialized() == false)
{ {
// Update screen
driver->beginScene(true, true, video::SColor(255,0,0,0));
guienv->drawAll();
driver->endScene();
// Update client and server
client.step(0.1); client.step(0.1);
if(server != NULL){
if(server != NULL)
server->step(0.1); server->step(0.1);
}
// Delay a bit
sleep_ms(100); sleep_ms(100);
} }
} }
catch(con::PeerNotFoundException &e) catch(con::PeerNotFoundException &e)
{ {
std::cout<<DTIME<<"Timed out."<<std::endl; std::cout<<DTIME<<"Timed out."<<std::endl;
return 0; //return 0;
error_message = L"Connection timed out.";
gui_loadingtext->remove();
continue;
} }
/* /*
@ -1644,52 +1833,23 @@ int main(int argc, char *argv[])
GUIQuickInventory *quick_inventory = new GUIQuickInventory GUIQuickInventory *quick_inventory = new GUIQuickInventory
(guienv, NULL, v2s32(10, 70), 5, &local_inventory); (guienv, NULL, v2s32(10, 70), 5, &local_inventory);
/*
We need some kind of a root node to be able to add
custom elements directly on the screen.
Otherwise they won't be automatically drawn.
*/
guiroot = guienv->addStaticText(L"",
core::rect<s32>(0, 0, 10000, 10000));
// Test the text input system // Test the text input system
/*(new GUITextInputMenu(guienv, guiroot, -1, &g_active_menu_count, /*(new GUITextInputMenu(guienv, guiroot, -1, &g_menumgr,
NULL))->drop();*/ NULL))->drop();*/
/*GUIMessageMenu *menu = /*GUIMessageMenu *menu =
new GUIMessageMenu(guienv, guiroot, -1, new GUIMessageMenu(guienv, guiroot, -1,
&g_active_menu_count, &g_menumgr,
L"Asd"); L"Asd");
menu->drop();*/ menu->drop();*/
// Launch pause menu // Launch pause menu
(new GUIPauseMenu(guienv, guiroot, -1, g_device, (new GUIPauseMenu(guienv, guiroot, -1, &g_gamecallback,
&g_active_menu_count))->drop(); &g_menumgr))->drop();
// First line of debug text
gui::IGUIStaticText *guitext = guienv->addStaticText(
L"Minetest-c55",
core::rect<s32>(5, 5, 795, 5+textsize.Y),
false, false);
// Second line of debug text
gui::IGUIStaticText *guitext2 = guienv->addStaticText(
L"",
core::rect<s32>(5, 5+(textsize.Y+5)*1, 795, (5+textsize.Y)*2),
false, false);
// At the middle of the screen // Enable texts
// Object infos are shown in this guitext2->setVisible(true);
gui::IGUIStaticText *guitext_info = guienv->addStaticText( guitext_info->setVisible(true);
L"test", guitext_chat->setVisible(true);
core::rect<s32>(100, 70, 100+400, 70+(textsize.Y+5)),
false, false);
// Chat text
gui::IGUIStaticText *chat_guitext = guienv->addStaticText(
L"Chat here\nOther line\nOther line\nOther line\nOther line",
core::rect<s32>(70, 60, 795, 150),
false, true);
chat_guitext->setBackgroundColor(video::SColor(96,0,0,0));
core::list<ChatLine> chat_lines;
/* /*
Some statistics are collected in these Some statistics are collected in these
@ -1715,6 +1875,12 @@ int main(int argc, char *argv[])
while(device->run()) while(device->run())
{ {
if(g_disconnect_requested)
{
g_disconnect_requested = false;
break;
}
/* /*
Run global IrrlichtWrapper's main thread processing stuff Run global IrrlichtWrapper's main thread processing stuff
*/ */
@ -2042,7 +2208,7 @@ int main(int argc, char *argv[])
narrow_to_wide(sign_object->getText()); narrow_to_wide(sign_object->getText());
(new GUITextInputMenu(guienv, guiroot, -1, (new GUITextInputMenu(guienv, guiroot, -1,
&g_active_menu_count, dest, &g_menumgr, dest,
wtext))->drop(); wtext))->drop();
} }
} }
@ -2519,7 +2685,7 @@ int main(int argc, char *argv[])
it = chat_lines.begin(); it = chat_lines.begin();
chat_lines.erase(it); chat_lines.erase(it);
} }
chat_guitext->setText(whole.c_str()); guitext_chat->setText(whole.c_str());
// Update gui element size and position // Update gui element size and position
core::rect<s32> rect( core::rect<s32> rect(
10, 10,
@ -2527,12 +2693,12 @@ int main(int argc, char *argv[])
screensize.X - 10, screensize.X - 10,
screensize.Y - 10 screensize.Y - 10
); );
chat_guitext->setRelativePosition(rect); guitext_chat->setRelativePosition(rect);
if(chat_lines.size() == 0) if(chat_lines.size() == 0)
chat_guitext->setVisible(false); guitext_chat->setVisible(false);
else else
chat_guitext->setVisible(true); guitext_chat->setVisible(true);
} }
/* /*
@ -2667,22 +2833,7 @@ int main(int argc, char *argv[])
delete quick_inventory; delete quick_inventory;
} // client is deleted at this point } // client and server are deleted at this point
delete g_input;
/*
In the end, delete the Irrlicht device.
*/
device->drop();
/*
Update configuration file
*/
/*if(configpath != "")
{
g_settings.updateConfigFile(configpath.c_str());
}*/
} //try } //try
catch(con::PeerNotFoundException &e) catch(con::PeerNotFoundException &e)
@ -2693,7 +2844,7 @@ int main(int argc, char *argv[])
{ {
GUIMessageMenu *menu = GUIMessageMenu *menu =
new GUIMessageMenu(guienv, guiroot, -1, new GUIMessageMenu(guienv, guiroot, -1,
&g_active_menu_count, &g_menumgr,
L"Connection timed out"); L"Connection timed out");
video::IVideoDriver* driver = g_device->getVideoDriver(); video::IVideoDriver* driver = g_device->getVideoDriver();
@ -2713,6 +2864,23 @@ int main(int argc, char *argv[])
}*/ }*/
} }
} // Menu-game loop
delete g_input;
/*
In the end, delete the Irrlicht device.
*/
device->drop();
/*
Update configuration file
*/
/*if(configpath != "")
{
g_settings.updateConfigFile(configpath.c_str());
}*/
END_DEBUG_EXCEPTION_HANDLER END_DEBUG_EXCEPTION_HANDLER
debugstreams_deinit(); debugstreams_deinit();

@ -1372,8 +1372,12 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
u32 loopcount = 0; u32 loopcount = 0;
u32 initial_size = m_transforming_liquid.size(); u32 initial_size = m_transforming_liquid.size();
while(m_transforming_liquid.size() != 0) while(m_transforming_liquid.size() != 0)
{ {
/*
Get a queued transforming liquid node
*/
v3s16 p0 = m_transforming_liquid.pop_front(); v3s16 p0 = m_transforming_liquid.pop_front();
MapNode n0 = getNode(p0); MapNode n0 = getNode(p0);
@ -1557,6 +1561,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
v3s16 p2 = p0 + dirs_to[i]; v3s16 p2 = p0 + dirs_to[i];
MapNode n2 = getNode(p2); MapNode n2 = getNode(p2);
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
if(content_liquid(n2.d)) if(content_liquid(n2.d))
{ {
@ -1605,6 +1610,8 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
n2_changed = true; n2_changed = true;
flowed = true; flowed = true;
} }
//dstream<<"[2] n2.param="<<(int)n2.param<<std::endl;
if(n2_changed) if(n2_changed)
{ {

@ -141,6 +141,8 @@ MapNode MapBlock::getNodeParentNoEx(v3s16 p)
n: getNodeParent(p) n: getNodeParent(p)
n2: getNodeParent(p + face_dir) n2: getNodeParent(p + face_dir)
face_dir: axis oriented unit vector from p to p2 face_dir: axis oriented unit vector from p to p2
returns encoded light value.
*/ */
u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2, u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
v3s16 face_dir) v3s16 face_dir)
@ -721,6 +723,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
MapNode &n = getNodeRef(x,y,z); MapNode &n = getNodeRef(x,y,z);
/*
Add torches to mesh
*/
if(n.d == CONTENT_TORCH) if(n.d == CONTENT_TORCH)
{ {
video::SColor c(255,255,255,255); video::SColor c(255,255,255,255);
@ -779,6 +784,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
// Add to mesh collector // Add to mesh collector
collector.append(material, vertices, 4, indices, 6); collector.append(material, vertices, 4, indices, 6);
} }
/*
Add flowing water to mesh
*/
else if(n.d == CONTENT_WATER) else if(n.d == CONTENT_WATER)
{ {
bool top_is_water = false; bool top_is_water = false;
@ -787,8 +795,9 @@ void MapBlock::updateMesh(u32 daynight_ratio)
if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE)
top_is_water = true; top_is_water = true;
}catch(InvalidPositionException &e){} }catch(InvalidPositionException &e){}
video::SColor c(128,255,255,255); u8 l = decode_light(n.getLightBlend(daynight_ratio));
video::SColor c(128,l,l,l);
// Neighbor water levels (key = relative position) // Neighbor water levels (key = relative position)
// Includes current node // Includes current node

@ -22,6 +22,16 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
class GUIModalMenu;
class IMenuManager
{
public:
// A GUIModalMenu calls these when this class is passed as a parameter
virtual void createdMenu(GUIModalMenu *menu) = 0;
virtual void deletingMenu(GUIModalMenu *menu) = 0;
};
/* /*
Remember to drop() the menu after creating, so that it can Remember to drop() the menu after creating, so that it can
remove itself when it wants to. remove itself when it wants to.
@ -32,21 +42,26 @@ class GUIModalMenu : public gui::IGUIElement
public: public:
GUIModalMenu(gui::IGUIEnvironment* env, GUIModalMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, gui::IGUIElement* parent, s32 id,
int *active_menu_count): IMenuManager *menumgr):
IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, IGUIElement(gui::EGUIET_ELEMENT, env, parent, id,
core::rect<s32>(0,0,100,100)) core::rect<s32>(0,0,100,100))
{ {
m_active_menu_count = active_menu_count; m_menumgr = menumgr;
m_allow_focus_removal = false; m_allow_focus_removal = false;
m_screensize_old = v2u32(0,0); m_screensize_old = v2u32(0,0);
setVisible(true); setVisible(true);
Environment->setFocus(this); Environment->setFocus(this);
(*m_active_menu_count)++; m_menumgr->createdMenu(this);
} }
virtual ~GUIModalMenu() virtual ~GUIModalMenu()
{ {
(*m_active_menu_count)--; m_menumgr->deletingMenu(this);
}
void allowFocusRemoval(bool allow)
{
m_allow_focus_removal = allow;
} }
bool canTakeFocus(gui::IGUIElement *e) bool canTakeFocus(gui::IGUIElement *e)
@ -75,18 +90,35 @@ public:
*/ */
void quitMenu() void quitMenu()
{ {
m_allow_focus_removal = true; allowFocusRemoval(true);
// This removes Environment's grab on us // This removes Environment's grab on us
Environment->removeFocus(this); Environment->removeFocus(this);
this->remove(); this->remove();
} }
void removeChildren()
{
const core::list<gui::IGUIElement*> &children = getChildren();
core::list<gui::IGUIElement*> children_copy;
for(core::list<gui::IGUIElement*>::ConstIterator
i = children.begin(); i != children.end(); i++)
{
children_copy.push_back(*i);
}
for(core::list<gui::IGUIElement*>::Iterator
i = children_copy.begin();
i != children_copy.end(); i++)
{
(*i)->remove();
}
}
virtual void regenerateGui(v2u32 screensize) = 0; virtual void regenerateGui(v2u32 screensize) = 0;
virtual void drawMenu() = 0; virtual void drawMenu() = 0;
virtual bool OnEvent(const SEvent& event) { return false; }; virtual bool OnEvent(const SEvent& event) { return false; };
private: private:
int *m_active_menu_count; IMenuManager *m_menumgr;
// This might be necessary to expose to the implementation if it // This might be necessary to expose to the implementation if it
// wants to launch other menus // wants to launch other menus
bool m_allow_focus_removal; bool m_allow_focus_removal;

@ -53,6 +53,10 @@ void * ServerThread::Thread()
catch(con::NoIncomingDataException &e) catch(con::NoIncomingDataException &e)
{ {
} }
catch(con::PeerNotFoundException &e)
{
dout_server<<"Server: PeerNotFoundException"<<std::endl;
}
} }
END_DEBUG_EXCEPTION_HANDLER END_DEBUG_EXCEPTION_HANDLER
@ -3436,4 +3440,44 @@ void Server::handlePeerChanges()
} }
} }
void dedicated_server_loop(Server &server)
{
DSTACK(__FUNCTION_NAME);
std::cout<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<"Running dedicated server"<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<std::endl;
for(;;)
{
// This is kind of a hack but can be done like this
// because server.step() is very light
sleep_ms(30);
server.step(0.030);
static int counter = 0;
counter--;
if(counter <= 0)
{
counter = 10;
core::list<PlayerInfo> list = server.getPlayerInfo();
core::list<PlayerInfo>::Iterator i;
static u32 sum_old = 0;
u32 sum = PIChecksum(list);
if(sum != sum_old)
{
std::cout<<DTIME<<"Player info:"<<std::endl;
for(i=list.begin(); i!=list.end(); i++)
{
i->PrintLine(&std::cout);
}
}
sum_old = sum;
}
}
}

@ -397,7 +397,6 @@ public:
// Environment and Connection must be locked when called // Environment and Connection must be locked when called
void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver); void SendBlockNoLock(u16 peer_id, MapBlock *block, u8 ver);
//TODO: Sending of many blocks in a single packet
// Environment and Connection must be locked when called // Environment and Connection must be locked when called
//void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver); //void SendSectorMeta(u16 peer_id, core::list<v2s16> ps, u8 ver);
@ -420,7 +419,6 @@ private:
// Virtual methods from con::PeerHandler. // Virtual methods from con::PeerHandler.
// As of now, these create and remove clients and players. // As of now, these create and remove clients and players.
// TODO: Make it possible to leave players on server.
void peerAdded(con::Peer *peer); void peerAdded(con::Peer *peer);
void deletingPeer(con::Peer *peer, bool timeout); void deletingPeer(con::Peer *peer, bool timeout);
@ -514,5 +512,10 @@ private:
friend class RemoteClient; friend class RemoteClient;
}; };
/*
Runs a simple dedicated server loop
*/
void dedicated_server_loop(Server &server);
#endif #endif

@ -301,14 +301,6 @@ int main(int argc, char *argv[])
<<std::endl; <<std::endl;
} }
DSTACK("Dedicated server branch");
std::cout<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<"Running dedicated server"<<std::endl;
std::cout<<"========================"<<std::endl;
std::cout<<std::endl;
// Figure out path to map // Figure out path to map
std::string map_dir = porting::path_userdata+"/map"; std::string map_dir = porting::path_userdata+"/map";
if(cmd_args.exists("map-dir")) if(cmd_args.exists("map-dir"))
@ -316,38 +308,13 @@ int main(int argc, char *argv[])
else if(g_settings.exists("map-dir")) else if(g_settings.exists("map-dir"))
map_dir = g_settings.get("map-dir"); map_dir = g_settings.get("map-dir");
// Create server
Server server(map_dir.c_str(), hm_params, map_params); Server server(map_dir.c_str(), hm_params, map_params);
server.start(port); server.start(port);
for(;;) // Run server
{ dedicated_server_loop(server);
// This is kind of a hack but can be done like this
// because server.step() is very light
sleep_ms(30);
server.step(0.030);
static int counter = 0;
counter--;
if(counter <= 0)
{
counter = 10;
core::list<PlayerInfo> list = server.getPlayerInfo();
core::list<PlayerInfo>::Iterator i;
static u32 sum_old = 0;
u32 sum = PIChecksum(list);
if(sum != sum_old)
{
std::cout<<DTIME<<"Player info:"<<std::endl;
for(i=list.begin(); i!=list.end(); i++)
{
i->PrintLine(&std::cout);
}
}
sum_old = sum;
}
}
} //try } //try
catch(con::PeerNotFoundException &e) catch(con::PeerNotFoundException &e)
{ {

@ -646,7 +646,7 @@ inline std::string lowercase(const std::string &s)
inline bool is_yes(const std::string &s) inline bool is_yes(const std::string &s)
{ {
std::string s2 = lowercase(trim(s)); std::string s2 = lowercase(trim(s));
if(s2 == "y" || s2 == "yes" || s2 == "true") if(s2 == "y" || s2 == "yes" || s2 == "true" || s2 == "1")
return true; return true;
return false; return false;
} }