#include "filesys.h"
#include <iostream>
+#include <string.h>
namespace fs
{
return (GetFileAttributes(path.c_str()) != INVALID_FILE_ATTRIBUTES);
}
+bool RecursiveDelete(std::string path)
+{
+ std::cerr<<"Removing \""<<path<<"\""<<std::endl;
+
+ return false;
+
+ // This silly function needs a double-null terminated string...
+ // Well, we'll just make sure it has at least two, then.
+ path += "\0\0";
+
+ SHFILEOPSTRUCT sfo;
+ sfo.hwnd = NULL;
+ sfo.wFunc = FO_DELETE;
+ sfo.pFrom = path.c_str();
+ sfo.pTo = NULL;
+ sfo.fFlags = FOF_SILENT | FOF_NOCONFIRMATION | FOF_NOCONFIRMMKDIR;
+
+ int r = SHFileOperation(&sfo);
+
+ return (r == 0);
+}
+
#else // POSIX
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <sys/stat.h>
+#include <sys/wait.h>
std::vector<DirListNode> GetDirListing(std::string pathstring)
{
return (stat(path.c_str(),&st) == 0);
}
+bool RecursiveDelete(std::string path)
+{
+ /*
+ Execute the 'rm' command directly, by fork() and execve()
+ */
+
+ std::cerr<<"Removing \""<<path<<"\""<<std::endl;
+
+ //return false;
+
+ pid_t child_pid = fork();
+
+ if(child_pid == 0)
+ {
+ // Child
+ char argv_data[3][10000];
+ strcpy(argv_data[0], "/bin/rm");
+ strcpy(argv_data[1], "-rf");
+ strncpy(argv_data[2], path.c_str(), 10000);
+ char *argv[4];
+ argv[0] = argv_data[0];
+ argv[1] = argv_data[1];
+ argv[2] = argv_data[2];
+ argv[3] = NULL;
+
+ std::cerr<<"Executing '"<<argv[0]<<"' '"<<argv[1]<<"' '"
+ <<argv[2]<<"'"<<std::endl;
+
+ execv(argv[0], argv);
+
+ // Execv shouldn't return. Failed.
+ return false;
+ }
+ else
+ {
+ // Parent
+ int child_status;
+ pid_t tpid;
+ do{
+ tpid = wait(&child_status);
+ //if(tpid != child_pid) process_terminated(tpid);
+ }while(tpid != child_pid);
+ return (child_status == 0);
+ }
+}
+
#endif
+bool RecursiveDeleteContent(std::string path)
+{
+ std::cerr<<"Removing content of \""<<path<<"\""<<std::endl;
+ std::vector<DirListNode> list = GetDirListing(path);
+ for(unsigned int i=0; i<list.size(); i++)
+ {
+ std::string childpath = path+"/"+list[i].name;
+ bool r = RecursiveDelete(childpath);
+ if(r == false)
+ {
+ std::cerr<<"Removing \""<<childpath<<"\" failed"<<std::endl;
+ return false;
+ }
+ }
+ return true;
+}
+
} // namespace fs
rect = rect + v2s32(size.X/2-180/2, size.Y/2-30/2 + 100);
Environment->addButton(rect, this, 257, L"Start Game / Connect");
}
+ // Map delete button
+ {
+ core::rect<s32> rect(0, 0, 130, 30);
+ rect = rect + v2s32(size.X/2-130/2+200, size.Y/2-30/2 + 100);
+ Environment->addButton(rect, this, 260, L"Delete map");
+ }
}
void GUIMainMenu::drawMenu()
{
switch(event.GUIEvent.Caller->getID())
{
- case 257:
+ case 257: // Start game
acceptInput();
quitMenu();
break;
+ case 260: // Delete map
+ // Don't accept input data, just set deletion request
+ m_data->delete_map = true;
+ m_accepted = true;
+ quitMenu();
+ break;
}
}
if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER)
meshbuffers? It should go quite fast.\r
- This is not easy; There'd need to be a buffer somewhere\r
that would contain the night and day lighting values.\r
+ - Actually if FastFaces would be stored, they could\r
+ hold both values\r
\r
-TODO: Combine MapBlock's face caches to so big pieces that VBO\r
+FEATURE: Combine MapBlock's face caches to so big pieces that VBO\r
gets used\r
- That is >500 vertices\r
- This is not easy; all the MapBlocks close to the player would\r
\r
TODO: Make morning and evening shorter\r
\r
+TODO: Don't update all meshes always on single node changes, but\r
+ check which ones should be updated\r
+ - implement Map::updateNodeMeshes()\r
+\r
Server:\r
-------\r
\r
- How about relocating minerals, too? Coal and gold in\r
downstream sand and gravel would be kind of cool\r
- This would need a better way of handling minerals, mainly\r
- to have mineral content as a separate field\r
+ to have mineral content as a separate field. the first\r
+ parameter field is free for this.\r
- Simulate rock falling from cliffs when water has removed\r
enough solid rock from the bottom\r
\r
+TODO: Mineral and ground material properties\r
+ - This way mineral ground toughness can be calculated with just\r
+ some formula, as well as tool strengths\r
+\r
TODO: Change AttributeList to split the area into smaller sections so\r
that searching won't be as heavy.\r
\r
#pragma comment(lib, "Irrlicht.lib")\r
//#pragma comment(lib, "jthread.lib")\r
#pragma comment(lib, "zlibwapi.lib")\r
+#pragma comment(lib, "Shell32.lib")\r
// This would get rid of the console window\r
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")\r
#endif\r
porting::initializePaths();\r
// Create user data directory\r
fs::CreateDir(porting::path_userdata);\r
-\r
+ \r
+ // C-style stuff initialization\r
initializeMaterialProperties();\r
+ init_mapnode();\r
\r
+ // Debug handler\r
BEGIN_DEBUG_EXCEPTION_HANDLER\r
\r
// Print startup message\r
*/\r
\r
init_content_inventory_texture_paths();\r
- init_tile_textures();\r
+ //init_tile_textures();\r
\r
/*\r
GUI stuff\r
{\r
\r
/*\r
- Out-of-game menu loop\r
+ Out-of-game menu loop.\r
+\r
+ Loop quits when menu returns proper parameters.\r
*/\r
- \r
- // Wait for proper parameters\r
for(;;)\r
{\r
// Cursor can be non-visible when coming from the game\r
dstream<<"Dropping main menu"<<std::endl;\r
\r
menu->drop();\r
+ \r
+ // Delete map if requested\r
+ if(menudata.delete_map)\r
+ {\r
+ bool r = fs::RecursiveDeleteContent(map_dir);\r
+ if(r == false)\r
+ error_message = L"Delete failed";\r
+ continue;\r
+ }\r
\r
playername = wide_to_narrow(menudata.name);\r
address = wide_to_narrow(menudata.address);\r
\r
static float dig_time = 0.0;\r
static u16 dig_index = 0;\r
+ \r
+ // Visualize selection\r
+\r
+ const float d = 0.502;\r
+ core::aabbox3d<f32> nodebox(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d);\r
+ v3f nodepos_f = intToFloat(nodepos);\r
+ //v3f nodepos_f(nodepos.X*BS, nodepos.Y*BS, nodepos.Z*BS);\r
+ nodebox.MinEdge += nodepos_f;\r
+ nodebox.MaxEdge += nodepos_f;\r
+ hilightboxes.push_back(nodebox);\r
+ \r
+ //hilightboxes.push_back(nodefacebox);\r
\r
- hilightboxes.push_back(nodefacebox);\r
+ // Handle digging\r
\r
if(g_input->getLeftReleased())\r
{\r
\r
if(dig_index < CRACK_ANIMATION_LENGTH)\r
{\r
+ //TimeTaker timer("client.setTempMod");\r
//dstream<<"dig_index="<<dig_index<<std::endl;\r
client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));\r
}\r