I'm trying to code a minigame right now, but I need know how to reset a full world as well Can anyone tell me the code? :')
That's the only thing coded by @MCG76 that is propably the best. See MCG plugins with world resetting.
Use this in the AsyncTask, because PocketMine-MP disallow to change, read files(not Config class) from out of AsyncTask. Code: Server::getInstance()->unloadLevel(Server::getInstance()->getLevelByName("example")); $archive = new \ZipArchive; $archive->open($this->getDataFolder() . "example.zip"); $archive->extractTo(Server::getInstance()->getDataPath()."worlds/"); $archive->close(); Server::getInstance()->loadLevel(Server::getInstance()->getLevelByName("example"));
PHP: public function reset() {//tp everybody to another world temporary $this->getServer()->loadLevel("Redirect"); foreach($this->getServer()->getOnlinePlayers() as $p){ $p->getInventory()->clearAll(); $p->teleport($this->getServer()->getLevelByName("Redirect")->getSafeSpawn()); }//replace world $this->getServer()->unloadLevel($this->getServer()->getLevelByName("WorldToReset")); $path = $this->getServer()->getDataPath(); $this->recurse_copy($path."worlds/WorldBackup",$path."worlds/WorldToReset"); $this->getServer()->loadLevel("WorldToReset");//tp everybody back to the world foreach($this->getServer()->getOnlinePlayers() as $p){ $p->teleport($this->getServer()->getLevelByName("WorldToReset")->getSafeSpawn()); } } public function recurse_copy($src,$dst) { $dir = opendir($src); @mkdir($dst); while(false !== ( $file = readdir($dir)) ) { if (( $file != '.' ) && ( $file != '..' )) { if ( is_dir($src . '/' . $file) ) { $this->recurse_copy($src . '/' . $file,$dst . '/' . $file); } else { copy($src . '/' . $file,$dst . '/' . $file); } } } closedir($dir); }
Text file? Terrible idea. PHP: public static function doBackup($backupPath, $worldPath){ $zip = new \ZipArchive; $zip->open($backupPath, \ZipArchive::CREATE); foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($worldPath)) as $file){ if(is_file($file)) $zip->addFile($file, str_replace("\\", "/", ltrim(substr($file, strlen($worldPath)), "/\\"))); }}public function resetLevel(Server $server, $levelName, $backupPath){ $lv = $server->getLevelByName($levelName); if($lv === null) return false; $server->unloadLevel($lv); $worldPath = $server->getDataPath() . "worlds/" . $levelName; self::file_delDir($worldPath); mkdir($worldPath); $zip = new \ZipArchive; $zip->open($backupPath); $zip->extractTo($worldPath); $server->loadLevel($levelName);}public static function file_delDir($dir){ $dir = rtrim($dir, "/\\") . "/"; foreach(scandir($dir) as $file){ if($file === "." or $file === ".."){ continue; } $path = $dir . $file; if(is_dir($path)){ self::dir_delete($path); }else{ unlink($path); } } rmdir($dir);}
Better question yet, how would you reset chunks in a world that is still loaded (if your server only has one world. Would you just save the chunk files, unload the chunk and then replace the chunk files?
It looks pretty good! Can you explain with comments how it works? There are somethings that I really didn't understand
Is there even such function? PHP: public static function doBackup($backupPath, $worldPath){ $zip = new \ZipArchive; // initialize a zip object $zip->open($backupPath, \ZipArchive::CREATE); // create the zip file at the desired path foreach(new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($worldPath)) as $file){ // loop through the world directory recursively if(is_file($file)) // don't add directories $zip->addFile($file, str_replace("\\", "/", ltrim(substr($file, strlen($worldPath)), "/\\"))); // add file into zip.// The second parameter if the path of the file inside the zip.// The str_replace is to replace the windows file separator \ into the common /.// substr calculates the local path by removing the directory we are looping through. }}public function resetLevel(Server $server, $levelName, $backupPath){ // attempt to unload level $lv = $server->getLevelByName($levelName); if($lv === null) return false; $server->unloadLevel($lv); // delete worlds $worldPath = $server->getDataPath() . "worlds/" . $levelName; self::file_delDir($worldPath); // make new world directory mkdir($worldPath); // extract zip file into world path $zip = new \ZipArchive; $zip->open($backupPath); $zip->extractTo($worldPath); // reload level $server->loadLevel($levelName);}public static function file_delDir($dir){ // clean the directory name to ensure it is suffixed with / $dir = rtrim($dir, "/\\") . "/"; // Loop through the files and directories in this directory, NOT recursively foreach(scandir($dir) as $file){ // ignore these two evil sources of bugs if($file === "." or $file === ".."){ continue; } // calculate the real path of the file $path = $dir . $file; // use recursive functions go delete the child directory cleanly if(is_dir($path)){ self::dir_delete($path); }else{ // otherwise, simply delete the file. unlink($path); } } // remove directory. This function only works when the directory is empty. rmdir($dir);}
It don't work, we can't be teleport to the world after reseting. I use ManyWorld and it say "No world with the name .......... exists!"
ManyWorlds might load the worlds into an array when it's enabled so it isn't constantly checking the worlds folder (Not sure in this, I haven't used ManyWorlds or looked through it's source). I'd suggest you just make your own plugin to teleport players between worlds as, it can eliminate other issues you may come across.