diff --git a/src/filesys.cpp b/src/filesys.cpp index a2d3f9d145c2388da2db27ca7aa2c298f704c15f..a025ec18562872392cedcdf3968f542d3754236c 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -19,6 +19,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include <iostream> +#include <string.h> namespace fs { @@ -130,12 +131,35 @@ bool PathExists(std::string path) 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) { @@ -184,7 +208,70 @@ bool PathExists(std::string path) 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 diff --git a/src/filesys.h b/src/filesys.h index 6dbc426a5494454a075047300808e77071eb86b7..e46b17b0def460faace60aa16759a1004890be54 100644 --- a/src/filesys.h +++ b/src/filesys.h @@ -40,6 +40,12 @@ bool CreateDir(std::string path); bool PathExists(std::string path); +// Only pass full paths to this one. True on success. +bool RecursiveDelete(std::string path); + +// Only pass full paths to this one. True on success. +bool RecursiveDeleteContent(std::string path); + }//fs #endif diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp index 84435b5f34fb797f8fcc99b3512dd9972cdc849a..2d02c0295f1238a9c56c95aa1956840fde0495e5 100644 --- a/src/guiMainMenu.cpp +++ b/src/guiMainMenu.cpp @@ -177,6 +177,12 @@ void GUIMainMenu::regenerateGui(v2u32 screensize) 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() @@ -252,10 +258,16 @@ bool GUIMainMenu::OnEvent(const SEvent& event) { 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) diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h index 8060f511d75a6ebf61f71a1e3cf306a0ab92f51d..010d0bf6d975e71dc27b2c29d1bd7e69a39226c9 100644 --- a/src/guiMainMenu.h +++ b/src/guiMainMenu.h @@ -29,11 +29,17 @@ with this program; if not, write to the Free Software Foundation, Inc., struct MainMenuData { + MainMenuData(): + creative_mode(false), + delete_map(false) + {} // These are in the native format of the gui elements std::wstring address; std::wstring port; std::wstring name; bool creative_mode; + // If map deletion is requested, this is set to true + bool delete_map; }; class GUIMainMenu : public GUIModalMenu diff --git a/src/main.cpp b/src/main.cpp index 171f1538a6f3e0e221b8c1c9d12607304dc2e3a1..da1b88d4a9db3220f865a57beb409000251f22f8 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -153,8 +153,10 @@ TODO: Optimize day/night mesh updating somehow meshbuffers? It should go quite fast. - This is not easy; There'd need to be a buffer somewhere that would contain the night and day lighting values. + - Actually if FastFaces would be stored, they could + hold both values -TODO: Combine MapBlock's face caches to so big pieces that VBO +FEATURE: Combine MapBlock's face caches to so big pieces that VBO gets used - That is >500 vertices - This is not easy; all the MapBlocks close to the player would @@ -181,6 +183,10 @@ TODO: Untie client network operations from framerate TODO: Make morning and evening shorter +TODO: Don't update all meshes always on single node changes, but + check which ones should be updated + - implement Map::updateNodeMeshes() + Server: ------- @@ -260,10 +266,15 @@ FEATURE: The map could be generated procedually: - How about relocating minerals, too? Coal and gold in downstream sand and gravel would be kind of cool - This would need a better way of handling minerals, mainly - to have mineral content as a separate field + to have mineral content as a separate field. the first + parameter field is free for this. - Simulate rock falling from cliffs when water has removed enough solid rock from the bottom +TODO: Mineral and ground material properties + - This way mineral ground toughness can be calculated with just + some formula, as well as tool strengths + TODO: Change AttributeList to split the area into smaller sections so that searching won't be as heavy. @@ -308,6 +319,7 @@ Doing now: #pragma comment(lib, "Irrlicht.lib") //#pragma comment(lib, "jthread.lib") #pragma comment(lib, "zlibwapi.lib") +#pragma comment(lib, "Shell32.lib") // This would get rid of the console window //#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") #endif @@ -1270,9 +1282,12 @@ int main(int argc, char *argv[]) porting::initializePaths(); // Create user data directory fs::CreateDir(porting::path_userdata); - + + // C-style stuff initialization initializeMaterialProperties(); + init_mapnode(); + // Debug handler BEGIN_DEBUG_EXCEPTION_HANDLER // Print startup message @@ -1550,7 +1565,7 @@ int main(int argc, char *argv[]) */ init_content_inventory_texture_paths(); - init_tile_textures(); + //init_tile_textures(); /* GUI stuff @@ -1608,10 +1623,10 @@ int main(int argc, char *argv[]) { /* - Out-of-game menu loop + Out-of-game menu loop. + + Loop quits when menu returns proper parameters. */ - - // Wait for proper parameters for(;;) { // Cursor can be non-visible when coming from the game @@ -1671,6 +1686,15 @@ int main(int argc, char *argv[]) dstream<<"Dropping main menu"<<std::endl; menu->drop(); + + // Delete map if requested + if(menudata.delete_map) + { + bool r = fs::RecursiveDeleteContent(map_dir); + if(r == false) + error_message = L"Delete failed"; + continue; + } playername = wide_to_narrow(menudata.name); address = wide_to_narrow(menudata.address); @@ -2386,8 +2410,20 @@ int main(int argc, char *argv[]) static float dig_time = 0.0; static u16 dig_index = 0; + + // Visualize selection + + const float d = 0.502; + core::aabbox3d<f32> nodebox(-BS*d, -BS*d, -BS*d, BS*d, BS*d, BS*d); + v3f nodepos_f = intToFloat(nodepos); + //v3f nodepos_f(nodepos.X*BS, nodepos.Y*BS, nodepos.Z*BS); + nodebox.MinEdge += nodepos_f; + nodebox.MaxEdge += nodepos_f; + hilightboxes.push_back(nodebox); + + //hilightboxes.push_back(nodefacebox); - hilightboxes.push_back(nodefacebox); + // Handle digging if(g_input->getLeftReleased()) { @@ -2473,6 +2509,7 @@ int main(int argc, char *argv[]) if(dig_index < CRACK_ANIMATION_LENGTH) { + //TimeTaker timer("client.setTempMod"); //dstream<<"dig_index="<<dig_index<<std::endl; client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index)); }