From ac6939ce94001d3497b696a44a28f6348e5213ae Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 22:44:42 -0500 Subject: [PATCH 01/47] Swapped data storage to use libasynql --- .poggit.yml | 2 + resources/config.yml | 30 +- resources/mysql.sql | 185 +++++++++++ resources/sqlite.sql | 180 ++++++++++ src/MyPlot/MyPlot.php | 52 +-- src/MyPlot/provider/ConfigDataProvider.php | 209 ------------ src/MyPlot/provider/DataProvider.php | 209 +++++++++--- src/MyPlot/provider/MySQLProvider.php | 370 --------------------- src/MyPlot/provider/SQLiteDataProvider.php | 315 ------------------ 9 files changed, 556 insertions(+), 996 deletions(-) create mode 100644 resources/mysql.sql create mode 100644 resources/sqlite.sql delete mode 100644 src/MyPlot/provider/ConfigDataProvider.php delete mode 100644 src/MyPlot/provider/MySQLProvider.php delete mode 100644 src/MyPlot/provider/SQLiteDataProvider.php diff --git a/.poggit.yml b/.poggit.yml index 1be598b0..b5efc69e 100644 --- a/.poggit.yml +++ b/.poggit.yml @@ -4,6 +4,8 @@ projects: icon: "icon.png" path: "" libs: + - src: poggit/libasynql/libasynql + version: ^3.3.0 - src: dktapps-pm-pl/pmforms/pmforms version: ^2.0.0 lint: false diff --git a/resources/config.yml b/resources/config.yml index 098e7dbb..7623816e 100644 --- a/resources/config.yml +++ b/resources/config.yml @@ -37,17 +37,25 @@ Custom Messages: false UI Forms: true # The data provider where plot data is stored. -# Current providers are: sqlite, mysql, json, and yaml. -DataProvider: sqlite - -# contains settings for mysql provider to use when selected -MySQLSettings: - Host: 127.0.0.1 - Port: 3306 - Username: default - Password: password - DatabaseName: MyPlot - ShutdownOnFailure: false +database: + # The database type. "sqlite" and "mysql" are supported. + type: sqlite + + # Edit these settings only if you choose "sqlite". + sqlite: + # The file name of the database in the plugin data folder. + # You can also put an absolute path here. + file: plots.db + # Edit these settings only if you choose "mysql". + mysql: + host: 127.0.0.1 + # Avoid using the "root" user for security reasons. + username: default + password: password + schema: myplot + # The maximum number of simultaneous SQL queries + # Recommended: 1 for sqlite, 2 for MySQL. You may want to further increase this value if your MySQL connection is very slow. + worker-limit: 1 # Use an economy with MyPlot. This will allow for plot pricing such as claiming, clearing, etc. # Currently supported economy plugins: Economy$ diff --git a/resources/mysql.sql b/resources/mysql.sql new file mode 100644 index 00000000..e62c0ed0 --- /dev/null +++ b/resources/mysql.sql @@ -0,0 +1,185 @@ +-- #!mysql +-- #{myplot +-- # {init +-- # {plots +CREATE TABLE IF NOT EXISTS plotsV2 +( + level TEXT, + X INT, + Z INT, + name TEXT, + owner TEXT, + helpers TEXT, + denied TEXT, + biome TEXT, + pvp INT, + price FLOAT, + PRIMARY KEY (level, X, Z) +); +-- # } +-- # {mergedPlots +CREATE TABLE IF NOT EXISTS mergedPlotsV2 +( + level TEXT, + originX INT, + originZ INT, + mergedX INT, + mergedZ INT, + PRIMARY KEY (level, originX, originZ, mergedX, mergedZ) +); +-- # } +-- # } +-- # {add +-- # {plot +-- # :level string +-- # :X int +-- # :Z int +-- # :name string +-- # :owner string +-- # :helpers string +-- # :denied string +-- # :biome string +-- # :pvp bool false +-- # :price int +INSERT INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) +VALUES (:level, :X, :Z, :name, :owner, :helpers, :denied, :biome, :pvp, :price) +ON DUPLICATE KEY UPDATE name = VALUES(:name), + owner = VALUES(:owner), + helpers = VALUES(:helpers), + denied = VALUES(:denied), + biome = VALUES(:biome), + pvp = VALUES(:pvp), + price = VALUES(:price); +-- # } +-- # {merge +-- # :level string +-- # :originX int +-- # :originZ int +-- # :mergedX int +-- # :mergedZ int +INSERT IGNORE INTO mergedPlotsV2 (`level`, `originX`, `originZ`, `mergedX`, `mergedZ`) +VALUES (:level, :originX, :originZ, :mergedX, :mergedZ); +-- # } +-- # } +-- # {get +-- # {plot +-- # {by-xz +-- # :level string +-- # :X int +-- # :Z int +SELECT name, owner, helpers, denied, biome, pvp, price +FROM plotsV2 +WHERE level = :level + AND X = :x + AND Z = :z; +-- # } +-- # } +-- # {all-plots +-- # {by-owner +-- # :owner string +SELECT * +FROM plotsV2 +WHERE owner = :owner; +-- # } +-- # } +-- # {all-plots +-- # {by-owner-and-level +-- # :owner string +-- # :level string +SELECT * +FROM plotsV2 +WHERE owner = :owner + AND level = :level; +-- # } +-- # } +-- # {highest-existing +-- # {by-interval +-- # :level string +-- # :number int +SELECT X, Z +FROM plotsV2 +WHERE (level = :level AND ((abs(X) = :number AND abs(Z) <= :number) OR (abs(Z) = :number AND abs(X) <= :number))); +-- # } +-- # } +-- # {merge-origin +-- # {by-merged +-- # :level string +-- # :mergedX int +-- # :mergedZ int +SELECT plotsV2.level, + X, + Z, + name, + owner, + helpers, + denied, + biome, + pvp, + price +FROM plotsV2 + LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level +WHERE mergedPlotsV2.level = :level + AND mergedX = :mergedX + AND mergedZ = :mergedZ; +-- # } +-- # } +-- # } +-- # {merge-plots +-- # {by-origin +-- # :level string +-- # :originX int +-- # :originZ int +SELECT plotsV2.level, + X, + Z, + name, + owner, + helpers, + denied, + biome, + pvp, + price +FROM plotsV2 + LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedPlotsV2.mergedX = plotsV2.X AND + mergedPlotsV2.mergedZ = plotsV2.Z +WHERE mergedPlotsV2.level = :level + AND originX = :originX + AND originZ = :originZ; +-- # } +-- # } +-- # } +-- # {remove +-- # {plot +-- # {by-xz +-- # :level string +-- # :x int +-- # :z int +DELETE +FROM plotsV2 +WHERE level = :level + AND X = :X + AND Z = :Z; +-- # } +-- # } +-- # {merge +-- # {by-xz +-- # :level string +-- # :x int +-- # :z int +-- # :biome string +-- # :pvp bool false +-- # :price int +UPDATE plotsV2 +SET name = '', + owner = '', + helpers = '', + denied = '', + biome = :biome, + pvp = :pvp, + price = :price +WHERE level = :level + AND X = :x + AND Z = :z; +-- # } +-- # } +-- # } \ No newline at end of file diff --git a/resources/sqlite.sql b/resources/sqlite.sql new file mode 100644 index 00000000..2018d14f --- /dev/null +++ b/resources/sqlite.sql @@ -0,0 +1,180 @@ +-- #!mysql +-- #{myplot +-- # {init +-- # {plots +CREATE TABLE IF NOT EXISTS plotsV2 +( + level TEXT, + X INTEGER, + Z INTEGER, + name TEXT, + owner TEXT, + helpers TEXT, + denied TEXT, + biome TEXT, + pvp INTEGER, + price FLOAT, + PRIMARY KEY (level, X, Z) +); +-- # } +-- # {mergedPlots +CREATE TABLE IF NOT EXISTS mergedPlotsV2 +( + level TEXT, + originX INTEGER, + originZ INTEGER, + mergedX INTEGER, + mergedZ INTEGER, + PRIMARY KEY (level, originX, originZ, mergedX, mergedZ) +); +-- # } +-- # } +-- # {add +-- # {plot +-- # :level string +-- # :X int +-- # :Z int +-- # :name string +-- # :owner string +-- # :helpers string +-- # :denied string +-- # :biome string +-- # :pvp bool false +-- # :price int +INSERT OR +REPLACE +INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) +VALUES (:level, :X, :Z, :name, :owner, :helpers, :denied, :biome, :pvp, :price); +-- # } +-- # {merge +-- # :level string +-- # :originX int +-- # :originZ int +-- # :mergedX int +-- # :mergedZ int +INSERT OR +REPLACE +INTO mergedPlotsV2 (level, originX, originZ, mergedX, mergedZ) +VALUES (:level, :originX, :originZ, :mergedX, :mergedZ); +-- # } +-- # } +-- # {get +-- # {plot +-- # {by-xz +-- # :level string +-- # :X int +-- # :Z int +SELECT name, owner, helpers, denied, biome, pvp, price +FROM plotsV2 +WHERE level = :level + AND X = :X + AND Z = :Z; +-- # } +-- # } +-- # {all-plots +-- # {by-owner +-- # :owner string +SELECT * +FROM plotsV2 +WHERE owner = :owner; +-- # } +-- # } +-- # {all-plots +-- # {by-owner-and-level +-- # :owner string +-- # :level string +SELECT * +FROM plotsV2 +WHERE owner = :owner + AND level = :level; +-- # } +-- # } +-- # {highest-existing +-- # {by-interval +-- # :level string +-- # :number int +SELECT X, Z +FROM plotsV2 +WHERE (level = :level AND ((abs(X) = :number AND abs(Z) <= :number) OR (abs(Z) = :number AND abs(X) <= :number))); +-- # } +-- # } +-- # {merge-origin +-- # {by-merged +-- # :level string +-- # :mergedX int +-- # :mergedZ int +SELECT plotsV2.level, + X, + Z, + name, + owner, + helpers, + denied, + biome, + pvp, + price +FROM plotsV2 + LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level +WHERE mergedPlotsV2.level = :level + AND mergedX = :mergedX + AND mergedZ = :mergedZ; +-- # } +-- # } +-- # } +-- # {merge-plots +-- # {by-origin +-- # :level string +-- # :originX int +-- # :originZ int +SELECT plotsV2.level, + X, + Z, + name, + owner, + helpers, + denied, + biome, + pvp, + price +FROM plotsV2 + LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedPlotsV2.mergedX = plotsV2.X AND + mergedPlotsV2.mergedZ = plotsV2.Z +WHERE mergedPlotsV2.level = :level + AND originX = :originX + AND originZ = :originZ; +-- # } +-- # } +-- # } +-- # {remove +-- # {plot +-- # {by-xz +-- # :level string +-- # :X int +-- # :Z int +DELETE +FROM plotsV2 +WHERE level = :level + AND X = :X + AND Z = :Z; +-- # } +-- # } +-- # {merge +-- # {by-xz +-- # :level string +-- # :X int +-- # :Z int +-- # :biome string +UPDATE plotsV2 +SET name = '', + owner = '', + helpers = '', + denied = '', + biome = :biome, + pvp = 0, + price = 0.0 +WHERE level = :level + AND X = :X + AND Z = :Z; +-- # } +-- # } +-- # } \ No newline at end of file diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 1d0fbdbb..2f4ec60c 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -2,6 +2,7 @@ declare(strict_types=1); namespace MyPlot; +use jasonwynn10\MyPlot\utils\AsyncVariants; use muqsit\worldstyler\Selection; use muqsit\worldstyler\shapes\CommonShape; use muqsit\worldstyler\shapes\Cuboid; @@ -15,12 +16,9 @@ use MyPlot\events\MyPlotResetEvent; use MyPlot\events\MyPlotSettingEvent; use MyPlot\events\MyPlotTeleportEvent; -use MyPlot\provider\ConfigDataProvider; use MyPlot\provider\DataProvider; use MyPlot\provider\EconomyProvider; use MyPlot\provider\EconomySProvider; -use MyPlot\provider\MySQLProvider; -use MyPlot\provider\SQLiteDataProvider; use MyPlot\task\ClearBorderTask; use MyPlot\task\ClearPlotTask; use MyPlot\task\FillPlotTask; @@ -40,6 +38,8 @@ use pocketmine\permission\PermissionManager; use pocketmine\player\Player; use pocketmine\plugin\PluginBase; +use pocketmine\promise\Promise; +use pocketmine\promise\PromiseResolver; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Config; use pocketmine\utils\TextFormat as TF; @@ -50,6 +50,7 @@ use pocketmine\world\Position; use pocketmine\world\World; use pocketmine\world\WorldCreationOptions; +use SOFe\AwaitGenerator\Await; class MyPlot extends PluginBase { @@ -1345,50 +1346,7 @@ public function onLoad() : void { } $this->getLogger()->debug(TF::BOLD . "Loading Data Provider settings"); // Initialize DataProvider - /** @var int $cacheSize */ - $cacheSize = $this->getConfig()->get("PlotCacheSize", 256); - $dataProvider = $this->getConfig()->get("DataProvider", "sqlite3"); - if(!is_string($dataProvider)) - $this->dataProvider = new ConfigDataProvider($this, $cacheSize); - else - try { - switch(strtolower($dataProvider)) { - case "mysqli": - case "mysql": - if(extension_loaded("mysqli")) { - $settings = (array) $this->getConfig()->get("MySQLSettings"); - $this->dataProvider = new MySQLProvider($this, $cacheSize, $settings); - }else { - $this->getLogger()->warning("MySQLi is not installed in your php build! JSON will be used instead."); - $this->dataProvider = new ConfigDataProvider($this, $cacheSize); - } - break; - case "yaml": - if(extension_loaded("yaml")) { - $this->dataProvider = new ConfigDataProvider($this, $cacheSize, true); - }else { - $this->getLogger()->warning("YAML is not installed in your php build! JSON will be used instead."); - $this->dataProvider = new ConfigDataProvider($this, $cacheSize); - } - break; - case "sqlite3": - case "sqlite": - if(extension_loaded("sqlite3")) { - $this->dataProvider = new SQLiteDataProvider($this, $cacheSize); - }else { - $this->getLogger()->warning("SQLite3 is not installed in your php build! JSON will be used instead."); - $this->dataProvider = new ConfigDataProvider($this, $cacheSize); - } - break; - case "json": - default: - $this->dataProvider = new ConfigDataProvider($this, $cacheSize); - break; - } - }catch(\Exception $e) { - $this->getLogger()->error("The selected data provider crashed. JSON will be used instead."); - $this->dataProvider = new ConfigDataProvider($this, $cacheSize); - } + $this->dataProvider = new DataProvider($this); $this->getLogger()->debug(TF::BOLD . "Loading Plot Clearing settings"); if($this->getConfig()->get("FastClearing", false) === true and $this->getServer()->getPluginManager()->getPlugin("WorldStyler") === null) { $this->getConfig()->set("FastClearing", false); diff --git a/src/MyPlot/provider/ConfigDataProvider.php b/src/MyPlot/provider/ConfigDataProvider.php deleted file mode 100644 index 1ffaba1a..00000000 --- a/src/MyPlot/provider/ConfigDataProvider.php +++ /dev/null @@ -1,209 +0,0 @@ -plugin->getDataFolder() . "Data"); - $this->config = new Config($this->plugin->getDataFolder() . "Data" . DIRECTORY_SEPARATOR . "plots".($yaml ? '.yml' : '.json'), $yaml ? Config::YAML : Config::JSON, ["plots" => [], "merges" => []]); - } - - public function savePlot(Plot $plot) : bool { - $plotId = $plot->levelName.';'.$plot->X.';'.$plot->Z; - $plots = $this->config->get("plots", []); - $plots[$plotId] = ["level" => $plot->levelName, "x" => $plot->X, "z" => $plot->Z, "name" => $plot->name, "owner" => $plot->owner, "helpers" => $plot->helpers, "denied" => $plot->denied, "biome" => $plot->biome, "pvp" => $plot->pvp, "price" => $plot->price]; - $this->config->set("plots", $plots); - $this->cachePlot($plot); - $this->config->save(); - return true; - } - - public function deletePlot(Plot $plot) : bool { - $plotId = $plot->levelName.';'.$plot->X.';'.$plot->Z; - $plots = $this->config->get("plots", []); - unset($plots[$plotId]); - $this->config->set("plots", $plots); - $plot = new Plot($plot->levelName, $plot->X, $plot->Z); - $this->cachePlot($plot); - $this->config->save(); - return true; - } - - public function getPlot(string $levelName, int $X, int $Z) : Plot { - if(($plot = $this->getPlotFromCache($levelName, $X, $Z)) !== null) { - return $plot; - } - $plots = (array)$this->config->get("plots", []); - $key = $levelName.';'.$X.';'.$Z; - if(isset($plots[$key])) { - $plotName = (string)$plots[$key]["name"]; - $owner = (string)$plots[$key]["owner"]; - $helpers = (array)$plots[$key]["helpers"]; - $denied = (array)$plots[$key]["denied"]; - $biome = strtoupper($plots[$key]["biome"]); - $pvp = (bool)$plots[$key]["pvp"]; - $price = (float)$plots[$key]["price"]; - return new Plot($levelName, $X, $Z, $plotName, $owner, $helpers, $denied, $biome, $pvp, $price); - } - return new Plot($levelName, $X, $Z); - } - - /** - * @param string $owner - * @param string $levelName - * - * @return Plot[] - */ - public function getPlotsByOwner(string $owner, string $levelName = "") : array { - $plots = $this->config->get("plots", []); - $ownerPlots = []; - /** @var string[] $ownerKeys */ - $ownerKeys = array_keys($plots, ["owner" => $owner], true); - foreach($ownerKeys as $ownerKey) { - if($levelName === "" or str_contains($ownerKey, $levelName)) { - $X = $plots[$ownerKey]["x"]; - $Z = $plots[$ownerKey]["z"]; - $plotName = $plots[$ownerKey]["name"] == "" ? "" : $plots[$ownerKey]["name"]; - $owner = $plots[$ownerKey]["owner"] == "" ? "" : $plots[$ownerKey]["owner"]; - $helpers = $plots[$ownerKey]["helpers"] == [] ? [] : $plots[$ownerKey]["helpers"]; - $denied = $plots[$ownerKey]["denied"] == [] ? [] : $plots[$ownerKey]["denied"]; - $biome = strtoupper($plots[$ownerKey]["biome"]) == "PLAINS" ? "PLAINS" : strtoupper($plots[$ownerKey]["biome"]); - $pvp = $plots[$ownerKey]["pvp"] == null ? false : $plots[$ownerKey]["pvp"]; - $price = $plots[$ownerKey]["price"] == null ? 0 : $plots[$ownerKey]["price"]; - $ownerPlots[] = new Plot($levelName, $X, $Z, $plotName, $owner, $helpers, $denied, $biome, $pvp, $price); - } - } - return $ownerPlots; - } - - public function getNextFreePlot(string $levelName, int $limitXZ = 0) : ?Plot { - $plotsArr = $this->config->get("plots", []); - for($i = 0; $limitXZ <= 0 or $i < $limitXZ; $i++) { - $existing = []; - foreach($plotsArr as $data) { - if($data["level"] === $levelName) { - if(abs($data["x"]) === $i and abs($data["z"]) <= $i) { - $existing[] = [$data["x"], $data["z"]]; - }elseif(abs($data["z"]) === $i and abs($data["x"]) <= $i) { - $existing[] = [$data["x"], $data["z"]]; - } - } - } - $plots = []; - foreach($existing as $XZ) { - $plots[$XZ[0]][$XZ[1]] = true; - } - if(count($plots) === max(1, 8 * $i)) { - continue; - } - if(($ret = self::findEmptyPlotSquared(0, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - for($a = 1; $a < $i; $a++) { - if(($ret = self::findEmptyPlotSquared($a, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - } - if(($ret = self::findEmptyPlotSquared($i, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - } - return null; - } - - public function mergePlots(Plot $base, Plot ...$plots) : bool { - $originId = $base->levelName.';'.$base->X.';'.$base->Z; - $mergedIds = $this->config->getNested("merges.$originId", []); - $mergedIds = array_merge($mergedIds, array_map(function(Plot $val) : string { - return $val->levelName.';'.$val->X.';'.$val->Z; - }, $plots)); - $mergedIds = array_unique($mergedIds, SORT_NUMERIC); - $this->config->setNested("merges.$originId", $mergedIds); - $this->config->save(); - return true; - } - - public function getMergedPlots(Plot $plot, bool $adjacent = false) : array { - $originId = $plot->levelName.';'.$plot->X.';'.$plot->Z; - $mergedIds = $this->config->getNested("merges.$originId", []); - $plotDatums = $this->config->get("plots", []); - $plots = [$plot]; - foreach($mergedIds as $mergedId) { - if(!isset($plotDatums[$mergedId])) - continue; - $levelName = $plotDatums[$mergedId]["level"]; - $X = $plotDatums[$mergedId]["x"]; - $Z = $plotDatums[$mergedId]["z"]; - $plotName = $plotDatums[$mergedId]["name"] == "" ? "" : $plotDatums[$mergedId]["name"]; - $owner = $plotDatums[$mergedId]["owner"] == "" ? "" : $plotDatums[$mergedId]["owner"]; - $helpers = $plotDatums[$mergedId]["helpers"] == [] ? [] : $plotDatums[$mergedId]["helpers"]; - $denied = $plotDatums[$mergedId]["denied"] == [] ? [] : $plotDatums[$mergedId]["denied"]; - $biome = strtoupper($plotDatums[$mergedId]["biome"]) == "PLAINS" ? "PLAINS" : strtoupper($plotDatums[$mergedId]["biome"]); - $pvp = $plotDatums[$mergedId]["pvp"] == null ? false : $plotDatums[$mergedId]["pvp"]; - $price = $plotDatums[$mergedId]["price"] == null ? 0 : $plotDatums[$mergedId]["price"]; - $plots[] = new Plot($levelName, $X, $Z, $plotName, $owner, $helpers, $denied, $biome, $pvp, $price); - } - if($adjacent) - $plots = array_filter($plots, function(Plot $val) use ($plot) { - for($i = Facing::NORTH; $i <= Facing::EAST; ++$i) { - if($plot->getSide($i)->isSame($val)) - return true; - } - return false; - }); - return $plots; - } - - public function getMergeOrigin(Plot $plot) : Plot { - $mergedIdString = $plot->levelName.';'.$plot->X.';'.$plot->Z; - $allMerges = $this->config->get("merges", []); - if(isset($allMerges[$mergedIdString])) - return $plot; - $originId = array_search($mergedIdString, $allMerges, true); - $plotDatums = $this->config->get("plots", []); - if(isset($plotDatums[$originId])) { - $levelName = $plotDatums[$originId]["level"]; - $X = $plotDatums[$originId]["x"]; - $Z = $plotDatums[$originId]["z"]; - $plotName = $plotDatums[$originId]["name"] == "" ? "" : $plotDatums[$originId]["name"]; - $owner = $plotDatums[$originId]["owner"] == "" ? "" : $plotDatums[$originId]["owner"]; - $helpers = $plotDatums[$originId]["helpers"] == [] ? [] : $plotDatums[$originId]["helpers"]; - $denied = $plotDatums[$originId]["denied"] == [] ? [] : $plotDatums[$originId]["denied"]; - $biome = strtoupper($plotDatums[$originId]["biome"]) == "PLAINS" ? "PLAINS" : strtoupper($plotDatums[$originId]["biome"]); - $pvp = $plotDatums[$originId]["pvp"] == null ? false : $plotDatums[$originId]["pvp"]; - $price = $plotDatums[$originId]["price"] == null ? 0 : $plotDatums[$originId]["price"]; - return new Plot($levelName, $X, $Z, $plotName, $owner, $helpers, $denied, $biome, $pvp, $price); - } - return $plot; - } - - public function close() : void { - $this->config->save(); - unset($this->config); - } -} \ No newline at end of file diff --git a/src/MyPlot/provider/DataProvider.php b/src/MyPlot/provider/DataProvider.php index 7cea29c2..ce65d052 100644 --- a/src/MyPlot/provider/DataProvider.php +++ b/src/MyPlot/provider/DataProvider.php @@ -4,32 +4,31 @@ use MyPlot\MyPlot; use MyPlot\Plot; +use pocketmine\math\Facing; +use poggit\libasynql\DataConnector; +use poggit\libasynql\libasynql; + +final class DataProvider{ -abstract class DataProvider -{ /** @var Plot[] $cache */ private array $cache = []; private int $cacheSize; - protected MyPlot $plugin; + private DataConnector $database; - /** - * DataProvider constructor. - * - * @param MyPlot $plugin - * @param int $cacheSize - */ - public function __construct(MyPlot $plugin, int $cacheSize = 0) { - $this->plugin = $plugin; - $this->cacheSize = $cacheSize; + public function __construct(protected MyPlot $plugin){ + $this->database = libasynql::create($plugin, $plugin->getConfig()->get("Database"), [ + 'sqlite' => 'sqlite.sql', + 'mysql' => 'mysql.sql', + ]); + $this->cacheSize = $plugin->getConfig()->get("PlotCacheSize", 2048); } - protected final function cachePlot(Plot $plot) : void { - if($this->cacheSize > 0) { + private function cachePlot(Plot $plot) : void{ + if($this->cacheSize > 0){ $key = $plot->levelName . ';' . $plot->X . ';' . $plot->Z; - if(isset($this->cache[$key])) { + if(isset($this->cache[$key])){ unset($this->cache[$key]); - } - elseif($this->cacheSize <= count($this->cache)) { + }elseif($this->cacheSize <= count($this->cache)){ array_shift($this->cache); } $this->cache = array_merge([$key => clone $plot], $this->cache); @@ -37,10 +36,10 @@ protected final function cachePlot(Plot $plot) : void { } } - protected final function getPlotFromCache(string $levelName, int $X, int $Z) : ?Plot { - if($this->cacheSize > 0) { + private function getPlotFromCache(string $levelName, int $X, int $Z) : ?Plot{ + if($this->cacheSize > 0){ $key = $levelName . ';' . $X . ';' . $Z; - if(isset($this->cache[$key])) { + if(isset($this->cache[$key])){ #$this->plugin->getLogger()->debug("Plot {$X};{$Z} was loaded from the cache"); return $this->cache[$key]; } @@ -48,48 +47,170 @@ protected final function getPlotFromCache(string $levelName, int $X, int $Z) : ? return null; } - public abstract function savePlot(Plot $plot) : bool; + public function savePlot(Plot $plot) : \Generator{ + [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.plot', [ + 'level' => $plot->levelName, + 'X' => $plot->X, + 'Z' => $plot->Z, + 'name' => $plot->name, + 'owner' => $plot->owner, + 'helpers' => implode(",", $plot->helpers), + 'denied' => implode(",", $plot->denied), + 'biome' => $plot->biome, + 'pvp' => $plot->pvp, + 'price' => $plot->price, + ]); + if($affectedRows < 1){ + return false; + } + $this->cachePlot($plot); + return true; + } - public abstract function deletePlot(Plot $plot) : bool; + public function deletePlot(Plot $plot) : \Generator{ + if($plot->isMerged()){ + $changedRows = yield $this->database->asyncChange('myplot.remove.merge.by-xz', [ + 'level' => $plot->levelName, + 'X' => $plot->X, + 'Z' => $plot->Z, + ]); + }else{ + $changedRows = yield $this->database->asyncChange('myplot.remove.plot.by-xz', [ + 'level' => $plot->levelName, + 'X' => $plot->X, + 'Z' => $plot->Z, + ]); + } + if($changedRows < 1){ + return false; + } + $this->cachePlot(new Plot($plot->levelName, $plot->X, $plot->Z)); + return true; + } - public abstract function getPlot(string $levelName, int $X, int $Z) : Plot; + public function getPlot(string $levelName, int $X, int $Z) : \Generator{ + $plot = $this->getPlotFromCache($levelName, $X, $Z); + if($plot !== null){ + return $plot; + } + $row = yield $this->database->asyncSelect('myplot.get.plot.by-xz', [ + 'level' => $levelName, + 'X' => $X, + 'Z' => $Z + ]); + return new Plot($levelName, $X, $Z, $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + } - /** - * @param string $owner - * @param string $levelName - * - * @return Plot[] - */ - public abstract function getPlotsByOwner(string $owner, string $levelName = "") : array; + public function getPlotsByOwner(string $owner, string $levelName = "") : \Generator{ + if($levelName !== null){ + $rows = yield $this->database->asyncSelect('myplot.get.all-plots.by-owner-and-level', [ + 'owner' => $owner, + 'level' => $levelName, + ]); + }else{ + $rows = yield $this->database->asyncSelect('myplot.get.all-plots.by-owner', [ + 'owner' => $owner, + ]); + } + $plots = []; + foreach($rows as $row){ + $plots[] = new Plot($row['level'], $row['X'], $row['Z'], $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + } + return $plots; + } - public abstract function getNextFreePlot(string $levelName, int $limitXZ = 0) : ?Plot; + public function getNextFreePlot(string $levelName, int $limitXZ = 0) : \Generator{ + for($i = 0; $limitXZ <= 0 or $i < $limitXZ; $i++){ + $rows = yield $this->database->asyncSelect('myplot.get.highest-existing.by-interval', [ + 'level' => $levelName, + 'number' => $i, + ]); + $plots = []; + foreach($rows as $row){ + $plots[$row['X']][$row['Z']] = true; + } + if(count($plots) === max(1, 8 * $i)){ + continue; + } + for($a = 0; $a <= $i; $a++){ + if(($ret = self::findEmptyPlotSquared($a, $i, $plots)) !== null){ + [$X, $Z] = $ret; + return new Plot($levelName, $X, $Z); + } + } + } + return null; + } - public abstract function mergePlots(Plot $base, Plot ...$plots) : bool; + public function mergePlots(Plot $base, Plot ...$plots) : \Generator{ + $ret = true; + foreach($plots as $plot){ + [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.merge', [ + 'level' => $base->levelName, + 'originX' => $base->X, + 'originZ' => $base->Z, + 'mergedX' => $plot->X, + 'mergedZ' => $plot->Z + ]); + if($affectedRows < 1){ + MyPlot::getInstance()->getLogger()->debug("Failed to merge plot $plot into $base"); + $ret = false; + } + } + return $ret; + } - /** - * @param Plot $plot - * @param bool $adjacent - * @return Plot[] - */ - public abstract function getMergedPlots(Plot $plot, bool $adjacent = false) : array; + public function getMergedPlots(Plot $plot, bool $adjacent = false) : \Generator{ + $origin = yield $this->getMergeOrigin($plot); + $rows = $this->database->asyncSelect('myplot.get.merge-plots.by-origin', [ + 'level' => $plot->levelName, + 'originX' => $plot->X, + 'originZ' => $plot->Z + ]); + $plots = [$origin]; + foreach($rows as $row){ + $helpers = explode(",", $row["helpers"]); + $denied = explode(",", $row["denied"]); + $pvp = is_numeric($row["pvp"]) ? (bool) $row["pvp"] : null; + $plots[] = new Plot($row["level"], $row["X"], $row["Z"], $row["name"], $row["owner"], $helpers, $denied, $row["biome"], $pvp, $row["price"]); + } + if($adjacent) + $plots = array_filter($plots, function(Plot $val) use ($plot) : bool{ + foreach(Facing::HORIZONTAL as $i){ + if($plot->getSide($i)->isSame($val)) + return true; + } + return false; + }); + return $plots; + } - public abstract function getMergeOrigin(Plot $plot) : Plot; + public function getMergeOrigin(Plot $plot) : \Generator{ + $row = yield $this->database->asyncSelect('myplot.get.merge-origin.by-merged', [ + 'level' => $plot->levelName, + 'mergedX' => $plot->X, + 'mergedZ' => $plot->Z + ]); + return new Plot($row['level'], $row['X'], $row['Z'], $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + } - public abstract function close() : void; + public function close() : void{ + $this->database->close(); + } /** - * @param int $a - * @param int $b + * @param int $a + * @param int $b * @param bool[][] $plots * * @return int[]|null */ - protected static function findEmptyPlotSquared(int $a, int $b, array $plots) : ?array { + private static function findEmptyPlotSquared(int $a, int $b, array $plots) : ?array{ if(!isset($plots[$a][$b])) return [$a, $b]; if(!isset($plots[$b][$a])) return [$b, $a]; - if($a !== 0) { + if($a !== 0){ if(!isset($plots[-$a][$b])) return [-$a, $b]; if(!isset($plots[$b][-$a])) diff --git a/src/MyPlot/provider/MySQLProvider.php b/src/MyPlot/provider/MySQLProvider.php deleted file mode 100644 index 63a35909..00000000 --- a/src/MyPlot/provider/MySQLProvider.php +++ /dev/null @@ -1,370 +0,0 @@ -plugin = $plugin; - parent::__construct($plugin, $cacheSize); - $this->settings = $settings; - $this->db = new \mysqli($settings['Host'], $settings['Username'], $settings['Password'], $settings['DatabaseName'], $settings['Port']); - if($this->db->connect_error !== null and $this->db->connect_error !== '') - throw new \RuntimeException("Failed to connect to the MySQL database: " . $this->db->connect_error); - $this->db->query("CREATE TABLE IF NOT EXISTS plotsV2 (level TEXT, X INT, Z INT, name TEXT, owner TEXT, helpers TEXT, denied TEXT, biome TEXT, pvp INT, price FLOAT, PRIMARY KEY (level, X, Z));"); - $res = $this->db->query("SELECT count(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='{$settings['DatabaseName']}' AND TABLE_NAME='plots'"); - if($res instanceof \mysqli_result and $res->fetch_array()[0] > 0) - $this->db->query("INSERT IGNORE INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) SELECT level, X, Z, name, owner, helpers, denied, biome, pvp, price FROM plots;"); - $this->db->query("CREATE TABLE IF NOT EXISTS mergedPlotsV2 (level TEXT, originX INT, originZ INT, mergedX INT, mergedZ INT, PRIMARY KEY(level, originX, originZ, mergedX, mergedZ));"); - $res = $this->db->query("SELECT count(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA='{$settings['DatabaseName']}' AND TABLE_NAME='mergedPlots';"); - if($res instanceof \mysqli_result and $res->fetch_array()[0] > 0) - $this->db->query("INSERT IGNORE INTO mergedPlotsV2 (level, originX, originZ, mergedX, mergedZ) SELECT r1.level, r1.X, r1.Z, r2.X, r2.Z FROM plots r1, mergedPlots JOIN plots r2 ON r1.id = mergedPlots.originId AND r2.id = mergedPlots.mergedId;"); - $this->prepare(); - $this->plugin->getLogger()->debug("MySQL data provider registered"); - } - - /** - * @throws \Exception - */ - public function savePlot(Plot $plot) : bool { - $this->reconnect(); - $helpers = implode(',', $plot->helpers); - $denied = implode(',', $plot->denied); - $stmt = $this->sqlSavePlot; - $stmt->bind_param('siisssssid', $plot->levelName, $plot->X, $plot->Z, $plot->name, $plot->owner, $helpers, $denied, $plot->biome, $plot->pvp, $plot->price); - $result = $stmt->execute(); - if($result === false) { - $this->plugin->getLogger()->error($stmt->error); - return false; - } - $this->cachePlot($plot); - return true; - } - - /** - * @throws \Exception - */ - public function deletePlot(Plot $plot) : bool { - $this->reconnect(); - $settings = MyPlot::getInstance()->getLevelSettings($plot->levelName); - if($plot->isMerged()) { - $stmt = $this->sqlDisposeMergedPlot; - $restrictPVP = !$settings->restrictPVP; - $stmt->bind_param('idsii', $restrictPVP, $settings->claimPrice, $plot->levelName, $plot->X, $plot->Z); - $result = $stmt->execute(); - if ($result === false) { - $this->plugin->getLogger()->error($stmt->error); - return false; - } - $plot = new Plot($plot->levelName, $plot->X, $plot->Z); - $this->cachePlot($this->getMergeOrigin($plot)); - }else{ - $stmt = $this->sqlRemovePlot; - $stmt->bind_param('sii', $plot->levelName, $plot->X, $plot->Z); - $result = $stmt->execute(); - if($result === false){ - $this->plugin->getLogger()->error($stmt->error); - return false; - } - $plot = new Plot($plot->levelName, $plot->X, $plot->Z); - $this->cachePlot($plot); - } - return true; - } - - /** - * @throws \Exception - */ - public function getPlot(string $levelName, int $X, int $Z) : Plot { - $this->reconnect(); - if(($plot = $this->getPlotFromCache($levelName, $X, $Z)) != null) { - return $plot; - } - $stmt = $this->sqlGetPlot; - $stmt->bind_param('sii', $levelName, $X, $Z); - $result = $stmt->execute(); - if($result === false) { - $this->plugin->getLogger()->error($stmt->error); - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - $result = $stmt->get_result(); - if($result !== false and ($val = $result->fetch_array(MYSQLI_ASSOC)) !== null) { - if($val["helpers"] === '') { - $helpers = []; - }else{ - $helpers = explode(",", (string) $val["helpers"]); - } - if($val["denied"] === '') { - $denied = []; - }else{ - $denied = explode(",", (string) $val["denied"]); - } - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - $plot = new Plot($levelName, $X, $Z, (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - }else{ - $plot = new Plot($levelName, $X, $Z); - } - $this->cachePlot($plot); - return $plot; - } - - /** - * @param string $owner - * @param string $levelName - * - * @return Plot[] - * @throws \Exception - */ - public function getPlotsByOwner(string $owner, string $levelName = "") : array { - $this->reconnect(); - if($levelName === '') { - $stmt = $this->sqlGetPlotsByOwner; - $stmt->bind_param('s', $owner); - }else{ - $stmt = $this->sqlGetPlotsByOwnerAndLevel; - $stmt->bind_param('ss', $owner, $levelName); - } - $plots = []; - $result = $stmt->execute(); - if($result === false) { - $this->plugin->getLogger()->error($stmt->error); - return $plots; - } - $result = $stmt->get_result(); - while($result !== false and ($val = $result->fetch_array()) !== null) { - $helpers = explode(",", (string) $val["helpers"]); - $denied = explode(",", (string) $val["denied"]); - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - $plots[] = new Plot((string) $val["level"], (int) $val["X"], (int) $val["Z"], (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - } - // Remove unloaded plots - $plots = array_filter($plots, function(Plot $plot) : bool { - return $this->plugin->isLevelLoaded($plot->levelName); - }); - // Sort plots by level - usort($plots, function(Plot $plot1, Plot $plot2) : int { - return strcmp($plot1->levelName, $plot2->levelName); - }); - return $plots; - } - - /** - * @throws \Exception - */ - public function getNextFreePlot(string $levelName, int $limitXZ = 0) : ?Plot { - $this->reconnect(); - $i = 0; - for(; $limitXZ <= 0 or $i < $limitXZ; $i++) { - $stmt = $this->sqlGetExistingXZ; - $stmt->bind_param('siiii', $levelName, $i, $i, $i, $i); - $result = $stmt->execute(); - if($result === false) { - $this->plugin->getLogger()->error($stmt->error); - continue; - } - $result = $stmt->get_result(); - $plots = []; - while($result !== false and ($val = $result->fetch_array(MYSQLI_NUM)) !== null) { - $plots[$val[0]][$val[1]] = true; - } - if(count($plots) === max(1, 8 * $i)) { - continue; - } - if(($ret = self::findEmptyPlotSquared(0, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - for($a = 1; $a < $i; $a++) { - if(($ret = self::findEmptyPlotSquared($a, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - } - if(($ret = self::findEmptyPlotSquared($i, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - } - return null; - } - - public function mergePlots(Plot $base, Plot ...$plots) : bool { - $stmt = $this->sqlMergePlot; - $ret = true; - foreach($plots as $plot) { - $stmt->bind_param('siiii', $base->levelName, $base->X, $base->Z, $plot->X, $plot->Z); - $result = $stmt->execute(); - if($result === false) { - $this->plugin->getLogger()->error($stmt->error); - $ret = false; - } - } - return $ret; - } - - public function getMergedPlots(Plot $plot, bool $adjacent = false) : array { - $origin = $this->getMergeOrigin($plot); - $stmt = $this->sqlGetMergedPlots; - $stmt->bind_param('sii', $origin->levelName, $origin->X, $origin->Z); - $result = $stmt->execute(); - $plots = []; - $plots[] = $origin; - if(!$result) { - $this->plugin->getLogger()->error($stmt->error); - return $plots; - } - $result = $stmt->get_result(); - while($result !== false and ($val = $result->fetch_array()) !== null) { - $helpers = explode(",", (string) $val["helpers"]); - $denied = explode(",", (string) $val["denied"]); - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - $plots[] = new Plot((string) $val["level"], (int) $val["X"], (int) $val["Z"], (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - } - if($adjacent) - $plots = array_filter($plots, function(Plot $val) use ($plot) : bool { - for($i = Facing::NORTH; $i <= Facing::EAST; ++$i) { - if($plot->getSide($i)->isSame($val)) - return true; - } - return false; - }); - return $plots; - } - - public function getMergeOrigin(Plot $plot) : Plot { - $stmt = $this->sqlGetMergeOrigin; - $stmt->bind_param('sii', $plot->levelName, $plot->X, $plot->Z); - $result = $stmt->execute(); - if(!$result) { - $this->plugin->getLogger()->error($stmt->error); - return $plot; - } - $result = $stmt->get_result(); - if($result !== false and ($val = $result->fetch_array()) !== null) { - $helpers = explode(",", (string) $val["helpers"]); - $denied = explode(",", (string) $val["denied"]); - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - return new Plot((string) $val["level"], (int) $val["X"], (int) $val["Z"], (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - } - return $plot; - } - - public function close() : void { - if($this->db->close()) - $this->plugin->getLogger()->debug("MySQL database closed!"); - } - - /** - * @throws \Exception - */ - private function reconnect() : void{ - if(!$this->db->ping()) { - $this->plugin->getLogger()->error("The MySQL server can not be reached! Trying to reconnect!"); - $this->close(); - $this->db->connect($this->settings['Host'], $this->settings['Username'], $this->settings['Password'], $this->settings['DatabaseName'], $this->settings['Port']); - $this->prepare(); - if($this->db->ping()) { - $this->plugin->getLogger()->notice("The MySQL connection has been re-established!"); - }else{ - $this->plugin->getLogger()->critical("The MySQL connection could not be re-established!"); - $this->plugin->getLogger()->critical("Closing level to prevent griefing!"); - foreach($this->plugin->getPlotLevels() as $levelName => $settings) { - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($levelName); - if($level !== null) { - $level->save(); // don't force in case owner doesn't want it saved - Server::getInstance()->getWorldManager()->unloadWorld($level, true); // force unload to prevent possible griefing - } - } - if($this->db->connect_error !== null and $this->db->connect_error !== '') - $this->plugin->getLogger()->critical("Failed to connect to the MySQL database: " . $this->db->connect_error); - if($this->plugin->getConfig()->getNested("MySQLSettings.ShutdownOnFailure", false) === true) { - $this->plugin->getServer()->shutdown(); - } - } - } - } - - private function prepare() : void { - $stmt = $this->db->prepare("SELECT name, owner, helpers, denied, biome, pvp, price FROM plotsV2 WHERE level = ? AND X = ? AND Z = ?;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetPlot = $stmt; - $stmt = $this->db->prepare("INSERT INTO plotsV2 (`level`, `X`, `Z`, `name`, `owner`, `helpers`, `denied`, `biome`, `pvp`, `price`) VALUES(?,?,?,?,?,?,?,?,?,?) ON DUPLICATE KEY UPDATE name = VALUES(name), owner = VALUES(owner), helpers = VALUES(helpers), denied = VALUES(denied), biome = VALUES(biome), pvp = VALUES(pvp), price = VALUES(price);"); - if($stmt === false) - throw new \Exception(); - $this->sqlSavePlot = $stmt; - $stmt = $this->db->prepare("DELETE FROM plotsV2 WHERE level = ? AND X = ? AND Z = ?;"); - if($stmt === false) - throw new \Exception(); - $this->sqlRemovePlot = $stmt; - $stmt = $this->db->prepare("SELECT * FROM plotsV2 WHERE owner = ?;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetPlotsByOwner = $stmt; - $stmt = $this->db->prepare("SELECT * FROM plotsV2 WHERE owner = ? AND level = ?;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetPlotsByOwnerAndLevel = $stmt; - $stmt = $this->db->prepare("SELECT X, Z FROM plotsV2 WHERE (level = ? AND ((abs(X) = ? AND abs(Z) <= ?) OR (abs(Z) = ? AND abs(X) <= ?)));"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetExistingXZ = $stmt; - - $stmt = $this->db->prepare("INSERT IGNORE INTO mergedPlotsV2 (`level`, `originX`, `originZ`, `mergedX`, `mergedZ`) VALUES (?,?,?,?,?);"); - if($stmt === false) - throw new \Exception(); - $this->sqlMergePlot = $stmt; - $stmt = $this->db->prepare("SELECT plotsV2.level, X, Z, name, owner, helpers, denied, biome, pvp, price FROM plotsV2 LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level WHERE mergedPlotsV2.level = ? AND mergedX = ? AND mergedZ = ?;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetMergeOrigin = $stmt; - $stmt = $this->db->prepare("SELECT plotsV2.level, X, Z, name, owner, helpers, denied, biome, pvp, price FROM plotsV2 LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedPlotsV2.mergedX = plotsV2.X AND mergedPlotsV2.mergedZ = plotsV2.Z WHERE mergedPlotsV2.level = ? AND originX = ? AND originZ = ?;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetMergedPlots = $stmt; - $stmt = $this->db->prepare("UPDATE plotsV2 SET name = '', owner = '', helpers = '', denied = '', biome = :biome, pvp = :pvp, price = :price WHERE level = :level AND X = :X AND Z = :Z;"); - if($stmt === false) - throw new \Exception(); - $this->sqlDisposeMergedPlot = $stmt; - } -} diff --git a/src/MyPlot/provider/SQLiteDataProvider.php b/src/MyPlot/provider/SQLiteDataProvider.php deleted file mode 100644 index 9abdf20f..00000000 --- a/src/MyPlot/provider/SQLiteDataProvider.php +++ /dev/null @@ -1,315 +0,0 @@ -db = new \SQLite3($this->plugin->getDataFolder() . "plots.db"); - $this->db->exec("CREATE TABLE IF NOT EXISTS plotsV2 - (level TEXT, X INTEGER, Z INTEGER, name TEXT, - owner TEXT, helpers TEXT, denied TEXT, biome TEXT, pvp INTEGER, price FLOAT, PRIMARY KEY (level, X, Z));"); - if($this->db->querySingle("SELECT count(name) FROM sqlite_Master WHERE type='table' AND name='plots';") > 0) - $this->db->exec("INSERT OR IGNORE INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) SELECT level, X, Z, name, owner, helpers, denied, biome, pvp, price FROM plots;"); - $this->db->exec("CREATE TABLE IF NOT EXISTS mergedPlotsV2 (level TEXT, originX INTEGER, originZ INTEGER, mergedX INTEGER, mergedZ INTEGER, PRIMARY KEY(level, originX, originZ, mergedX, mergedZ));"); - if($this->db->querySingle("SELECT count(name) FROM sqlite_Master WHERE type='table' AND name='mergedPlots';") > 0) - $this->db->exec("INSERT OR IGNORE INTO mergedPlotsV2 (level, originX, originZ, mergedX, mergedZ) SELECT r1.level, r1.X, r1.Z, r2.X, r2.Z FROM plots r1, mergedPlots JOIN plots r2 ON r1.id = mergedPlots.originId AND r2.id = mergedPlots.mergedId;"); - $this->prepare(); - $this->plugin->getLogger()->debug("SQLite data provider registered"); - } - - public function savePlot(Plot $plot) : bool { - $helpers = implode(",", $plot->helpers); - $denied = implode(",", $plot->denied); - $stmt = $this->sqlSavePlot; - $stmt->bindValue(":level", $plot->levelName, SQLITE3_TEXT); - $stmt->bindValue(":X", $plot->X, SQLITE3_INTEGER); - $stmt->bindValue(":Z", $plot->Z, SQLITE3_INTEGER); - $stmt->bindValue(":name", $plot->name, SQLITE3_TEXT); - $stmt->bindValue(":owner", $plot->owner, SQLITE3_TEXT); - $stmt->bindValue(":helpers", $helpers, SQLITE3_TEXT); - $stmt->bindValue(":denied", $denied, SQLITE3_TEXT); - $stmt->bindValue(":biome", $plot->biome, SQLITE3_TEXT); - $stmt->bindValue(":pvp", $plot->pvp, SQLITE3_INTEGER); - $stmt->bindValue(":price", $plot->price, SQLITE3_FLOAT); - $stmt->reset(); - $result = $stmt->execute(); - if(!$result instanceof \SQLite3Result) { - return false; - } - $this->cachePlot($plot); - return true; - } - - public function deletePlot(Plot $plot) : bool { - if($plot->isMerged()){ - $plot = $this->getMergeOrigin($plot); - $settings = MyPlot::getInstance()->getLevelSettings($plot->levelName); - $stmt = $this->sqlDisposeMergedPlot; - $stmt->bindValue(":pvp", !$settings->restrictPVP, SQLITE3_INTEGER); - $stmt->bindValue(":price", $settings->claimPrice, SQLITE3_FLOAT); - }else { - $stmt = $this->sqlRemovePlot; - } - $stmt->bindValue(":level", $plot->levelName, SQLITE3_TEXT); - $stmt->bindValue(":X", $plot->X, SQLITE3_INTEGER); - $stmt->bindValue(":Z", $plot->Z, SQLITE3_INTEGER); - $stmt->reset(); - $result = $stmt->execute(); - if(!$result instanceof \SQLite3Result) { - return false; - } - $this->cachePlot(new Plot($plot->levelName, $plot->X, $plot->Z)); - return true; - } - - public function getPlot(string $levelName, int $X, int $Z) : Plot { - if(($plot = $this->getPlotFromCache($levelName, $X, $Z)) !== null) { - return $plot; - } - $this->sqlGetPlot->bindValue(":level", $levelName, SQLITE3_TEXT); - $this->sqlGetPlot->bindValue(":X", $X, SQLITE3_INTEGER); - $this->sqlGetPlot->bindValue(":Z", $Z, SQLITE3_INTEGER); - $this->sqlGetPlot->reset(); - $result = $this->sqlGetPlot->execute(); - if($result !== false and ($val = $result->fetchArray(SQLITE3_ASSOC)) !== false) { - if($val["helpers"] === null or $val["helpers"] === "") { - $helpers = []; - }else{ - $helpers = explode(",", (string) $val["helpers"]); - } - if($val["denied"] === null or $val["denied"] === "") { - $denied = []; - }else{ - $denied = explode(",", (string) $val["denied"]); - } - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - $plot = new Plot($levelName, $X, $Z, (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - }else{ - $plot = new Plot($levelName, $X, $Z); - } - $this->cachePlot($plot); - return $plot; - } - - /** - * @param string $owner - * @param string $levelName - * - * @return Plot[] - */ - public function getPlotsByOwner(string $owner, string $levelName = "") : array { - if($levelName === "") { - $stmt = $this->sqlGetPlotsByOwner; - }else{ - $stmt = $this->sqlGetPlotsByOwnerAndLevel; - $stmt->bindValue(":level", $levelName, SQLITE3_TEXT); - } - $stmt->bindValue(":owner", $owner, SQLITE3_TEXT); - $plots = []; - $stmt->reset(); - $result = $stmt->execute(); - while($result !== false and ($val = $result->fetchArray(SQLITE3_ASSOC)) !== false) { - $helpers = explode(",", (string) $val["helpers"]); - $denied = explode(",", (string) $val["denied"]); - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - $plots[] = new Plot((string) $val["level"], (int) $val["X"], (int) $val["Z"], (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - } - // Remove unloaded plots - $plots = array_filter($plots, function(Plot $plot) : bool { - return $this->plugin->isLevelLoaded($plot->levelName); - }); - // Sort plots by level - usort($plots, function(Plot $plot1, Plot $plot2) : int { - return strcmp($plot1->levelName, $plot2->levelName); - }); - return $plots; - } - - public function getNextFreePlot(string $levelName, int $limitXZ = 0) : ?Plot { - $this->sqlGetExistingXZ->bindValue(":level", $levelName, SQLITE3_TEXT); - $i = 0; - $this->sqlGetExistingXZ->bindParam(":number", $i, SQLITE3_INTEGER); - for(; $limitXZ <= 0 or $i < $limitXZ; $i++) { - $this->sqlGetExistingXZ->reset(); - $result = $this->sqlGetExistingXZ->execute(); - $plots = []; - while($result !== false and ($val = $result->fetchArray(SQLITE3_NUM)) !== false) { - $plots[$val[0]][$val[1]] = true; - } - if(count($plots) === max(1, 8 * $i)) { - continue; - } - if(($ret = self::findEmptyPlotSquared(0, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - for($a = 1; $a < $i; $a++) { - if(($ret = self::findEmptyPlotSquared($a, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - } - if(($ret = self::findEmptyPlotSquared($i, $i, $plots)) !== null) { - [$X, $Z] = $ret; - $plot = new Plot($levelName, $X, $Z); - $this->cachePlot($plot); - return $plot; - } - } - return null; - } - - public function close() : void { - $this->db->close(); - $this->plugin->getLogger()->debug("SQLite database closed!"); - } - - public function mergePlots(Plot $base, Plot ...$plots) : bool { - $stmt = $this->sqlMergePlot; - $ret = true; - foreach($plots as $plot) { - $stmt->bindValue(":level", $base->levelName); - $stmt->bindValue(":originX", $base->X); - $stmt->bindValue(":originZ", $base->Z); - $stmt->bindValue(":mergedX", $plot->X); - $stmt->bindValue(":mergedZ", $plot->Z); - $stmt->reset(); - $result = $stmt->execute(); - if(!$result instanceof \SQLite3Result) { - MyPlot::getInstance()->getLogger()->debug("Failed to merge plot $plot into $base"); - $ret = false; - } - } - return $ret; - } - - /** - * @param Plot $plot - * @param bool $adjacent - * - * @return Plot[] - */ - public function getMergedPlots(Plot $plot, bool $adjacent = false) : array { - $origin = $this->getMergeOrigin($plot); - $stmt = $this->sqlGetMergedPlots; - $stmt->bindValue(":level", $origin->levelName); - $stmt->bindValue(":originX", $origin->X); - $stmt->bindValue(":originZ", $origin->Z); - $stmt->reset(); - $result = $stmt->execute(); - $plots = [$origin]; - while($result !== false and ($val = $result->fetchArray(SQLITE3_ASSOC)) !== false) { - $helpers = explode(",", (string) $val["helpers"]); - $denied = explode(",", (string) $val["denied"]); - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - $plots[] = new Plot((string) $val["level"], (int) $val["X"], (int) $val["Z"], (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - } - if($adjacent) - $plots = array_filter($plots, function(Plot $val) use ($plot) : bool { - for($i = Facing::NORTH; $i <= Facing::EAST; ++$i) { - if($plot->getSide($i)->isSame($val)) - return true; - } - return false; - }); - return $plots; - } - - public function getMergeOrigin(Plot $plot) : Plot { - $stmt = $this->sqlGetMergeOrigin; - $stmt->bindValue(":level", $plot->levelName); - $stmt->bindValue(":mergedX", $plot->X); - $stmt->bindValue(":mergedZ", $plot->Z); - $stmt->reset(); - $result = $stmt->execute(); - if(!$result instanceof \SQLite3Result) { - return $plot; - } - if(($val = $result->fetchArray(SQLITE3_ASSOC)) !== false) { - $helpers = explode(",", (string) $val["helpers"]); - $denied = explode(",", (string) $val["denied"]); - $pvp = is_numeric($val["pvp"]) ? (bool)$val["pvp"] : null; - return new Plot((string) $val["level"], (int) $val["X"], (int) $val["Z"], (string) $val["name"], (string) $val["owner"], $helpers, $denied, (string) $val["biome"], $pvp, (float) $val["price"]); - } - return $plot; - } - - private function prepare() : void { - $stmt = $this->db->prepare("SELECT name, owner, helpers, denied, biome, pvp, price FROM plotsV2 WHERE level = :level AND X = :X AND Z = :Z;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetPlot = $stmt; - $stmt = $this->db->prepare("INSERT OR REPLACE INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) VALUES (:level, :X, :Z, :name, :owner, :helpers, :denied, :biome, :pvp, :price);"); - if($stmt === false) - throw new \Exception(); - $this->sqlSavePlot = $stmt; - $stmt = $this->db->prepare("DELETE FROM plotsV2 WHERE level = :level AND X = :X AND Z = :Z;"); - if($stmt === false) - throw new \Exception(); - $this->sqlRemovePlot = $stmt; - $stmt = $this->db->prepare("UPDATE plotsV2 SET name = '', owner = '', helpers = '', denied = '', biome = :biome, pvp = :pvp, price = :price WHERE level = :level AND X = :X AND Z = :Z;"); - if($stmt === false) - throw new \Exception(); - $this->sqlDisposeMergedPlot = $stmt; - $stmt = $this->db->prepare("SELECT * FROM plotsV2 WHERE owner = :owner;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetPlotsByOwner = $stmt; - $stmt = $this->db->prepare("SELECT * FROM plotsV2 WHERE owner = :owner AND level = :level;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetPlotsByOwnerAndLevel = $stmt; - $stmt = $this->db->prepare("SELECT X, Z FROM plotsV2 WHERE ( - level = :level - AND ( - (abs(X) = :number AND abs(Z) <= :number) OR - (abs(Z) = :number AND abs(X) <= :number) - ) - );"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetExistingXZ = $stmt; - $stmt = $this->db->prepare("INSERT OR REPLACE INTO mergedPlotsV2 (level, originX, originZ, mergedX, mergedZ) VALUES (:level, :originX, :originZ, :mergedX, :mergedZ);"); - if($stmt === false) - throw new \Exception(); - $this->sqlMergePlot = $stmt; - $stmt = $this->db->prepare("SELECT plotsV2.level, X, Z, name, owner, helpers, denied, biome, pvp, price FROM plotsV2 LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level WHERE mergedPlotsV2.level = :level AND mergedX = :mergedX AND mergedZ = :mergedZ;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetMergeOrigin = $stmt; - $stmt = $this->db->prepare("SELECT plotsV2.level, X, Z, name, owner, helpers, denied, biome, pvp, price FROM plotsV2 LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedPlotsV2.mergedX = plotsV2.X AND mergedPlotsV2.mergedZ = plotsV2.Z WHERE mergedPlotsV2.level = :level AND originX = :originX AND originZ = :originZ;"); - if($stmt === false) - throw new \Exception(); - $this->sqlGetMergedPlots = $stmt; - } -} \ No newline at end of file From 65f87812050a8d0429c1aeb9bd23b401aae1cc63 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:17:02 -0500 Subject: [PATCH 02/47] Converted save function to async/await format --- src/MyPlot/MyPlot.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 2f4ec60c..535dd7ee 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -194,10 +194,17 @@ public function generateLevel(string $levelName, string $generator = MyPlotGener * * @param Plot $plot * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function savePlot(Plot $plot) : bool { - return $this->dataProvider->savePlot($plot); + public function savePlot(Plot $plot) : Promise{ + $resolver = new PromiseResolver(); + Await::g2c( + $this->dataProvider->savePlot($plot), + fn() => $resolver->resolve($plot), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 88c6948c632b74bb8ea6a9b4ba18bf8a95eb28a7 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:19:00 -0500 Subject: [PATCH 03/47] Converted getPlotsOfPlayer function to async/await format --- src/MyPlot/MyPlot.php | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 535dd7ee..d0b0dd9c 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -212,13 +212,20 @@ public function savePlot(Plot $plot) : Promise{ * * @api * - * @param string $username - * @param string $levelName + * @param string $username + * @param string|null $levelName * - * @return Plot[] + * @return Promise + * @phpstan-return Promise> */ - public function getPlotsOfPlayer(string $username, string $levelName) : array { - return $this->dataProvider->getPlotsByOwner($username, $levelName); + public function getPlotsOfPlayer(string $username, ?string $levelName = null) : Promise{ + $resolver = new PromiseResolver(); + Await::g2c( + $this->dataProvider->getPlotsByOwner($username, $levelName), + fn(array $plots) => $resolver->resolve($plots), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 49d326d3d3f443bba84d5fa8bfe9bc5cd273e2d4 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:19:26 -0500 Subject: [PATCH 04/47] Converted getNextFreePlot function to async/await format --- src/MyPlot/MyPlot.php | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index d0b0dd9c..960716bf 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -234,12 +234,19 @@ public function getPlotsOfPlayer(string $username, ?string $levelName = null) : * @api * * @param string $levelName - * @param int $limitXZ + * @param int $limitXZ * - * @return Plot|null + * @return Promise + * @phpstan-return Promise */ - public function getNextFreePlot(string $levelName, int $limitXZ = 0) : ?Plot { - return $this->dataProvider->getNextFreePlot($levelName, $limitXZ); + public function getNextFreePlot(string $levelName, int $limitXZ = 0) : Promise{ + $resolver = new PromiseResolver(); + Await::g2c( + $this->dataProvider->getNextFreePlot($levelName, $limitXZ), + fn(?Plot $plot) => $resolver->resolve($plot), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From a03fad9a3cd32ee2679bb63b0384f23405bd8d7e Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:20:15 -0500 Subject: [PATCH 05/47] Converted getPlotByPosition function to async/await format --- src/MyPlot/MyPlot.php | 64 +++++++++++++++++++++++++------------------ 1 file changed, 37 insertions(+), 27 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 960716bf..8f306b38 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -256,41 +256,51 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : Promise{ * * @param Position $position * - * @return Plot|null + * @return Promise + * @phpstan-return Promise */ - public function getPlotByPosition(Position $position) : ?Plot { - $x = $position->x; - $z = $position->z; - $levelName = $position->getWorld()->getFolderName(); - if(!$this->isLevelLoaded($levelName)) - return null; - $plotLevel = $this->getLevelSettings($levelName); + public function getPlotByPosition(Position $position) : Promise{ + $resolver = new PromiseResolver(); + Await::f2c( + function() use ($position){ + $x = $position->x; + $z = $position->z; + $levelName = $position->getWorld()->getFolderName(); + if(!$this->isLevelLoaded($levelName)) + return null; + $plotLevel = $this->getLevelSettings($levelName); - $plot = $this->getPlotFast($x, $z, $plotLevel); - if($plot instanceof Plot) - return $this->dataProvider->getMergeOrigin($plot); + $plot = $this->getPlotFast($x, $z, $plotLevel); + if($plot instanceof Plot) + return yield $this->dataProvider->getMergeOrigin($plot); - if(!($basePlot = $this->dataProvider->getPlot($levelName, $x, $z))->isMerged()) - return null; + $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); + if(!$basePlot->isMerged()) + return null; - // no plot found at current location yet, so search cardinal directions - $plotN = $basePlot->getSide(Facing::NORTH); - if($plotN->isSame($basePlot)) - return $this->dataProvider->getMergeOrigin($plotN); + // no plot found at current location yet, so search cardinal directions + $plotN = $basePlot->getSide(Facing::NORTH); + if($plotN->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotN); - $plotS = $basePlot->getSide(Facing::SOUTH); - if($plotS->isSame($basePlot)) - return $this->dataProvider->getMergeOrigin($plotS); + $plotS = $basePlot->getSide(Facing::SOUTH); + if($plotS->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotS); - $plotE = $basePlot->getSide(Facing::EAST); - if($plotE->isSame($basePlot)) - return $this->dataProvider->getMergeOrigin($plotE); + $plotE = $basePlot->getSide(Facing::EAST); + if($plotE->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotE); - $plotW = $basePlot->getSide(Facing::WEST); - if($plotW->isSame($basePlot)) - return $this->dataProvider->getMergeOrigin($plotW); + $plotW = $basePlot->getSide(Facing::WEST); + if($plotW->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotW); - return null; + return null; + }, + fn(?Plot $plot) => $resolver->resolve($plot), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 21801d3b0a5bcc97b724401093b94d0d46ec0de0 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:20:51 -0500 Subject: [PATCH 06/47] Converted getPlotPosition function to async/await format --- src/MyPlot/MyPlot.php | 41 +++++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 8f306b38..fe142475 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -342,23 +342,32 @@ private function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) * @param Plot $plot * @param bool $mergeOrigin * - * @return Position + * @return Promise + * @phpstan-return Promise */ - public function getPlotPosition(Plot $plot, bool $mergeOrigin = true) : Position { - $plotLevel = $this->getLevelSettings($plot->levelName); - $origin = $this->dataProvider->getMergeOrigin($plot); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if ($mergeOrigin) { - $x = $totalSize * $origin->X; - $z = $totalSize * $origin->Z; - } else { - $x = $totalSize * $plot->X; - $z = $totalSize * $plot->Z; - } - $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - return new Position($x, $plotLevel->groundHeight, $z, $level); + public function getPlotPosition(Plot $plot, bool $mergeOrigin = true) : Promise{ + $resolver = new PromiseResolver(); + Await::f2c( + function() use ($plot, $mergeOrigin){ + $plotLevel = $this->getLevelSettings($plot->levelName); + $origin = yield $this->dataProvider->getMergeOrigin($plot); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($mergeOrigin){ + $x = $totalSize * $origin->X; + $z = $totalSize * $origin->Z; + }else{ + $x = $totalSize * $plot->X; + $z = $totalSize * $plot->Z; + } + $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); + return new Position($x, $plotLevel->groundHeight, $z, $level); + }, + fn(Position $position) => $resolver->resolve($position), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 0042529ad5793886f3ce1319d1ac5aaf9532774e Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:22:27 -0500 Subject: [PATCH 07/47] Converted isPositionBorderingPlot function to async/await format --- src/MyPlot/MyPlot.php | 129 ++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 60 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index fe142475..308a09a5 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -377,69 +377,78 @@ function() use ($plot, $mergeOrigin){ * * @param Position $position * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function isPositionBorderingPlot(Position $position) : bool { - if(!$position->isValid()) - return false; - for($i = Facing::NORTH; $i <= Facing::EAST; ++$i) { - $pos = $position->getSide($i); - $x = $pos->x; - $z = $pos->z; - $levelName = $pos->getWorld()->getFolderName(); - - if(!$this->isLevelLoaded($levelName)) - return false; - - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0) { - $difX = $x % $totalSize; - }else{ - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0) { - $difZ = $z % $totalSize; - }else{ - $difZ = abs(($z - $plotSize + 1) % $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)) { - continue; - } - return true; - } - for($i = Facing::NORTH; $i <= Facing::EAST; ++$i) { - for($n = Facing::NORTH; $n <= Facing::EAST; ++$n) { - if($i === $n or Facing::opposite($i) === $n) - continue; - $pos = $position->getSide($i)->getSide($n); - $x = $pos->x; - $z = $pos->z; - $levelName = $pos->getWorld()->getFolderName(); - - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0) { - $difX = $x % $totalSize; - }else{ - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0) { - $difZ = $z % $totalSize; - }else{ - $difZ = abs(($z - $plotSize + 1) % $totalSize); + public function isPositionBorderingPlot(Position $position) : Promise{ + $resolver = new PromiseResolver(); + Await::f2c( + function() use ($position){ + if(!$position->isValid()) + return false; + foreach(Facing::HORIZONTAL as $i){ + $pos = $position->getSide($i); + $x = $pos->x; + $z = $pos->z; + $levelName = $pos->getWorld()->getFolderName(); + + if(!$this->isLevelLoaded($levelName)) + return false; + + $plotLevel = $this->getLevelSettings($levelName); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($x >= 0){ + $difX = $x % $totalSize; + }else{ + $difX = abs(($x - $plotSize + 1) % $totalSize); + } + if($z >= 0){ + $difZ = $z % $totalSize; + }else{ + $difZ = abs(($z - $plotSize + 1) % $totalSize); + } + if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ + continue; + } + return true; } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)) { - continue; + foreach(Facing::HORIZONTAL as $i){ + foreach(Facing::HORIZONTAL as $n){ + if($i === $n or Facing::opposite($i) === $n) + continue; + $pos = $position->getSide($i)->getSide($n); + $x = $pos->x; + $z = $pos->z; + $levelName = $pos->getWorld()->getFolderName(); + + $plotLevel = $this->getLevelSettings($levelName); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($x >= 0){ + $difX = $x % $totalSize; + }else{ + $difX = abs(($x - $plotSize + 1) % $totalSize); + } + if($z >= 0){ + $difZ = $z % $totalSize; + }else{ + $difZ = abs(($z - $plotSize + 1) % $totalSize); + } + if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ + continue; + } + return true; + } } - return true; - } - } - return false; + return false; + }, + fn(bool $isBordering) => $resolver->resolve($isBordering), + fn() => $resolver->reject() + ); + return $resolver->getPromise(); } /** From b13d409cea7ff66f31219bd21cddd7acdcb1d0c9 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:24:09 -0500 Subject: [PATCH 08/47] Converted getPlotBorderingPosition function to async/await format --- src/MyPlot/MyPlot.php | 94 ++++++++++++++++++++++++++----------------- 1 file changed, 58 insertions(+), 36 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 308a09a5..b1e55fb1 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -458,47 +458,69 @@ function() use ($position){ * * @param Position $position * - * @return Plot|null + * @return Promise + * @phpstan-return Promise */ - public function getPlotBorderingPosition(Position $position) : ?Plot { - if(!$position->isValid()) - return null; - for($i = Facing::NORTH; $i <= Facing::EAST; ++$i) { - $pos = $position->getSide($i); - $x = $pos->x; - $z = $pos->z; - $levelName = $pos->getWorld()->getFolderName(); - - if(!$this->isLevelLoaded($levelName)) + public function getPlotBorderingPosition(Position $position) : Promise{ + $resolver = new PromiseResolver(); + Await::f2c(function() use ($position){ + if(!$position->isValid()) return null; + foreach(Facing::HORIZONTAL as $i){ + $pos = $position->getSide($i); + $x = $pos->x; + $z = $pos->z; + $levelName = $pos->getWorld()->getFolderName(); - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0) { - $X = (int) floor($x / $totalSize); - $difX = $x % $totalSize; - }else{ - $X = (int) ceil(($x - $plotSize + 1) / $totalSize); - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0) { - $Z = (int) floor($z / $totalSize); - $difZ = $z % $totalSize; - }else{ - $Z = (int) ceil(($z - $plotSize + 1) / $totalSize); - $difZ = abs(($z - $plotSize + 1) % $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)) { - if($this->getPlotByPosition($pos) instanceof Plot) { - return $this->getPlotByPosition($pos); + if(!$this->isLevelLoaded($levelName)) + return null; + + $plotLevel = $this->getLevelSettings($levelName); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($x >= 0){ + $X = (int) floor($x / $totalSize); + $difX = $x % $totalSize; + }else{ + $X = (int) ceil(($x - $plotSize + 1) / $totalSize); + $difX = abs(($x - $plotSize + 1) % $totalSize); + } + if($z >= 0){ + $Z = (int) floor($z / $totalSize); + $difZ = $z % $totalSize; + }else{ + $Z = (int) ceil(($z - $plotSize + 1) / $totalSize); + $difZ = abs(($z - $plotSize + 1) % $totalSize); } - continue; + if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ + $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); + if(!$basePlot->isMerged()) + return null; + + // no plot found at current location yet, so search cardinal directions + $plotN = $basePlot->getSide(Facing::NORTH); + if($plotN->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotN); + + $plotS = $basePlot->getSide(Facing::SOUTH); + if($plotS->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotS); + + $plotE = $basePlot->getSide(Facing::EAST); + if($plotE->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotE); + + $plotW = $basePlot->getSide(Facing::WEST); + if($plotW->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotW); + continue; + } + return yield $this->dataProvider->getPlot($levelName, $X, $Z); } - return $this->dataProvider->getPlot($levelName, $X, $Z); - } - return null; + return null; + }); + return $resolver->getPromise(); } /** From 73d357d69874c7791bd8f23ff6b806adcf1464ff Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:24:41 -0500 Subject: [PATCH 09/47] Converted getPlotBB function to async/await format --- src/MyPlot/MyPlot.php | 67 +++++++++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 24 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index b1e55fb1..6951b368 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -530,33 +530,52 @@ public function getPlotBorderingPosition(Position $position) : Promise{ * * @param Plot $plot * - * @return AxisAlignedBB + * @return Promise + * @phpstan-return Promise */ - public function getPlotBB(Plot $plot) : AxisAlignedBB { - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize-1; - $pos = $this->getPlotPosition($plot, false); - $xMax = (int)($pos->x + $plotSize); - $zMax = (int)($pos->z + $plotSize); - foreach ($this->dataProvider->getMergedPlots($plot) as $mergedPlot){ - $xplot = $this->getPlotPosition($mergedPlot, false)->x; - $zplot = $this->getPlotPosition($mergedPlot, false)->z; - $xMaxPlot = (int)($xplot + $plotSize); - $zMaxPlot = (int)($zplot + $plotSize); - if($pos->x > $xplot) $pos->x = $xplot; - if($pos->z > $zplot) $pos->z = $zplot; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } + public function getPlotBB(Plot $plot) : Promise{ + $resolver = new PromiseResolver(); + Await::f2c( + function() use ($plot){ + $getPlotPosition = function($plot){ + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + $x = $totalSize * $plot->X; + $z = $totalSize * $plot->Z; + $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); + return new Position($x, $plotLevel->groundHeight, $z, $level); + }; + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize - 1; + $pos = $getPlotPosition($plot); + $xMax = (int) ($pos->x + $plotSize); + $zMax = (int) ($pos->z + $plotSize); + foreach((yield $this->dataProvider->getMergedPlots($plot)) as $mergedPlot){ + $xplot = $getPlotPosition($mergedPlot)->x; + $zplot = $getPlotPosition($mergedPlot)->z; + $xMaxPlot = (int) ($xplot + $plotSize); + $zMaxPlot = (int) ($zplot + $plotSize); + if($pos->x > $xplot) $pos->x = $xplot; + if($pos->z > $zplot) $pos->z = $zplot; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } - return new AxisAlignedBB( - min($pos->x, $xMax), - 0, - min($pos->z, $zMax), - max($pos->x, $xMax), - $pos->getWorld()->getMaxY(), - max($pos->z, $zMax) + return new AxisAlignedBB( + min($pos->x, $xMax), + $pos->getWorld()->getMinY(), + min($pos->z, $zMax), + max($pos->x, $xMax), + $pos->getWorld()->getMaxY(), + max($pos->z, $zMax) + ); + }, + fn(AxisAlignedBB $aabb) => $resolver->resolve($aabb), + fn(\Throwable $e) => $resolver->reject() ); + return $resolver->getPromise(); } /** From 430bca77443ad6ca36376703c9fc8a94842e62d3 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:35:59 -0500 Subject: [PATCH 10/47] Converted renamePlot function to async/await format --- src/MyPlot/MyPlot.php | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 6951b368..78dc98d0 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -768,18 +768,21 @@ public function claimPlot(Plot $plot, string $claimer, string $plotName = "") : * * @api * - * @param Plot $plot + * @param Plot $plot * @param string $newName * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function renamePlot(Plot $plot, string $newName = "") : bool { + public function renamePlot(Plot $plot, string $newName = "") : Promise{ $newPlot = clone $plot; $newPlot->name = $newName; $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); - if($ev->isCancelled()) { - return false; + if($ev->isCancelled()){ + $resolver = new PromiseResolver(); + $resolver->resolve(false); + return $resolver->getPromise(); } return $this->savePlot($ev->getPlot()); } From 48b4a6e502dad9f5ca483a66bc7d838c8b856cd2 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:37:05 -0500 Subject: [PATCH 11/47] Fixed getPlotBorderingPosition missing its promise resolution --- src/MyPlot/MyPlot.php | 108 ++++++++++++++++++++++-------------------- 1 file changed, 56 insertions(+), 52 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 78dc98d0..d5145615 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -463,63 +463,67 @@ function() use ($position){ */ public function getPlotBorderingPosition(Position $position) : Promise{ $resolver = new PromiseResolver(); - Await::f2c(function() use ($position){ - if(!$position->isValid()) - return null; - foreach(Facing::HORIZONTAL as $i){ - $pos = $position->getSide($i); - $x = $pos->x; - $z = $pos->z; - $levelName = $pos->getWorld()->getFolderName(); - - if(!$this->isLevelLoaded($levelName)) + Await::f2c( + function() use ($position){ + if(!$position->isValid()) return null; + foreach(Facing::HORIZONTAL as $i){ + $pos = $position->getSide($i); + $x = $pos->x; + $z = $pos->z; + $levelName = $pos->getWorld()->getFolderName(); - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0){ - $X = (int) floor($x / $totalSize); - $difX = $x % $totalSize; - }else{ - $X = (int) ceil(($x - $plotSize + 1) / $totalSize); - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0){ - $Z = (int) floor($z / $totalSize); - $difZ = $z % $totalSize; - }else{ - $Z = (int) ceil(($z - $plotSize + 1) / $totalSize); - $difZ = abs(($z - $plotSize + 1) % $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ - $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); - if(!$basePlot->isMerged()) + if(!$this->isLevelLoaded($levelName)) return null; - // no plot found at current location yet, so search cardinal directions - $plotN = $basePlot->getSide(Facing::NORTH); - if($plotN->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotN); - - $plotS = $basePlot->getSide(Facing::SOUTH); - if($plotS->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotS); - - $plotE = $basePlot->getSide(Facing::EAST); - if($plotE->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotE); - - $plotW = $basePlot->getSide(Facing::WEST); - if($plotW->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotW); - continue; + $plotLevel = $this->getLevelSettings($levelName); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($x >= 0){ + $X = (int) floor($x / $totalSize); + $difX = $x % $totalSize; + }else{ + $X = (int) ceil(($x - $plotSize + 1) / $totalSize); + $difX = abs(($x - $plotSize + 1) % $totalSize); + } + if($z >= 0){ + $Z = (int) floor($z / $totalSize); + $difZ = $z % $totalSize; + }else{ + $Z = (int) ceil(($z - $plotSize + 1) / $totalSize); + $difZ = abs(($z - $plotSize + 1) % $totalSize); + } + if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ + $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); + if(!$basePlot->isMerged()) + return null; + + // no plot found at current location yet, so search cardinal directions + $plotN = $basePlot->getSide(Facing::NORTH); + if($plotN->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotN); + + $plotS = $basePlot->getSide(Facing::SOUTH); + if($plotS->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotS); + + $plotE = $basePlot->getSide(Facing::EAST); + if($plotE->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotE); + + $plotW = $basePlot->getSide(Facing::WEST); + if($plotW->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotW); + continue; + } + return yield $this->dataProvider->getPlot($levelName, $X, $Z); } - return yield $this->dataProvider->getPlot($levelName, $X, $Z); - } - return null; - }); + return null; + }, + fn(?Plot $plot) => $resolver->resolve($plot), + fn(\Throwable $e) => $resolver->reject() + ); return $resolver->getPromise(); } From 5e5ce0b9a10b26e831254b5fb6e8d021a28dba2b Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Fri, 4 Feb 2022 23:44:52 -0500 Subject: [PATCH 12/47] Converted disposePlot to async/await format --- src/MyPlot/MyPlot.php | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index d5145615..4059949d 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1071,15 +1071,23 @@ public function fillPlot(Plot $plot, Block $plotFillBlock, int $maxBlocksPerTick * * @param Plot $plot * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function disposePlot(Plot $plot) : bool { + public function disposePlot(Plot $plot) : Promise { + $resolver = new PromiseResolver(); $ev = new MyPlotDisposeEvent($plot); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } - return $this->getProvider()->deletePlot($plot); + Await::g2c( + $this->dataProvider->deletePlot($plot), + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 5599012ee3cc9d1202a7692f09df6d6144c4dee8 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 00:01:30 -0500 Subject: [PATCH 13/47] Converted claimPlot to async/await format --- src/MyPlot/MyPlot.php | 43 +++++++++++++++++++++++++++---------------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 4059949d..c856b58e 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -738,33 +738,44 @@ public function teleportPlayerToMerge(Player $player, Plot $plot, bool $center = * * @api * - * @param Plot $plot + * @param Plot $plot * @param string $claimer * @param string $plotName * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function claimPlot(Plot $plot, string $claimer, string $plotName = "") : bool { + public function claimPlot(Plot $plot, string $claimer, string $plotName = "") : Promise{ + $resolver = new PromiseResolver(); $newPlot = clone $plot; $newPlot->owner = $claimer; $newPlot->price = 0.0; $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); - if($ev->isCancelled()) { - return false; + if($ev->isCancelled()){ + $resolver->resolve(false); + return $resolver->getPromise(); } $plot = $ev->getPlot(); - $failed = false; - foreach($this->getProvider()->getMergedPlots($plot) as $merged) { - if($plotName !== "") { - $this->renamePlot($merged, $plotName); - } - $merged->owner = $claimer; - $merged->price = 0.0; - if(!$this->savePlot($merged)) - $failed = true; - } - return !$failed; + Await::f2c( + function() use ($plot, $claimer, $plotName) : \Generator{ + $failed = false; + foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged) { + $merged->owner = $claimer; + $merged->price = 0.0; + if($plotName !== "") + $merged->name = $plotName; + $saved = yield $this->dataProvider->savePlot($plot); + if(!$saved) { + $failed = true; + } + } + return !$failed; + }, + fn(bool $succeeded) => $resolver->resolve($succeeded), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 58ecfc46f4837d3c70051b17416904aa8a32913d Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 00:02:00 -0500 Subject: [PATCH 14/47] Added missing function param --- src/MyPlot/MyPlot.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index c856b58e..76f796f6 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -446,7 +446,7 @@ function() use ($position){ return false; }, fn(bool $isBordering) => $resolver->resolve($isBordering), - fn() => $resolver->reject() + fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); } From f2f2473d56c4f399649963ab17ef059c489f05af Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 02:44:20 -0500 Subject: [PATCH 15/47] Added some utility functions for more generators --- src/MyPlot/utils/AsyncVariants.php | 35 ++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 src/MyPlot/utils/AsyncVariants.php diff --git a/src/MyPlot/utils/AsyncVariants.php b/src/MyPlot/utils/AsyncVariants.php new file mode 100644 index 00000000..490d8560 --- /dev/null +++ b/src/MyPlot/utils/AsyncVariants.php @@ -0,0 +1,35 @@ +getLevelSettings($plot->levelName); + $origin = yield $plugin->getProvider()->getMergeOrigin($plot); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($mergeOrigin){ + $x = $totalSize * $origin->X; + $z = $totalSize * $origin->Z; + }else{ + $x = $totalSize * $plot->X; + $z = $totalSize * $plot->Z; + } + $level = $plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + return new Position($x, $plotLevel->groundHeight, $z, $level); + } +} \ No newline at end of file From aec381448cfc27a3e32ef9280d03ba3c5e959fff Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 02:47:28 -0500 Subject: [PATCH 16/47] use new utility functions in getPlotBB --- src/MyPlot/MyPlot.php | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 76f796f6..29a59200 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -541,24 +541,14 @@ public function getPlotBB(Plot $plot) : Promise{ $resolver = new PromiseResolver(); Await::f2c( function() use ($plot){ - $getPlotPosition = function($plot){ - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - $x = $totalSize * $plot->X; - $z = $totalSize * $plot->Z; - $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - return new Position($x, $plotLevel->groundHeight, $z, $level); - }; $plotLevel = $this->getLevelSettings($plot->levelName); $plotSize = $plotLevel->plotSize - 1; - $pos = $getPlotPosition($plot); + $pos = yield AsyncVariants::getPlotPosition($plot, false); $xMax = (int) ($pos->x + $plotSize); $zMax = (int) ($pos->z + $plotSize); foreach((yield $this->dataProvider->getMergedPlots($plot)) as $mergedPlot){ - $xplot = $getPlotPosition($mergedPlot)->x; - $zplot = $getPlotPosition($mergedPlot)->z; + $xplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->x; + $zplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->z; $xMaxPlot = (int) ($xplot + $plotSize); $zMaxPlot = (int) ($zplot + $plotSize); if($pos->x > $xplot) $pos->x = $xplot; From 3f120c1aed56a0a41980e8b6e250acb12be121be Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 02:48:18 -0500 Subject: [PATCH 17/47] publicize getPlotFast for a non-async way to get a plot object --- src/MyPlot/MyPlot.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 29a59200..740f95f9 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -310,7 +310,7 @@ function() use ($position){ * * @return Plot|null */ - private function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?Plot { + public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?Plot{ $plotSize = $plotLevel->plotSize; $roadWidth = $plotLevel->roadWidth; $totalSize = $plotSize + $roadWidth; @@ -331,7 +331,7 @@ private function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)) return null; - return $this->dataProvider->getPlot($plotLevel->name, $x, $z); + return new Plot($plotLevel->name, $x, $z); } /** From 87d5e37971f3e7b4d18087112a20c60c4ff6bc97 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 02:54:48 -0500 Subject: [PATCH 18/47] Updated clonePlot to Async/Await format --- src/MyPlot/MyPlot.php | 169 ++++++++++++++++++++++-------------------- 1 file changed, 90 insertions(+), 79 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 740f95f9..95be4a54 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -800,92 +800,103 @@ public function renamePlot(Plot $plot, string $newName = "") : Promise{ * @param Plot $plotFrom * @param Plot $plotTo * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function clonePlot(Plot $plotFrom, Plot $plotTo) : bool { + public function clonePlot(Plot $plotFrom, Plot $plotTo) : Promise { + $resolver = new PromiseResolver(); $styler = $this->getServer()->getPluginManager()->getPlugin("WorldStyler"); if(!$styler instanceof WorldStyler) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } if(!$this->isLevelLoaded($plotFrom->levelName) or !$this->isLevelLoaded($plotTo->levelName)) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } - $world = $this->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); - $aabb = $this->getPlotBB($plotTo); - foreach($world->getEntities() as $entity) { - if($aabb->isVectorInXZ($entity->getPosition())) { - if($entity instanceof Player){ - $this->teleportPlayerToPlot($entity, $plotTo); + Await::f2c( + function() use ($plotFrom, $plotTo, $styler) { + $world = $this->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); + $aabb = yield $this->getPlotBB($plotTo); + foreach($world->getEntities() as $entity) { + if($aabb->isVectorInXZ($entity->getPosition())) { + if($entity instanceof Player){ + $this->teleportPlayerToPlot($entity, $plotTo); + } + } } - } - } - $ev = new MyPlotCloneEvent($plotFrom, $plotTo); - $ev->call(); - if($ev->isCancelled()) { - return false; - } - $plotFrom = $ev->getPlot(); - $plotTo = $ev->getClonePlot(); - if(!$this->isLevelLoaded($plotFrom->levelName) or !$this->isLevelLoaded($plotTo->levelName)) { - return false; - } - $plotLevel = $this->getLevelSettings($plotFrom->levelName); - $plotSize = $plotLevel->plotSize-1; - $plotBeginPos = $this->getPlotPosition($plotFrom); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = (int)($plotBeginPos->x + $plotSize); - $zMax = (int)($plotBeginPos->z + $plotSize); - foreach ($this->getProvider()->getMergedPlots($plotFrom) as $mergedPlot){ - $pos = $this->getPlotPosition($mergedPlot, false)->subtract(1,0,1); - $xMaxPlot = (int)($pos->x + $plotSize); - $zMaxPlot = (int)($pos->z + $plotSize); - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - $selection = $styler->getSelection(99997) ?? new Selection(99997); - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); // do not use async because WorldStyler async is very broken right now - $cuboid->copy($level, $vec2, function (float $time, int $changed) : void { - $this->getLogger()->debug(TF::GREEN . 'Copied ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's to the MyPlot clipboard.'); - }); - - $plotLevel = $this->getLevelSettings($plotTo->levelName); - $plotSize = $plotLevel->plotSize-1; - $plotBeginPos = $this->getPlotPosition($plotTo); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = (int)($plotBeginPos->x + $plotSize); - $zMax = (int)($plotBeginPos->z + $plotSize); - foreach ($this->getProvider()->getMergedPlots($plotTo) as $mergedPlot){ - $pos = $this->getPlotPosition($mergedPlot, false)->subtract(1,0,1); - $xMaxPlot = (int)($pos->x + $plotSize); - $zMaxPlot = (int)($pos->z + $plotSize); - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); - $commonShape = CommonShape::fromSelection($selection); - //$commonShape = $commonShape->async(); // do not use async because WorldStyler async is very broken right now - $commonShape->paste($level, $vec2, true, function (float $time, int $changed) : void { - $this->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); - }); - $styler->removeSelection(99997); - foreach($this->getPlotChunks($plotTo) as [$chunkX, $chunkZ, $chunk]) { - $level->setChunk($chunkX, $chunkZ, $chunk); - } - return true; + $ev = new MyPlotCloneEvent($plotFrom, $plotTo); + $ev->call(); + if($ev->isCancelled()) { + return false; + } + $plotFrom = $ev->getPlot(); + $plotTo = $ev->getClonePlot(); + if(!$this->isLevelLoaded($plotFrom->levelName) or !$this->isLevelLoaded($plotTo->levelName)){ + return false; + } + $plotLevel = $this->getLevelSettings($plotFrom->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield AsyncVariants::getPlotPosition($plotFrom); + $level = $plotBeginPos->getWorld(); + $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); + $plotBeginPos->y = 0; + $xMax = (int) ($plotBeginPos->x + $plotSize); + $zMax = (int) ($plotBeginPos->z + $plotSize); + foreach(yield $this->dataProvider->getMergedPlots($plotFrom) as $mergedPlot){ + $pos = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->subtract(1, 0, 1); + $xMaxPlot = (int) ($pos->x + $plotSize); + $zMaxPlot = (int) ($pos->z + $plotSize); + if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; + if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + $selection = $styler->getSelection(99997) ?? new Selection(99997); + $selection->setPosition(1, $plotBeginPos); + $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); + $selection->setPosition(2, $vec2); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); // do not use async because WorldStyler async is very broken right now + $cuboid->copy($level, $vec2, function(float $time, int $changed) : void{ + $this->getLogger()->debug(TF::GREEN . 'Copied ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's to the MyPlot clipboard.'); + }); + + $plotLevel = $this->getLevelSettings($plotTo->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield AsyncVariants::getPlotPosition($plotTo); + $level = $plotBeginPos->getWorld(); + $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); + $plotBeginPos->y = 0; + $xMax = (int) ($plotBeginPos->x + $plotSize); + $zMax = (int) ($plotBeginPos->z + $plotSize); + foreach(yield $this->dataProvider->getMergedPlots($plotTo) as $mergedPlot){ + $pos = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->subtract(1, 0, 1); + $xMaxPlot = (int) ($pos->x + $plotSize); + $zMaxPlot = (int) ($pos->z + $plotSize); + if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; + if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + $selection->setPosition(1, $plotBeginPos); + $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); + $selection->setPosition(2, $vec2); + $commonShape = CommonShape::fromSelection($selection); + //$commonShape = $commonShape->async(); // do not use async because WorldStyler async is very broken right now + $commonShape->paste($level, $vec2, true, function (float $time, int $changed) : void { + $this->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); + }); + $styler->removeSelection(99997); + foreach($this->getPlotChunks($plotTo) as [$chunkX, $chunkZ, $chunk]) { + $level->setChunk($chunkX, $chunkZ, $chunk); + } + return true; + }, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 73be90826f3063c7c182dd89bf5f6f4cf1dfe26b Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 02:57:07 -0500 Subject: [PATCH 19/47] Updated clearPlot to Async/Await format --- src/MyPlot/MyPlot.php | 182 ++++++++++++++++++++++-------------------- 1 file changed, 96 insertions(+), 86 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 95be4a54..a098368b 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -907,103 +907,113 @@ function() use ($plotFrom, $plotTo, $styler) { * @param Plot $plot * @param int $maxBlocksPerTick * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function clearPlot(Plot $plot, int $maxBlocksPerTick = 256) : bool { + public function clearPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { + $resolver = new PromiseResolver(); $ev = new MyPlotClearEvent($plot, $maxBlocksPerTick); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } $plot = $ev->getPlot(); if(!$this->isLevelLoaded($plot->levelName)) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null) - return false; - foreach($level->getEntities() as $entity) { - if($this->getPlotBB($plot)->isVectorInXZ($entity->getPosition())) { - if(!$entity instanceof Player) { - $entity->flagForDespawn(); - }else{ - $this->teleportPlayerToPlot($entity, $plot); - } - } - } - if($this->getConfig()->get("FastClearing", false) === true) { - $styler = $this->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if(!$styler instanceof WorldStyler) { - return false; - } - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize-1; - $plotBeginPos = $this->getPlotPosition($plot); - $xMax = (int)($plotBeginPos->x + $plotSize); - $zMax = (int)($plotBeginPos->z + $plotSize); - foreach ($this->getProvider()->getMergedPlots($plot) as $mergedPlot){ - $xplot = $this->getPlotPosition($mergedPlot, false)->x; - $zplot = $this->getPlotPosition($mergedPlot, false)->z; - $xMaxPlot = (int)($xplot + $plotSize); - $zMaxPlot = (int)($zplot + $plotSize); - if($plotBeginPos->x > $xplot) $plotBeginPos->x = $xplot; - if($plotBeginPos->z > $zplot) $plotBeginPos->z = $zplot; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - // Above ground - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight+1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, World::Y_MAX, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), VanillaBlocks::AIR()->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Ground Surface - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFloorBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Ground - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight-1, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFillBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Bottom of world - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 0; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, 0, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]) { - $plotBeginPos->getWorld()->setChunk($chunkX, $chunkZ, $chunk); - } - $this->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this, $plot), 1); - return true; + if($level === null){ + $resolver->resolve(false); + return $resolver->getPromise(); } - $this->getScheduler()->scheduleTask(new ClearPlotTask($this, $plot, $maxBlocksPerTick)); - return true; + Await::f2c( + function() use ($plot, $maxBlocksPerTick, $level) : \Generator { + foreach($level->getEntities() as $entity) { + if((yield $this->getPlotBB($plot))->isVectorInXZ($entity->getPosition())) { + if(!$entity instanceof Player) { + $entity->flagForDespawn(); + }else{ + $this->teleportPlayerToPlot($entity, $plot); + } + } + } + $styler = $this->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if($this->getConfig()->get("FastClearing", false) === true && $styler instanceof WorldStyler) { + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize-1; + $plotBeginPos = yield AsyncVariants::getPlotPosition($plot); + $xMax = (int)($plotBeginPos->x + $plotSize); + $zMax = (int)($plotBeginPos->z + $plotSize); + foreach(yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot){ + $xplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->x; + $zplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->z; + $xMaxPlot = (int) ($xplot + $plotSize); + $zMaxPlot = (int) ($zplot + $plotSize); + if($plotBeginPos->x > $xplot) $plotBeginPos->x = $xplot; + if($plotBeginPos->z > $zplot) $plotBeginPos->z = $zplot; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + // Above ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = $plotLevel->groundHeight+1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, World::Y_MAX, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), VanillaBlocks::AIR()->getFullId(), function (float $time, int $changed) : void { + $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Ground Surface + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = $plotLevel->groundHeight; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFloorBlock->getFullId(), function (float $time, int $changed) : void { + $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = 1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight-1, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFillBlock->getFullId(), function (float $time, int $changed) : void { + $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Bottom of world + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = 0; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, 0, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function (float $time, int $changed) : void { + $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]) { + $plotBeginPos->getWorld()->setChunk($chunkX, $chunkZ, $chunk); + } + $this->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this, $plot), 1); + return true; + } + $this->getScheduler()->scheduleTask(new ClearPlotTask($this, $plot, $maxBlocksPerTick)); + return true; + }, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From 339bcf187ff7cc1a112e0fc83961581dca1294c5 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:04:21 -0500 Subject: [PATCH 20/47] Updated resetPlot to Async/Await format --- src/MyPlot/MyPlot.php | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index a098368b..8b6879c6 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1117,20 +1117,33 @@ public function disposePlot(Plot $plot) : Promise { * * @api * + * @noinspection PhpVoidFunctionResultUsedInspection + * * @param Plot $plot * @param int $maxBlocksPerTick * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function resetPlot(Plot $plot, int $maxBlocksPerTick = 256) : bool { + public function resetPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { + $resolver = new PromiseResolver(); $ev = new MyPlotResetEvent($plot); $ev->call(); - if($ev->isCancelled()) - return false; - if($this->disposePlot($plot)) { - return $this->clearPlot($plot, $maxBlocksPerTick); + if($ev->isCancelled()) { + $resolver->resolve(false); + return $resolver->getPromise(); } - return false; + Await::g2c( + $this->dataProvider->deletePlot($plot), + fn(bool $success) => + $success && + $this->clearPlot($plot, $maxBlocksPerTick)->onCompletion( + fn(bool $success) => $resolver->resolve($success), + fn() => $resolver->reject() + ), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From bff40b565852ee9dc7f10b2d9a86465257965433 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:07:33 -0500 Subject: [PATCH 21/47] Updated setPlotBiome to Async/Await format --- src/MyPlot/MyPlot.php | 62 ++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 8b6879c6..860e8e98 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1154,15 +1154,18 @@ public function resetPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { * @param Plot $plot * @param Biome $biome * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function setPlotBiome(Plot $plot, Biome $biome) : bool { + public function setPlotBiome(Plot $plot, Biome $biome) : Promise { + $resolver = new PromiseResolver(); $newPlot = clone $plot; $newPlot->biome = str_replace(" ", "_", strtoupper($biome->getName())); $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } $plot = $ev->getPlot(); if(defined(BiomeIds::class."::".$plot->biome) and is_int(constant(BiomeIds::class."::".$plot->biome))) { @@ -1171,30 +1174,41 @@ public function setPlotBiome(Plot $plot, Biome $biome) : bool { $biome = BiomeIds::PLAINS; } $biome = BiomeRegistry::getInstance()->getBiome($biome); - if(!$this->isLevelLoaded($plot->levelName)) - return false; - $failed = false; - foreach($this->getProvider()->getMergedPlots($plot) as $merged) { - $merged->biome = $plot->biome; - if(!$this->savePlot($merged)) - $failed = true; + if(!$this->isLevelLoaded($plot->levelName)){ + $resolver->resolve(false); + return $resolver->getPromise(); } - $plotLevel = $this->getLevelSettings($plot->levelName); - $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null) - return false; - foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]) { - for($x = 0; $x < 16; ++$x) { - for($z = 0; $z < 16; ++$z) { - $chunkPlot = $this->getPlotByPosition(new Position(($chunkX << 4) + $x, $plotLevel->groundHeight, ($chunkZ << 4) + $z, $level)); - if($chunkPlot instanceof Plot and $chunkPlot->isSame($plot)) { - $chunk->setBiomeId($x, $z, $biome->getId()); + Await::f2c( + function() use ($plot, $biome, $resolver) { + $failed = false; + foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ + $merged->biome = $plot->biome; + if(!yield $this->dataProvider->savePlot($merged)) + $failed = true; + } + $plotLevel = $this->getLevelSettings($plot->levelName); + $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($level === null) { + return false; + } + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]) { + for($x = 0; $x < 16; ++$x) { + for($z = 0; $z < 16; ++$z) { + $pos = new Position(($chunkX << 4) + $x, $plotLevel->groundHeight, ($chunkZ << 4) + $z, $level); + $chunkPlot = $this->getPlotFast($pos->x, $pos->z, $plotLevel); + if($chunkPlot instanceof Plot and $chunkPlot->isSame($plot)) { + $chunk->setBiomeId($x, $z, $biome->getId()); + } + } } + $level->setChunk($chunkX, $chunkZ, $chunk); } - } - $level->setChunk($chunkX, $chunkZ, $chunk); - } - return !$failed; + return !$failed; + }, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } public function setPlotPvp(Plot $plot, bool $pvp) : bool { From b15e883175387f7f7831f9092c8b1da99ec5ad6e Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:08:57 -0500 Subject: [PATCH 22/47] Updated setPlotPvp to Async/Await format --- src/MyPlot/MyPlot.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 860e8e98..91881f0c 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1211,13 +1211,26 @@ function() use ($plot, $biome, $resolver) { return $resolver->getPromise(); } - public function setPlotPvp(Plot $plot, bool $pvp) : bool { + /** + * TODO: description + * + * @api + * + * @param Plot $plot + * @param bool $pvp + * + * @return Promise + * @phpstan-return Promise + */ + public function setPlotPvp(Plot $plot, bool $pvp) : Promise { + $resolver = new PromiseResolver(); $newPlot = clone $plot; $newPlot->pvp = $pvp; $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } return $this->savePlot($ev->getPlot()); } From aa8cc793c2510512ddc6b6b062d737059bd48b93 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:10:10 -0500 Subject: [PATCH 23/47] Updated addPlotHelper to Async/Await format --- src/MyPlot/MyPlot.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 91881f0c..beb46c84 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1235,13 +1235,26 @@ public function setPlotPvp(Plot $plot, bool $pvp) : Promise { return $this->savePlot($ev->getPlot()); } - public function addPlotHelper(Plot $plot, string $player) : bool { + /** + * TODO: description + * + * @api + * + * @param Plot $plot + * @param string $player + * + * @return Promise + * @phpstan-return Promise + */ + public function addPlotHelper(Plot $plot, string $player) : Promise { + $resolver = new PromiseResolver(); $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->addHelper($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } return $this->savePlot($ev->getPlot()); } From 50f3ef82f61840025cc8f560917bfa6bd8d19345 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:10:57 -0500 Subject: [PATCH 24/47] Updated removePlotHelper to Async/Await format --- src/MyPlot/MyPlot.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index beb46c84..ea11c033 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1259,13 +1259,26 @@ public function addPlotHelper(Plot $plot, string $player) : Promise { return $this->savePlot($ev->getPlot()); } - public function removePlotHelper(Plot $plot, string $player) : bool { + /** + * TODO: description + * + * @api + * + * @param Plot $plot + * @param string $player + * + * @return Promise + * @phpstan-return Promise + */ + public function removePlotHelper(Plot $plot, string $player) : Promise { + $resolver = new PromiseResolver(); $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->removeHelper($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } return $this->savePlot($ev->getPlot()); } From ff11da3c08943e493fbba1857526391147bc85ad Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:11:15 -0500 Subject: [PATCH 25/47] Updated addPlotDenied to Async/Await format --- src/MyPlot/MyPlot.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index ea11c033..3af78d14 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1283,13 +1283,26 @@ public function removePlotHelper(Plot $plot, string $player) : Promise { return $this->savePlot($ev->getPlot()); } - public function addPlotDenied(Plot $plot, string $player) : bool { + /** + * TODO: description + * + * @api + * + * @param Plot $plot + * @param string $player + * + * @return Promise + * @phpstan-return Promise + */ + public function addPlotDenied(Plot $plot, string $player) : Promise { + $resolver = new PromiseResolver(); $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->denyPlayer($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } return $this->savePlot($ev->getPlot()); } From 3d623cba11c7bfb50e880776d6eedac9c6fcb313 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:11:27 -0500 Subject: [PATCH 26/47] Updated removePlotDenied to Async/Await format --- src/MyPlot/MyPlot.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 3af78d14..6c226979 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1307,13 +1307,26 @@ public function addPlotDenied(Plot $plot, string $player) : Promise { return $this->savePlot($ev->getPlot()); } - public function removePlotDenied(Plot $plot, string $player) : bool { + /** + * TODO: description + * + * @api + * + * @param Plot $plot + * @param string $player + * + * @return Promise + * @phpstan-return Promise + */ + public function removePlotDenied(Plot $plot, string $player) : Promise { + $resolver = new PromiseResolver(); $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->unDenyPlayer($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } return $this->savePlot($ev->getPlot()); } From 0481a836d1a9019ef692fe83a48e7fd3fef9e294 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:11:54 -0500 Subject: [PATCH 27/47] Updated buyPlot to Async/Await format --- src/MyPlot/MyPlot.php | 51 ++++++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 6c226979..8e5afc9e 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1364,28 +1364,39 @@ public function sellPlot(Plot $plot, float $price) : bool { * @param Plot $plot * @param Player $player * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function buyPlot(Plot $plot, Player $player) : bool { - if($this->getEconomyProvider() === null or !$this->getEconomyProvider()->reduceMoney($player, $plot->price) or !$this->getEconomyProvider()->addMoney($this->getServer()->getOfflinePlayer($plot->owner), $plot->price)) - return false; - $failed = false; - foreach ($this->dataProvider->getMergedPlots($plot) as $mergedPlot) { - $newPlot = clone $mergedPlot; - $newPlot->owner = $player->getName(); - $newPlot->helpers = []; - $newPlot->denied = []; - $newPlot->price = 0.0; - $ev = new MyPlotSettingEvent($mergedPlot, $newPlot); - $ev->call(); - if ($ev->isCancelled()) { - return false; - } - $mergedPlot = $ev->getPlot(); - if($this->savePlot($mergedPlot)) - $failed = true; + public function buyPlot(Plot $plot, Player $player) : Promise { + $resolver = new PromiseResolver(); + if($this->getEconomyProvider() === null or !$this->getEconomyProvider()->reduceMoney($player, $plot->price) or !$this->getEconomyProvider()->addMoney($this->getServer()->getOfflinePlayer($plot->owner), $plot->price)) { + $resolver->resolve(false); + return $resolver->getPromise(); } - return !$failed; + Await::f2c( + function() use($plot, $player) { + $failed = false; + foreach (yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot) { + $newPlot = clone $mergedPlot; + $newPlot->owner = $player->getName(); + $newPlot->helpers = []; + $newPlot->denied = []; + $newPlot->price = 0.0; + $ev = new MyPlotSettingEvent($mergedPlot, $newPlot); + $ev->call(); + if ($ev->isCancelled()) { + $failed = true; + } + $mergedPlot = $ev->getPlot(); + if(! yield $this->dataProvider->savePlot($mergedPlot)) + $failed = true; + } + return !$failed; + }, + fn(bool $success) => $resolver->resolve($success), + fn() => $resolver->reject() + ); + return $resolver->getPromise(); } /** From b06d1b1ce883c4368e54255408277609d8663a07 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:14:53 -0500 Subject: [PATCH 28/47] Updated mergePlots to Async/Await format --- src/MyPlot/MyPlot.php | 142 +++++++++++++++++++++++------------------- 1 file changed, 77 insertions(+), 65 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 8e5afc9e..82df1e93 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -573,83 +573,95 @@ function() use ($plot){ } /** + * TODO: description + * + * @api + * * @param Plot $plot The plot that is to be expanded * @param int $direction The Vector3 direction value to expand towards * @param int $maxBlocksPerTick * - * @return bool - * @throws \Exception + * @return Promise + * @phpstan-return Promise */ - public function mergePlots(Plot $plot, int $direction, int $maxBlocksPerTick = 256) : bool { - if (!$this->isLevelLoaded($plot->levelName)) - return false; - /** @var Plot[][] $toMerge */ - $toMerge = []; - $mergedPlots = $this->getProvider()->getMergedPlots($plot); - $newPlot = $plot->getSide($direction); - $alreadyMerged = false; - foreach ($mergedPlots as $mergedPlot) { - if ($mergedPlot->isSame($newPlot)) { - $alreadyMerged = true; - } - } - if ($alreadyMerged === false and $newPlot->isMerged()) { - $this->getLogger()->debug("Failed to merge due to plot origin mismatch"); - return false; - } - $toMerge[] = [$plot, $newPlot]; - - foreach ($mergedPlots as $mergedPlot) { - $newPlot = $mergedPlot->getSide($direction); - $alreadyMerged = false; - foreach ($mergedPlots as $mergedPlot2) { - if ($mergedPlot2->isSame($newPlot)) { - $alreadyMerged = true; + public function mergePlots(Plot $plot, int $direction, int $maxBlocksPerTick = 256) : Promise{ + $resolver = new PromiseResolver(); + Await::f2c( + function() use ($plot, $direction, $maxBlocksPerTick){ + if(!$this->isLevelLoaded($plot->levelName)) + return false; + /** @var Plot[][] $toMerge */ + $toMerge = []; + $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); + $newPlot = $plot->getSide($direction); + $alreadyMerged = false; + foreach($mergedPlots as $mergedPlot){ + if($mergedPlot->isSame($newPlot)){ + $alreadyMerged = true; + } } - } - if ($alreadyMerged === false and $newPlot->isMerged()) { - $this->getLogger()->debug("Failed to merge due to plot origin mismatch"); - return false; - } - $toMerge[] = [$mergedPlot, $newPlot]; - } - /** @var Plot[][] $toFill */ - $toFill = []; - foreach ($toMerge as $pair) { - foreach ($toMerge as $pair2) { - for ($i = Facing::NORTH; $i <= Facing::EAST; ++$i) { - if ($pair[1]->getSide($i)->isSame($pair2[1])) { - $toFill[] = [$pair[1], $pair2[1]]; + if($alreadyMerged === false and $newPlot->isMerged()){ + $this->getLogger()->debug("Failed to merge due to plot origin mismatch"); + return false; + } + $toMerge[] = [$plot, $newPlot]; + + foreach($mergedPlots as $mergedPlot) { + $newPlot = $mergedPlot->getSide($direction); + $alreadyMerged = false; + foreach($mergedPlots as $mergedPlot2){ + if($mergedPlot2->isSame($newPlot)){ + $alreadyMerged = true; + } + } + if($alreadyMerged === false and $newPlot->isMerged()){ + $this->getLogger()->debug("Failed to merge due to plot origin mismatch"); + return false; + } + $toMerge[] = [$mergedPlot, $newPlot]; + } + /** @var Plot[][] $toFill */ + $toFill = []; + foreach($toMerge as $pair) { + foreach($toMerge as $pair2) { + foreach(Facing::HORIZONTAL as $i) { + if($pair[1]->getSide($i)->isSame($pair2[1])) { + $toFill[] = [$pair[1], $pair2[1]]; + } + } + } + } + $ev = new MyPlotMergeEvent(yield $this->dataProvider->getMergeOrigin($plot), $toMerge); + $ev->call(); + if($ev->isCancelled()) { + return false; + } + foreach($toMerge as $pair) { + if($pair[1]->owner === "") { + $this->getLogger()->debug("Failed to merge due to plot not claimed"); + return false; + }elseif($plot->owner !== $pair[1]->owner) { + $this->getLogger()->debug("Failed to merge due to owner mismatch"); + return false; } } - } - } - $ev = new MyPlotMergeEvent($this->getProvider()->getMergeOrigin($plot), $toMerge); - $ev->call(); - if($ev->isCancelled()) { - return false; - } - foreach ($toMerge as $pair) { - if ($pair[1]->owner === "") { - $this->getLogger()->debug("Failed to merge due to plot not claimed"); - return false; - } elseif ($plot->owner !== $pair[1]->owner) { - $this->getLogger()->debug("Failed to merge due to owner mismatch"); - return false; - } - } - // TODO: WorldStyler clearing + // TODO: WorldStyler clearing - foreach ($toMerge as $pair) - $this->getScheduler()->scheduleTask(new RoadFillTask($this, $pair[0], $pair[1], false, -1, $maxBlocksPerTick)); + foreach($toMerge as $pair) + $this->getScheduler()->scheduleTask(new RoadFillTask($this, $pair[0], $pair[1], false, -1, $maxBlocksPerTick)); - foreach ($toFill as $pair) - $this->getScheduler()->scheduleTask(new RoadFillTask($this, $pair[0], $pair[1], true, $direction, $maxBlocksPerTick)); + foreach($toFill as $pair) + $this->getScheduler()->scheduleTask(new RoadFillTask($this, $pair[0], $pair[1], true, $direction, $maxBlocksPerTick)); - return $this->getProvider()->mergePlots($this->getProvider()->getMergeOrigin($plot), ...array_map(function (array $val) : Plot { - return $val[1]; - }, $toMerge)); + return yield $this->dataProvider->mergePlots(yield $this->dataProvider->getMergeOrigin($plot), ...array_map(function(array $val) : Plot{ + return $val[1]; + }, $toMerge)); + }, + fn(bool $result) => $resolver->resolve($result), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** From ccd237d92ec2bc4660cfbdf82353e8eb8bf33239 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sat, 5 Feb 2022 03:15:18 -0500 Subject: [PATCH 29/47] Updated sellPlot to Async/Await format --- src/MyPlot/MyPlot.php | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 82df1e93..4d530d6c 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -1351,18 +1351,23 @@ public function removePlotDenied(Plot $plot, string $player) : Promise { * @param Plot $plot * @param float $price * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function sellPlot(Plot $plot, float $price) : bool { - if($this->getEconomyProvider() === null or $price < 0) - return false; + public function sellPlot(Plot $plot, float $price) : Promise { + $resolver = new PromiseResolver(); + if($this->getEconomyProvider() === null or $price < 0) { + $resolver->resolve(false); + return $resolver->getPromise(); + } $newPlot = clone $plot; $newPlot->price = $price; $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } $plot = $ev->getPlot(); return $this->savePlot($plot); From 778975653ca08168665174e018c2e795f286e6ab Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sun, 6 Mar 2022 18:36:01 -0500 Subject: [PATCH 30/47] Extract await-style API into InternalAPI class --- src/MyPlot/EventListener.php | 39 +- src/MyPlot/InternalAPI.php | 904 ++++++++++++++++++++++++++ src/MyPlot/MyPlot.php | 1165 +++++++--------------------------- 3 files changed, 1161 insertions(+), 947 deletions(-) create mode 100644 src/MyPlot/InternalAPI.php diff --git a/src/MyPlot/EventListener.php b/src/MyPlot/EventListener.php index 70b984f0..769d70d0 100644 --- a/src/MyPlot/EventListener.php +++ b/src/MyPlot/EventListener.php @@ -31,16 +31,7 @@ class EventListener implements Listener { - private MyPlot $plugin; - - /** - * EventListener constructor. - * - * @param MyPlot $plugin - */ - public function __construct(MyPlot $plugin) { - $this->plugin = $plugin; - } + public function __construct(private MyPlot $plugin, private InternalAPI $api) {} /** * @ignoreCancelled false @@ -66,7 +57,7 @@ public function onLevelLoad(WorldLoadEvent $event) : void { foreach(array_keys($default) as $key) { $settings[$key] = $config->get((string)$key); } - $this->plugin->addLevelSettings($levelName, new PlotLevelSettings($levelName, $settings)); + $this->api->addLevelSettings($levelName, new PlotLevelSettings($levelName, $settings)); if($this->plugin->getConfig()->get('AllowFireTicking', false) === false) { $ref = new \ReflectionClass($event->getWorld()); @@ -90,7 +81,7 @@ public function onLevelUnload(WorldUnloadEvent $event) : void { return; } $levelName = $event->getWorld()->getFolderName(); - if($this->plugin->unloadLevelSettings($levelName)) { + if($this->api->unloadLevelSettings($levelName)) { $this->plugin->getLogger()->debug("Level " . $event->getWorld()->getFolderName() . " unloaded!"); } } @@ -137,7 +128,7 @@ public function onSignChange(SignChangeEvent $event) : void { private function onEventOnBlock(BlockPlaceEvent|SignChangeEvent|PlayerInteractEvent|BlockBreakEvent $event) : void { $levelName = $event->getBlock()->getPosition()->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) { + if($this->api->getLevelSettings($levelName) === null) { return; } $plot = $this->plugin->getPlotByPosition($event->getBlock()->getPosition()); @@ -162,7 +153,7 @@ private function onEventOnBlock(BlockPlaceEvent|SignChangeEvent|PlayerInteractEv $endPos = clone $beginPos; $beginPos->x += $maxLengthLeaves; $beginPos->z += $maxLengthLeaves; - $plotSize = $this->plugin->getLevelSettings($levelName)->plotSize; + $plotSize = $this->api->getLevelSettings($levelName)->plotSize; $endPos->x += $plotSize - $maxLengthLeaves; $endPos->z += $plotSize - $maxLengthLeaves; if($block->getPosition()->x >= $beginPos->x and $block->getPosition()->z >= $beginPos->z and $block->getPosition()->x < $endPos->x and $block->getPosition()->z < $endPos->z) { @@ -171,7 +162,7 @@ private function onEventOnBlock(BlockPlaceEvent|SignChangeEvent|PlayerInteractEv } }elseif($event->getPlayer()->hasPermission("myplot.admin.build.road")) return; - elseif($this->plugin->isPositionBorderingPlot($event->getBlock()->getPosition()) and $this->plugin->getLevelSettings($levelName)->editBorderBlocks) { + elseif($this->plugin->isPositionBorderingPlot($event->getBlock()->getPosition()) and $this->api->getLevelSettings($levelName)->editBorderBlocks) { $plot = $this->plugin->getPlotBorderingPosition($event->getBlock()->getPosition()); if($plot instanceof Plot) { $ev = new MyPlotBorderChangeEvent($plot, $event->getBlock(), $event->getPlayer(), $event); @@ -201,7 +192,7 @@ public function onExplosion(EntityExplodeEvent $event) : void { return; } $levelName = $event->getEntity()->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) + if($this->api->getLevelSettings($levelName) === null) return; $plot = $this->plugin->getPlotByPosition($event->getPosition()); if($plot === null) { @@ -210,7 +201,7 @@ public function onExplosion(EntityExplodeEvent $event) : void { } $beginPos = $this->plugin->getPlotPosition($plot); $endPos = clone $beginPos; - $levelSettings = $this->plugin->getLevelSettings($levelName); + $levelSettings = $this->api->getLevelSettings($levelName); $plotSize = $levelSettings->plotSize; $endPos->x += $plotSize; $endPos->z += $plotSize; @@ -237,9 +228,9 @@ public function onEntityMotion(EntityMotionEvent $event) : void { if(!$level instanceof World) return; $levelName = $level->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) + if($this->api->getLevelSettings($levelName) === null) return; - $settings = $this->plugin->getLevelSettings($levelName); + $settings = $this->api->getLevelSettings($levelName); if($settings->restrictEntityMovement and !($event->getEntity() instanceof Player)) { $event->cancel(); $this->plugin->getLogger()->debug("Cancelled entity motion on " . $levelName); @@ -257,9 +248,9 @@ public function onBlockSpread(BlockSpreadEvent $event) : void { return; } $levelName = $event->getBlock()->getPosition()->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) + if($this->api->getLevelSettings($levelName) === null) return; - $settings = $this->plugin->getLevelSettings($levelName); + $settings = $this->api->getLevelSettings($levelName); $newBlockInPlot = ($plotA = $this->plugin->getPlotByPosition($event->getBlock()->getPosition())) instanceof Plot; $sourceBlockInPlot = ($plotB = $this->plugin->getPlotByPosition($event->getSource()->getPosition())) instanceof Plot; @@ -305,7 +296,7 @@ public function onPlayerTeleport(EntityTeleportEvent $event) : void { private function onEventOnMove(Player $player, EntityTeleportEvent|PlayerMoveEvent $event) : void { $levelName = $player->getWorld()->getFolderName(); - if (!$this->plugin->isLevelLoaded($levelName)) + if ($this->api->getLevelSettings($levelName) === null) return; $plot = $this->plugin->getPlotByPosition($event->getTo()); $plotFrom = $this->plugin->getPlotByPosition($event->getFrom()); @@ -367,10 +358,10 @@ public function onEntityDamage(EntityDamageByEntityEvent $event) : void { $damager = $event->getDamager(); if($damaged instanceof Player and $damager instanceof Player and !$event->isCancelled()) { $levelName = $damaged->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) { + if($this->api->getLevelSettings($levelName) === null) { return; } - $settings = $this->plugin->getLevelSettings($levelName); + $settings = $this->api->getLevelSettings($levelName); $plot = $this->plugin->getPlotByPosition($damaged->getPosition()); if($plot !== null) { $ev = new MyPlotPvpEvent($plot, $damager, $damaged, $event); diff --git a/src/MyPlot/InternalAPI.php b/src/MyPlot/InternalAPI.php new file mode 100644 index 00000000..81eae1d8 --- /dev/null +++ b/src/MyPlot/InternalAPI.php @@ -0,0 +1,904 @@ +getLogger()->debug(TF::BOLD . "Loading Data Provider settings"); + $this->dataProvider = new DataProvider($plugin); + } + + public function getAllLevelSettings() : array{ + return $this->levels; + } + + public function getLevelSettings(string $levelName) : ?PlotLevelSettings{ + return $this->levels[$levelName] ?? null; + } + + public function addLevelSettings(string $levelName, PlotLevelSettings $settings) : void{ + $this->levels[$levelName] = $settings; + } + + public function unloadLevelSettings(string $levelName) : bool{ + if(isset($this->levels[$levelName])){ + unset($this->levels[$levelName]); + return true; + } + return false; + } + + /** + * @param SinglePlot $plot + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function savePlot(SinglePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotsToSave($plot), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlotsToSave(SinglePlot $plot) : \Generator{ + $failed = false; + foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ + $savePlot = clone $plot; + $savePlot->X = $merged->X; + $savePlot->Z = $merged->Z; + $savePlot->levelName = $merged->levelName; + $saved = yield $this->dataProvider->savePlot($plot); + if(!$saved){ + $failed = true; + } + } + return !$failed; + } + + /** + * @param string $username + * @param string|null $levelName + * @param callable|null $onComplete + * @phpstan-param (callable(array): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlotsOfPlayer(string $username, ?string $levelName, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->dataProvider->getPlotsByOwner($username, $levelName), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param string $levelName + * @param int $limitXZ + * @param callable|null $onComplete + * @phpstan-param (callable(Plot): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getNextFreePlot(string $levelName, int $limitXZ, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->dataProvider->getNextFreePlot($levelName, $limitXZ), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?SinglePlot{ + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($x >= 0){ + $difX = $x % $totalSize; + $x = (int) floor($x / $totalSize); + }else{ + $difX = abs(($x - $plotSize + 1) % $totalSize); + $x = (int) ceil(($x - $plotSize + 1) / $totalSize); + } + if($z >= 0){ + $difZ = $z % $totalSize; + $z = (int) floor($z / $totalSize); + }else{ + $difZ = abs(($z - $plotSize + 1) % $totalSize); + $z = (int) ceil(($z - $plotSize + 1) / $totalSize); + } + if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)) + return null; + + return new SinglePlot($plotLevel->name, $x, $z); + } + + /** + * @param Position $position + * @param callable|null $onComplete + * @phpstan-param (callable(Plot): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlotByPosition(Position $position, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotByPosition($position), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlotByPosition(Position $position) : \Generator{ + $x = $position->x; + $z = $position->z; + $levelName = $position->getWorld()->getFolderName(); + if($this->getLevelSettings($levelName) === null) + return null; + $plotLevel = $this->getLevelSettings($levelName); + + $plot = $this->getPlotFast($x, $z, $plotLevel); + if($plot instanceof SinglePlot) + return yield $this->dataProvider->getMergeOrigin($plot); + + $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); + if(!$basePlot->isMerged()) + return null; + + // no plot found at current location yet, so search cardinal directions + $plotN = $basePlot->getSide(Facing::NORTH); + if($plotN->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotN); + + $plotS = $basePlot->getSide(Facing::SOUTH); + if($plotS->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotS); + + $plotE = $basePlot->getSide(Facing::EAST); + if($plotE->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotE); + + $plotW = $basePlot->getSide(Facing::WEST); + if($plotW->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotW); + + return null; + } + + /** + * @param SinglePlot $plot + * @param bool $mergeOrigin + * @param callable|null $onComplete + * @phpstan-param (callable(Position): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlotPosition(SinglePlot $plot, bool $mergeOrigin, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotPosition($plot, $mergeOrigin), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlotPosition(SinglePlot $plot, bool $mergeOrigin) : \Generator{ + $plotLevel = $this->getLevelSettings($plot->levelName); + $origin = yield $this->dataProvider->getMergeOrigin($plot); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($mergeOrigin){ + $x = $totalSize * $origin->X; + $z = $totalSize * $origin->Z; + }else{ + $x = $totalSize * $plot->X; + $z = $totalSize * $plot->Z; + } + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + return new Position($x, $plotLevel->groundHeight, $z, $level); + } + + /** + * @param Position $position + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function isPositionBorderingPlot(Position $position, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::f2c( + function() use ($position){ + $plot = yield $this->generatePlotBorderingPosition($position); + return $plot instanceof SinglePlot; + }, + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param Position $position + * @param callable|null $onComplete + * @phpstan-param (callable(Plot): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlotBorderingPosition(Position $position, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotBorderingPosition($position), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlotBorderingPosition(Position $position) : \Generator{ + if(!$position->isValid()) + return null; + foreach(Facing::HORIZONTAL as $i){ + $pos = $position->getSide($i); + $x = $pos->x; + $z = $pos->z; + $levelName = $pos->getWorld()->getFolderName(); + + if($this->getLevelSettings($levelName) === null) + return null; + + $plotLevel = $this->getLevelSettings($levelName); + $plotSize = $plotLevel->plotSize; + $roadWidth = $plotLevel->roadWidth; + $totalSize = $plotSize + $roadWidth; + if($x >= 0){ + $X = (int) floor($x / $totalSize); + $difX = $x % $totalSize; + }else{ + $X = (int) ceil(($x - $plotSize + 1) / $totalSize); + $difX = abs(($x - $plotSize + 1) % $totalSize); + } + if($z >= 0){ + $Z = (int) floor($z / $totalSize); + $difZ = $z % $totalSize; + }else{ + $Z = (int) ceil(($z - $plotSize + 1) / $totalSize); + $difZ = abs(($z - $plotSize + 1) % $totalSize); + } + if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ + $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); + if(!$basePlot->isMerged()) + return null; + + // no plot found at current location yet, so search cardinal directions + $plotN = $basePlot->getSide(Facing::NORTH); + if($plotN->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotN); + + $plotS = $basePlot->getSide(Facing::SOUTH); + if($plotS->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotS); + + $plotE = $basePlot->getSide(Facing::EAST); + if($plotE->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotE); + + $plotW = $basePlot->getSide(Facing::WEST); + if($plotW->isSame($basePlot)) + return yield $this->dataProvider->getMergeOrigin($plotW); + continue; + } + return yield $this->dataProvider->getPlot($levelName, $X, $Z); + } + return null; + } + + /** + * @param SinglePlot $plot + * @param callable|null $onComplete + * @phpstan-param (callable(AxisAlignedBB): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlotBB(SinglePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotBB($plot), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlotBB(SinglePlot $plot) : \Generator{ + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize - 1; + $pos = yield $this->generatePlotPosition($plot, false); + $xMax = $pos->x + $plotSize; + $zMax = $pos->z + $plotSize; + foreach((yield $this->dataProvider->getMergedPlots($plot)) as $mergedPlot){ + $xplot = (yield $this->generatePlotPosition($mergedPlot, false))->x; + $zplot = (yield $this->generatePlotPosition($mergedPlot, false))->z; + $xMaxPlot = (int) ($xplot + $plotSize); + $zMaxPlot = (int) ($zplot + $plotSize); + if($pos->x > $xplot) $pos->x = $xplot; + if($pos->z > $zplot) $pos->z = $zplot; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + + return new AxisAlignedBB( + min($pos->x, $xMax), + $pos->getWorld()->getMinY(), + min($pos->z, $zMax), + max($pos->x, $xMax), + $pos->getWorld()->getMaxY(), + max($pos->z, $zMax) + ); + } + + /** + * @param SinglePlot $plot + * @param int $direction + * @param int $maxBlocksPerTick + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateMergePlots($plot, $direction, $maxBlocksPerTick), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generateMergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTick) : \Generator{ + if($this->getLevelSettings($plot->levelName) === null) + return false; + /** @var SinglePlot[][] $toMerge */ + $toMerge = []; + $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); + $newPlot = $plot->getSide($direction); + $alreadyMerged = false; + foreach($mergedPlots as $mergedPlot){ + if($mergedPlot->isSame($newPlot)){ + $alreadyMerged = true; + } + } + if($alreadyMerged === false and $newPlot->isMerged()){ + $this->plugin->getLogger()->debug("Failed to merge due to plot origin mismatch"); + return false; + } + $toMerge[] = [$plot, $newPlot]; + + foreach($mergedPlots as $mergedPlot){ + $newPlot = $mergedPlot->getSide($direction); + $alreadyMerged = false; + foreach($mergedPlots as $mergedPlot2){ + if($mergedPlot2->isSame($newPlot)){ + $alreadyMerged = true; + } + } + if($alreadyMerged === false and $newPlot->isMerged()){ + $this->plugin->getLogger()->debug("Failed to merge due to plot origin mismatch"); + return false; + } + $toMerge[] = [$mergedPlot, $newPlot]; + } + /** @var BasePlot[][] $toFill */ + $toFill = []; + foreach($toMerge as $pair){ + foreach($toMerge as $pair2){ + foreach(Facing::HORIZONTAL as $i){ + if($pair[1]->getSide($i)->isSame($pair2[1])){ + $toFill[] = [$pair[1], $pair2[1]]; + } + } + } + } + $ev = new MyPlotMergeEvent(yield $this->dataProvider->getMergeOrigin($plot), $toMerge); + $ev->call(); + if($ev->isCancelled()){ + return false; + } + foreach($toMerge as $pair){ + if($pair[1]->owner === ""){ + $this->plugin->getLogger()->debug("Failed to merge due to plot not claimed"); + return false; + }elseif($plot->owner !== $pair[1]->owner){ + $this->plugin->getLogger()->debug("Failed to merge due to owner mismatch"); + return false; + } + } + + // TODO: WorldStyler clearing + + foreach($toMerge as $pair) + $this->plugin->getScheduler()->scheduleTask(new RoadFillTask($this->plugin, $pair[0], $pair[1], false, -1, $maxBlocksPerTick)); + + foreach($toFill as $pair) + $this->plugin->getScheduler()->scheduleTask(new RoadFillTask($this->plugin, $pair[0], $pair[1], true, $direction, $maxBlocksPerTick)); + + return yield $this->dataProvider->mergePlots(yield $this->dataProvider->getMergeOrigin($plot), ...array_map(function(array $val) : SinglePlot{ + return $val[1]; + }, $toMerge)); + } + + /** + * @param Player $player + * @param SinglePlot $plot + * @param bool $center + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function teleportPlayerToPlot(Player $player, SinglePlot $plot, bool $center, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlayerTeleport($player, $plot, $center), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlayerTeleport(Player $player, SinglePlot $plot, bool $center) : \Generator{ + if($center){ + $pos = $plot->isMerged() ? yield $this->getMergeMid($plot) : yield $this->getPlotMid($plot); + return $player->teleport($pos); + } + + if($plot->isMerged()){ + $plotLevel = $this->getLevelSettings($plot->levelName); + + $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); + $minx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->x < (yield $this->generatePlotPosition($b, false))->x ? $a : $b; + }), false))->x; + $maxx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->x > (yield $this->generatePlotPosition($b, false))->x ? $a : $b; + }), false))->x + $plotLevel->plotSize; + $minz = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->z < (yield $this->generatePlotPosition($b, false))->z ? $a : $b; + }), false))->z; + + $pos = new Position($minx, $plotLevel->groundHeight, $minz, $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)); + $pos->x = floor(($minx + $maxx) / 2); + $pos->y += 1.5; + $pos->z -= 1; + return $player->teleport($pos); + } + + $plotLevel = $this->getLevelSettings($plot->levelName); + $pos = yield $this->generatePlotPosition($plot, true); + $pos->x += floor($plotLevel->plotSize / 2); + $pos->y += 1.5; + $pos->z -= 1; + return $player->teleport($pos); + } + + private function getPlotMid(SinglePlot $plot) : \Generator{ + if($this->getLevelSettings($plot->levelName) === null) + return null; + + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize; + $pos = yield $this->generatePlotPosition($plot, false); + return new Position($pos->x + ($plotSize / 2), $pos->y + 1, $pos->z + ($plotSize / 2), $pos->getWorld()); + } + + private function getMergeMid(SinglePlot $plot) : \Generator{ + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize; + $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); + $minx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->x < (yield $this->generatePlotPosition($b, false))->x ? $a : $b; + }), false))->x; + $maxx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->x > (yield $this->generatePlotPosition($b, false))->x ? $a : $b; + }), false))->x + $plotSize; + $minz = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->z < (yield $this->generatePlotPosition($b, false))->z ? $a : $b; + }), false))->z; + $maxz = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->z > (yield $this->generatePlotPosition($b, false))->z ? $a : $b; + }), false))->z + $plotSize; + return new Position(($minx + $maxx) / 2, $plotLevel->groundHeight, ($minz + $maxz) / 2, $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)); + } + + /** + * @param SinglePlot $plotFrom + * @param SinglePlot $plotTo + * @param WorldStyler $styler + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo, WorldStyler $styler, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::f2c( + function() use ($plotFrom, $plotTo, $styler){ + $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); + $aabb = yield $this->generatePlotBB($plotTo); + foreach($world->getEntities() as $entity){ + if($aabb->isVectorInXZ($entity->getPosition())){ + if($entity instanceof Player){ + $this->generatePlayerTeleport($entity, $plotTo, false); + } + } + } + $plotLevel = $this->getLevelSettings($plotFrom->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plotFrom, true); + $level = $plotBeginPos->getWorld(); + $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); + $plotBeginPos->y = 0; + $xMax = $plotBeginPos->x + $plotSize; + $zMax = $plotBeginPos->z + $plotSize; + foreach(yield $this->dataProvider->getMergedPlots($plotFrom) as $mergedPlot){ + $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); + $xMaxPlot = $pos->x + $plotSize; + $zMaxPlot = $pos->z + $plotSize; + if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; + if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + $selection = $styler->getSelection(99997) ?? new Selection(99997); + $selection->setPosition(1, $plotBeginPos); + $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); + $selection->setPosition(2, $vec2); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); // do not use async because WorldStyler async is very broken right now + $cuboid->copy($level, $vec2, function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug(TF::GREEN . 'Copied ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's to the MyPlot clipboard.'); + }); + + $plotLevel = $this->getLevelSettings($plotTo->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plotTo, true); + $level = $plotBeginPos->getWorld(); + $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); + $plotBeginPos->y = 0; + $xMax = $plotBeginPos->x + $plotSize; + $zMax = $plotBeginPos->z + $plotSize; + foreach(yield $this->dataProvider->getMergedPlots($plotTo) as $mergedPlot){ + $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); + $xMaxPlot = $pos->x + $plotSize; + $zMaxPlot = $pos->z + $plotSize; + if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; + if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + $selection->setPosition(1, $plotBeginPos); + $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); + $selection->setPosition(2, $vec2); + $commonShape = CommonShape::fromSelection($selection); + //$commonShape = $commonShape->async(); // do not use async because WorldStyler async is very broken right now + $commonShape->paste($level, $vec2, true, function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); + }); + $styler->removeSelection(99997); + foreach((yield $this->generatePlotChunks($plotTo)) as [$chunkX, $chunkZ, $chunk]){ + $level->setChunk($chunkX, $chunkZ, $chunk); + } + return true; + }, + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param SinglePlot $plot + * @param int $maxBlocksPerTick + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function clearPlot(SinglePlot $plot, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::f2c( + function() use ($plot, $maxBlocksPerTick) : \Generator{ + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($level === null){ + return false; + } + foreach($level->getEntities() as $entity){ + if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition())){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->generatePlayerTeleport($entity, $plot, false); + } + } + } + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if($this->plugin->getConfig()->get("FastClearing", false) === true && $styler instanceof WorldStyler){ + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plot, true); + $xMax = $plotBeginPos->x + $plotSize; + $zMax = $plotBeginPos->z + $plotSize; + foreach(yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot){ + $xplot = (yield $this->generatePlotPosition($mergedPlot, false))->x; + $zplot = (yield $this->generatePlotPosition($mergedPlot, false))->z; + $xMaxPlot = (int) ($xplot + $plotSize); + $zMaxPlot = (int) ($zplot + $plotSize); + if($plotBeginPos->x > $xplot) $plotBeginPos->x = $xplot; + if($plotBeginPos->z > $zplot) $plotBeginPos->z = $zplot; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + // Above ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = $plotLevel->groundHeight + 1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, World::Y_MAX, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), VanillaBlocks::AIR()->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Ground Surface + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = $plotLevel->groundHeight; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFloorBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = 1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight - 1, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Bottom of world + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = 0; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, 0, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + foreach($this->plugin->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ + $plotBeginPos->getWorld()->setChunk($chunkX, $chunkZ, $chunk); + } + $this->plugin->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this->plugin, $plot), 1); + return true; + } + $this->plugin->getScheduler()->scheduleTask(new ClearPlotTask($this->plugin, $plot, $maxBlocksPerTick)); + return true; + }, + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param SinglePlot $plot + * @param Block $plotFillBlock + * @param int $maxBlocksPerTick + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function fillPlot(SinglePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::f2c( + function() use ($plot, $plotFillBlock, $maxBlocksPerTick){ + foreach($this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)->getEntities() as $entity){ + if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition()) && $entity->getPosition()->y <= $this->getLevelSettings($plot->levelName)->groundHeight){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->generatePlayerTeleport($entity, $plot, false); + } + } + } + if($this->plugin->getConfig()->get("FastFilling", false) === true){ + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if(!$styler instanceof WorldStyler){ + return false; + } + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plot, false); + // Ground + $selection = $styler->getSelection(99998); + $plotBeginPos->y = 1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, $plotLevel->groundHeight, $plotBeginPos->z + $plotSize)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Bottom of world + $selection = $styler->getSelection(99998); + $plotBeginPos->y = 0; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, 0, $plotBeginPos->z + $plotSize)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + foreach((yield $this->generatePlotChunks($plot)) as [$chunkX, $chunkZ, $chunk]){ + $plotBeginPos->getWorld()?->setChunk($chunkX, $chunkZ, $chunk); + } + return true; + } + $this->plugin->getScheduler()->scheduleTask(new FillPlotTask($this->plugin, $plot, $plotFillBlock, $maxBlocksPerTick)); + return true; + }, + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param SinglePlot $plot + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function disposePlot(SinglePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->dataProvider->deletePlot($plot), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param SinglePlot $plot + * @param int $maxBlocksPerTick + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + * + * @noinspection PhpVoidFunctionResultUsedInspection + */ + public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ + $this->disposePlot( + $plot, + fn(bool $success) => $success && $this->clearPlot( + $plot, + $maxBlocksPerTick, + $onComplete, + $onFail + ), + $onFail + ); + } + + /** + * @param SinglePlot $plot + * @param Biome $biome + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function setPlotBiome(SinglePlot $plot, Biome $biome, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotBiome($plot, $biome), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ + $failed = false; + foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ + $merged->biome = $plot->biome; + if(!yield $this->dataProvider->savePlot($merged)) + $failed = true; + } + $plotLevel = $this->getLevelSettings($plot->levelName); + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($level === null){ + return false; + } + foreach((yield $this->generatePlotChunks($plot)) as [$chunkX, $chunkZ, $chunk]){ + for($x = 0; $x < 16; ++$x){ + for($z = 0; $z < 16; ++$z){ + $pos = new Position(($chunkX << 4) + $x, $plotLevel->groundHeight, ($chunkZ << 4) + $z, $level); + $chunkPlot = $this->getPlotFast($pos->x, $pos->z, $plotLevel); + if($chunkPlot instanceof SinglePlot and $chunkPlot->isSame($plot)){ + $chunk->setBiomeId($x, $z, $biome->getId()); + } + } + } + $level->setChunk($chunkX, $chunkZ, $chunk); + } + return !$failed; + } + + /** + * @param SinglePlot $plot + * @param callable|null $onComplete + * @phpstan-param (callable(array): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlotChunks(SinglePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotChunks($plot), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + private function generatePlotChunks(SinglePlot $plot) : \Generator{ + $plotLevel = $this->getLevelSettings($plot->levelName); + if($plotLevel === null){ + return []; + } + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($level === null){ + return []; + } + $plotSize = $plotLevel->plotSize; + $chunks = []; + foreach((yield $this->dataProvider->getMergedPlots($plot)) as $mergedPlot){ + $pos = yield $this->generatePlotPosition($mergedPlot, false); + $xMax = ($pos->x + $plotSize) >> 4; + $zMax = ($pos->z + $plotSize) >> 4; + for($x = $pos->x >> 4; $x <= $xMax; $x++){ + for($z = $pos->z >> 4; $z <= $zMax; $z++){ + $chunks[] = [$x, $z, $level->getChunk($x, $z)]; + } + } + } + return $chunks; + } + + public function onDisable() : void { + $this->dataProvider->close(); + } +} \ No newline at end of file diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 4d530d6c..45e2436b 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -2,35 +2,23 @@ declare(strict_types=1); namespace MyPlot; -use jasonwynn10\MyPlot\utils\AsyncVariants; -use muqsit\worldstyler\Selection; -use muqsit\worldstyler\shapes\CommonShape; -use muqsit\worldstyler\shapes\Cuboid; use muqsit\worldstyler\WorldStyler; use MyPlot\events\MyPlotClearEvent; use MyPlot\events\MyPlotCloneEvent; use MyPlot\events\MyPlotDisposeEvent; use MyPlot\events\MyPlotFillEvent; use MyPlot\events\MyPlotGenerationEvent; -use MyPlot\events\MyPlotMergeEvent; use MyPlot\events\MyPlotResetEvent; use MyPlot\events\MyPlotSettingEvent; use MyPlot\events\MyPlotTeleportEvent; -use MyPlot\provider\DataProvider; +use MyPlot\plot\SinglePlot; use MyPlot\provider\EconomyProvider; use MyPlot\provider\EconomySProvider; -use MyPlot\task\ClearBorderTask; -use MyPlot\task\ClearPlotTask; -use MyPlot\task\FillPlotTask; -use MyPlot\task\RoadFillTask; use onebone\economyapi\EconomyAPI; use pocketmine\block\Block; -use pocketmine\block\VanillaBlocks; use pocketmine\data\bedrock\BiomeIds; -use pocketmine\event\world\WorldLoadEvent; use pocketmine\lang\Language; use pocketmine\math\AxisAlignedBB; -use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\permission\DefaultPermissions; use pocketmine\permission\Permission; @@ -40,7 +28,6 @@ use pocketmine\plugin\PluginBase; use pocketmine\promise\Promise; use pocketmine\promise\PromiseResolver; -use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Config; use pocketmine\utils\TextFormat as TF; use pocketmine\world\biome\Biome; @@ -48,18 +35,14 @@ use pocketmine\world\format\Chunk; use pocketmine\world\generator\GeneratorManager; use pocketmine\world\Position; -use pocketmine\world\World; use pocketmine\world\WorldCreationOptions; -use SOFe\AwaitGenerator\Await; class MyPlot extends PluginBase { private static MyPlot $instance; - /** @var PlotLevelSettings[] $levels */ - private array $levels = []; - private DataProvider $dataProvider; - private ?EconomyProvider $economyProvider = null; - private Language $Language; + private Language $language; + private ?EconomyProvider $economyProvider; + private InternalAPI $internalAPI; public static function getInstance() : self { return self::$instance; @@ -73,7 +56,7 @@ public static function getInstance() : self { * @return Language */ public function getLanguage() : Language { - return $this->Language; + return $this->language; } /** @@ -87,17 +70,6 @@ public function getFallBackLang() : Language { return new Language(Language::FALLBACK_LANGUAGE, $this->getFile() . "resources/"); } - /** - * Returns the DataProvider that is being used - * - * @api - * - * @return DataProvider - */ - public function getProvider() : DataProvider { - return $this->dataProvider; - } - /** * Returns the EconomyProvider that is being used * @@ -121,29 +93,52 @@ public function setEconomyProvider(?EconomyProvider $provider) : void { $this->getConfig()->set("UseEconomy", false); $this->getLogger()->info("Economy mode disabled!"); }else{ - $this->getLogger()->info("A custom economy provider has been registered. Economy mode now enabled!"); $this->getConfig()->set("UseEconomy", true); - $this->economyProvider = $provider; + $this->getLogger()->info("A custom economy provider has been registered. Economy mode now enabled!"); } + $this->economyProvider = $provider; + } + + /** + * Returns the PlotLevelSettings of all the loaded Worlds + * + * @api + * + * @return PlotLevelSettings[] + */ + public function getPlotLevels() : array { + return $this->internalAPI->getAllLevelSettings(); } /** - * Returns a PlotLevelSettings object which contains all the settings of a level + * Returns a PlotLevelSettings object which contains all the settings of a world * * @api * * @param string $levelName * - * @return PlotLevelSettings + * @return PlotLevelSettings|null */ - public function getLevelSettings(string $levelName) : PlotLevelSettings { - if(!isset($this->levels[$levelName])) - throw new AssumptionFailedError("Provided level name is not a MyPlot level"); - return $this->levels[$levelName]; + public function getLevelSettings(string $levelName) : ?PlotLevelSettings { + return $this->internalAPI->getLevelSettings($levelName); } /** - * Checks if a plot level is loaded + * Registers a new PlotLevelSettings object to the loaded worlds list + * + * @api + * + * @param string $levelName + * @param PlotLevelSettings $settings + * + * @return void + */ + public function addLevelSettings(string $levelName, PlotLevelSettings $settings) : void { + $this->internalAPI->addLevelSettings($levelName, $settings); + } + + /** + * Unregisters a PlotLevelSettings object from the loaded worlds list * * @api * @@ -151,10 +146,11 @@ public function getLevelSettings(string $levelName) : PlotLevelSettings { * * @return bool */ - public function isLevelLoaded(string $levelName) : bool { - return isset($this->levels[$levelName]); + public function unloadLevelSettings(string $levelName) : bool { + return $this->internalAPI->unloadLevelSettings($levelName); } + /** * Generate a new plot level with optional settings * @@ -192,16 +188,16 @@ public function generateLevel(string $levelName, string $generator = MyPlotGener * * @api * - * @param Plot $plot + * @param SinglePlot $plot * * @return Promise - * @phpstan-return Promise + * @phpstan-return Promise */ - public function savePlot(Plot $plot) : Promise{ + public function savePlot(SinglePlot $plot) : Promise{ $resolver = new PromiseResolver(); - Await::g2c( - $this->dataProvider->savePlot($plot), - fn() => $resolver->resolve($plot), + $this->internalAPI->savePlot( + $plot, + fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); @@ -216,12 +212,13 @@ public function savePlot(Plot $plot) : Promise{ * @param string|null $levelName * * @return Promise - * @phpstan-return Promise> + * @phpstan-return Promise> */ public function getPlotsOfPlayer(string $username, ?string $levelName = null) : Promise{ $resolver = new PromiseResolver(); - Await::g2c( - $this->dataProvider->getPlotsByOwner($username, $levelName), + $this->internalAPI->getPlotsOfPlayer( + $username, + $levelName, fn(array $plots) => $resolver->resolve($plots), fn(\Throwable $e) => $resolver->reject() ); @@ -237,13 +234,14 @@ public function getPlotsOfPlayer(string $username, ?string $levelName = null) : * @param int $limitXZ * * @return Promise - * @phpstan-return Promise + * @phpstan-return Promise */ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : Promise{ $resolver = new PromiseResolver(); - Await::g2c( - $this->dataProvider->getNextFreePlot($levelName, $limitXZ), - fn(?Plot $plot) => $resolver->resolve($plot), + $this->internalAPI->getNextFreePlot( + $levelName, + $limitXZ, + fn(?SinglePlot $plot) => $resolver->resolve($plot), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); @@ -257,113 +255,34 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : Promise{ * @param Position $position * * @return Promise - * @phpstan-return Promise + * @phpstan-return Promise */ public function getPlotByPosition(Position $position) : Promise{ $resolver = new PromiseResolver(); - Await::f2c( - function() use ($position){ - $x = $position->x; - $z = $position->z; - $levelName = $position->getWorld()->getFolderName(); - if(!$this->isLevelLoaded($levelName)) - return null; - $plotLevel = $this->getLevelSettings($levelName); - - $plot = $this->getPlotFast($x, $z, $plotLevel); - if($plot instanceof Plot) - return yield $this->dataProvider->getMergeOrigin($plot); - - $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); - if(!$basePlot->isMerged()) - return null; - - // no plot found at current location yet, so search cardinal directions - $plotN = $basePlot->getSide(Facing::NORTH); - if($plotN->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotN); - - $plotS = $basePlot->getSide(Facing::SOUTH); - if($plotS->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotS); - - $plotE = $basePlot->getSide(Facing::EAST); - if($plotE->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotE); - - $plotW = $basePlot->getSide(Facing::WEST); - if($plotW->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotW); - - return null; - }, - fn(?Plot $plot) => $resolver->resolve($plot), + $this->internalAPI->getPlotByPosition( + $position, + fn(?SinglePlot $plot) => $resolver->resolve($plot), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); } - /** - * @param float $x - * @param float $z - * @param PlotLevelSettings $plotLevel - * - * @return Plot|null - */ - public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?Plot{ - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0) { - $difX = $x % $totalSize; - $x = (int) floor($x / $totalSize); - }else{ - $difX = abs(($x - $plotSize + 1) % $totalSize); - $x = (int) ceil(($x - $plotSize + 1) / $totalSize); - } - if($z >= 0) { - $difZ = $z % $totalSize; - $z = (int) floor($z / $totalSize); - }else{ - $difZ = abs(($z - $plotSize + 1) % $totalSize); - $z = (int) ceil(($z - $plotSize + 1) / $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)) - return null; - - return new Plot($plotLevel->name, $x, $z); - } - /** * Get the beginning position of a plot * * @api * - * @param Plot $plot - * @param bool $mergeOrigin + * @param SinglePlot $plot + * @param bool $mergeOrigin * * @return Promise * @phpstan-return Promise */ - public function getPlotPosition(Plot $plot, bool $mergeOrigin = true) : Promise{ + public function getPlotPosition(SinglePlot $plot, bool $mergeOrigin = true) : Promise{ $resolver = new PromiseResolver(); - Await::f2c( - function() use ($plot, $mergeOrigin){ - $plotLevel = $this->getLevelSettings($plot->levelName); - $origin = yield $this->dataProvider->getMergeOrigin($plot); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($mergeOrigin){ - $x = $totalSize * $origin->X; - $z = $totalSize * $origin->Z; - }else{ - $x = $totalSize * $plot->X; - $z = $totalSize * $plot->Z; - } - $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - return new Position($x, $plotLevel->groundHeight, $z, $level); - }, + $this->internalAPI->getPlotPosition( + $plot, + $mergeOrigin, fn(Position $position) => $resolver->resolve($position), fn(\Throwable $e) => $resolver->reject() ); @@ -382,70 +301,9 @@ function() use ($plot, $mergeOrigin){ */ public function isPositionBorderingPlot(Position $position) : Promise{ $resolver = new PromiseResolver(); - Await::f2c( - function() use ($position){ - if(!$position->isValid()) - return false; - foreach(Facing::HORIZONTAL as $i){ - $pos = $position->getSide($i); - $x = $pos->x; - $z = $pos->z; - $levelName = $pos->getWorld()->getFolderName(); - - if(!$this->isLevelLoaded($levelName)) - return false; - - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0){ - $difX = $x % $totalSize; - }else{ - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0){ - $difZ = $z % $totalSize; - }else{ - $difZ = abs(($z - $plotSize + 1) % $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ - continue; - } - return true; - } - foreach(Facing::HORIZONTAL as $i){ - foreach(Facing::HORIZONTAL as $n){ - if($i === $n or Facing::opposite($i) === $n) - continue; - $pos = $position->getSide($i)->getSide($n); - $x = $pos->x; - $z = $pos->z; - $levelName = $pos->getWorld()->getFolderName(); - - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0){ - $difX = $x % $totalSize; - }else{ - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0){ - $difZ = $z % $totalSize; - }else{ - $difZ = abs(($z - $plotSize + 1) % $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ - continue; - } - return true; - } - } - return false; - }, - fn(bool $isBordering) => $resolver->resolve($isBordering), + $this->internalAPI->isPositionBorderingPlot( + $position, + fn(bool $bordering) => $resolver->resolve($bordering), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); @@ -459,69 +317,13 @@ function() use ($position){ * @param Position $position * * @return Promise - * @phpstan-return Promise + * @phpstan-return Promise */ public function getPlotBorderingPosition(Position $position) : Promise{ $resolver = new PromiseResolver(); - Await::f2c( - function() use ($position){ - if(!$position->isValid()) - return null; - foreach(Facing::HORIZONTAL as $i){ - $pos = $position->getSide($i); - $x = $pos->x; - $z = $pos->z; - $levelName = $pos->getWorld()->getFolderName(); - - if(!$this->isLevelLoaded($levelName)) - return null; - - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0){ - $X = (int) floor($x / $totalSize); - $difX = $x % $totalSize; - }else{ - $X = (int) ceil(($x - $plotSize + 1) / $totalSize); - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0){ - $Z = (int) floor($z / $totalSize); - $difZ = $z % $totalSize; - }else{ - $Z = (int) ceil(($z - $plotSize + 1) / $totalSize); - $difZ = abs(($z - $plotSize + 1) % $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ - $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); - if(!$basePlot->isMerged()) - return null; - - // no plot found at current location yet, so search cardinal directions - $plotN = $basePlot->getSide(Facing::NORTH); - if($plotN->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotN); - - $plotS = $basePlot->getSide(Facing::SOUTH); - if($plotS->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotS); - - $plotE = $basePlot->getSide(Facing::EAST); - if($plotE->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotE); - - $plotW = $basePlot->getSide(Facing::WEST); - if($plotW->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotW); - continue; - } - return yield $this->dataProvider->getPlot($levelName, $X, $Z); - } - return null; - }, - fn(?Plot $plot) => $resolver->resolve($plot), + $this->internalAPI->getPlotBorderingPosition( + $position, + fn(SinglePlot $plot) => $resolver->resolve($plot), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); @@ -532,41 +334,16 @@ function() use ($position){ * * @api * - * @param Plot $plot + * @param SinglePlot $plot * * @return Promise * @phpstan-return Promise */ - public function getPlotBB(Plot $plot) : Promise{ + public function getPlotBB(SinglePlot $plot) : Promise{ $resolver = new PromiseResolver(); - Await::f2c( - function() use ($plot){ - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize - 1; - $pos = yield AsyncVariants::getPlotPosition($plot, false); - $xMax = (int) ($pos->x + $plotSize); - $zMax = (int) ($pos->z + $plotSize); - foreach((yield $this->dataProvider->getMergedPlots($plot)) as $mergedPlot){ - $xplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->x; - $zplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->z; - $xMaxPlot = (int) ($xplot + $plotSize); - $zMaxPlot = (int) ($zplot + $plotSize); - if($pos->x > $xplot) $pos->x = $xplot; - if($pos->z > $zplot) $pos->z = $zplot; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - - return new AxisAlignedBB( - min($pos->x, $xMax), - $pos->getWorld()->getMinY(), - min($pos->z, $zMax), - max($pos->x, $xMax), - $pos->getWorld()->getMaxY(), - max($pos->z, $zMax) - ); - }, - fn(AxisAlignedBB $aabb) => $resolver->resolve($aabb), + $this->internalAPI->getPlotBB( + $plot, + fn(AxisAlignedBB $bb) => $resolver->resolve($bb), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); @@ -577,88 +354,20 @@ function() use ($plot){ * * @api * - * @param Plot $plot The plot that is to be expanded - * @param int $direction The Vector3 direction value to expand towards - * @param int $maxBlocksPerTick + * @param SinglePlot $plot The plot that is to be expanded + * @param int $direction The Vector3 direction value to expand towards + * @param int $maxBlocksPerTick * * @return Promise * @phpstan-return Promise */ - public function mergePlots(Plot $plot, int $direction, int $maxBlocksPerTick = 256) : Promise{ + public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTick = 256) : Promise{ $resolver = new PromiseResolver(); - Await::f2c( - function() use ($plot, $direction, $maxBlocksPerTick){ - if(!$this->isLevelLoaded($plot->levelName)) - return false; - /** @var Plot[][] $toMerge */ - $toMerge = []; - $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); - $newPlot = $plot->getSide($direction); - $alreadyMerged = false; - foreach($mergedPlots as $mergedPlot){ - if($mergedPlot->isSame($newPlot)){ - $alreadyMerged = true; - } - } - if($alreadyMerged === false and $newPlot->isMerged()){ - $this->getLogger()->debug("Failed to merge due to plot origin mismatch"); - return false; - } - $toMerge[] = [$plot, $newPlot]; - - foreach($mergedPlots as $mergedPlot) { - $newPlot = $mergedPlot->getSide($direction); - $alreadyMerged = false; - foreach($mergedPlots as $mergedPlot2){ - if($mergedPlot2->isSame($newPlot)){ - $alreadyMerged = true; - } - } - if($alreadyMerged === false and $newPlot->isMerged()){ - $this->getLogger()->debug("Failed to merge due to plot origin mismatch"); - return false; - } - $toMerge[] = [$mergedPlot, $newPlot]; - } - /** @var Plot[][] $toFill */ - $toFill = []; - foreach($toMerge as $pair) { - foreach($toMerge as $pair2) { - foreach(Facing::HORIZONTAL as $i) { - if($pair[1]->getSide($i)->isSame($pair2[1])) { - $toFill[] = [$pair[1], $pair2[1]]; - } - } - } - } - $ev = new MyPlotMergeEvent(yield $this->dataProvider->getMergeOrigin($plot), $toMerge); - $ev->call(); - if($ev->isCancelled()) { - return false; - } - foreach($toMerge as $pair) { - if($pair[1]->owner === "") { - $this->getLogger()->debug("Failed to merge due to plot not claimed"); - return false; - }elseif($plot->owner !== $pair[1]->owner) { - $this->getLogger()->debug("Failed to merge due to owner mismatch"); - return false; - } - } - - // TODO: WorldStyler clearing - - foreach($toMerge as $pair) - $this->getScheduler()->scheduleTask(new RoadFillTask($this, $pair[0], $pair[1], false, -1, $maxBlocksPerTick)); - - foreach($toFill as $pair) - $this->getScheduler()->scheduleTask(new RoadFillTask($this, $pair[0], $pair[1], true, $direction, $maxBlocksPerTick)); - - return yield $this->dataProvider->mergePlots(yield $this->dataProvider->getMergeOrigin($plot), ...array_map(function(array $val) : Plot{ - return $val[1]; - }, $toMerge)); - }, - fn(bool $result) => $resolver->resolve($result), + $this->internalAPI->mergePlots( + $plot, + $direction, + $maxBlocksPerTick, + fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); @@ -669,70 +378,29 @@ function() use ($plot, $direction, $maxBlocksPerTick){ * * @api * - * @param Player $player - * @param Plot $plot - * @param bool $center - * - * @return bool - */ - public function teleportPlayerToPlot(Player $player, Plot $plot, bool $center = false) : bool { - $ev = new MyPlotTeleportEvent($plot, $player, $center); - $ev->call(); - if($ev->isCancelled()) { - return false; - } - if($plot->isMerged()){ - return $this->teleportPlayerToMerge($player, $plot, $center); - } - if($center) - return $this->teleportMiddle($player, $plot); - $plotLevel = $this->getLevelSettings($plot->levelName); - $pos = $this->getPlotPosition($plot); - $pos->x += floor($plotLevel->plotSize / 2); - $pos->y += 1.5; - $pos->z -= 1; - return $player->teleport($pos); - } - - /** - * Teleport a player to a Merge - * - * @api + * @param Player $player + * @param SinglePlot $plot + * @param bool $center * - * @param Player $player - * @param Plot $plot - * @param bool $center - * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function teleportPlayerToMerge(Player $player, Plot $plot, bool $center = false) : bool { + public function teleportPlayerToPlot(Player $player, SinglePlot $plot, bool $center = false) : Promise { + $resolver = new PromiseResolver(); $ev = new MyPlotTeleportEvent($plot, $player, $center); $ev->call(); - if ($ev->isCancelled()) { - return false; - } - if(!$plot->isMerged()){ - $this->teleportPlayerToPlot($player, $plot, $center); + if($ev->isCancelled()){ + $resolver->resolve(false); + return $resolver->getPromise(); } - if ($center) - return $this->teleportMiddle($player, $plot); - $plotLevel = $this->getLevelSettings($plot->levelName); - $mergedPlots = $this->getProvider()->getMergedPlots($plot); - $minx = $this->getPlotPosition(array_reduce($mergedPlots, function(Plot $a, Plot $b) : Plot { - return $this->getPlotPosition($a, false)->x < $this->getPlotPosition($b, false)->x ? $a : $b; - }, $mergedPlots[0]), false)->x; - $maxx = $this->getPlotPosition(array_reduce($mergedPlots, function(Plot $a, Plot $b) : Plot { - return $this->getPlotPosition($a, false)->x > $this->getPlotPosition($b, false)->x ? $a : $b; - }, $mergedPlots[0]), false)->x + $plotLevel->plotSize; - $minz = $this->getPlotPosition(array_reduce($mergedPlots, function(Plot $a, Plot $b) : Plot { - return $this->getPlotPosition($a, false)->z < $this->getPlotPosition($b, false)->z ? $a : $b; - }, $mergedPlots[0]), false)->z; - - $pos = new Position($minx,$plotLevel->groundHeight, $minz, $this->getServer()->getWorldManager()->getWorldByName($plot->levelName)); - $pos->x = floor(($minx + $maxx) / 2); - $pos->y += 1.5; - $pos->z -= 1; - return $player->teleport($pos); + $this->internalAPI->teleportPlayerToPlot( + $player, + $plot, + $center, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -740,44 +408,29 @@ public function teleportPlayerToMerge(Player $player, Plot $plot, bool $center = * * @api * - * @param Plot $plot - * @param string $claimer - * @param string $plotName + * @param SinglePlot $plot + * @param string $claimer + * @param string $plotName * * @return Promise * @phpstan-return Promise */ - public function claimPlot(Plot $plot, string $claimer, string $plotName = "") : Promise{ - $resolver = new PromiseResolver(); + public function claimPlot(SinglePlot $plot, string $claimer, string $plotName = "") : Promise{ $newPlot = clone $plot; $newPlot->owner = $claimer; + $newPlot->helpers = []; + $newPlot->denied = []; + if($plotName !== "") + $newPlot->name = $plotName; $newPlot->price = 0.0; $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); if($ev->isCancelled()){ + $resolver = new PromiseResolver(); $resolver->resolve(false); return $resolver->getPromise(); } - $plot = $ev->getPlot(); - Await::f2c( - function() use ($plot, $claimer, $plotName) : \Generator{ - $failed = false; - foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged) { - $merged->owner = $claimer; - $merged->price = 0.0; - if($plotName !== "") - $merged->name = $plotName; - $saved = yield $this->dataProvider->savePlot($plot); - if(!$saved) { - $failed = true; - } - } - return !$failed; - }, - fn(bool $succeeded) => $resolver->resolve($succeeded), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + return $this->savePlot($ev->getPlot()); } /** @@ -785,13 +438,13 @@ function() use ($plot, $claimer, $plotName) : \Generator{ * * @api * - * @param Plot $plot - * @param string $newName + * @param SinglePlot $plot + * @param string $newName * * @return Promise * @phpstan-return Promise */ - public function renamePlot(Plot $plot, string $newName = "") : Promise{ + public function renamePlot(SinglePlot $plot, string $newName = "") : Promise{ $newPlot = clone $plot; $newPlot->name = $newName; $ev = new MyPlotSettingEvent($plot, $newPlot); @@ -809,102 +462,35 @@ public function renamePlot(Plot $plot, string $newName = "") : Promise{ * * @api * - * @param Plot $plotFrom - * @param Plot $plotTo + * @param SinglePlot $plotFrom + * @param SinglePlot $plotTo * * @return Promise * @phpstan-return Promise */ - public function clonePlot(Plot $plotFrom, Plot $plotTo) : Promise { + public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : Promise { $resolver = new PromiseResolver(); $styler = $this->getServer()->getPluginManager()->getPlugin("WorldStyler"); if(!$styler instanceof WorldStyler) { $resolver->resolve(false); return $resolver->getPromise(); } - if(!$this->isLevelLoaded($plotFrom->levelName) or !$this->isLevelLoaded($plotTo->levelName)) { + $ev = new MyPlotCloneEvent($plotFrom, $plotTo); + $ev->call(); + if($ev->isCancelled()) { $resolver->resolve(false); return $resolver->getPromise(); } - Await::f2c( - function() use ($plotFrom, $plotTo, $styler) { - $world = $this->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); - $aabb = yield $this->getPlotBB($plotTo); - foreach($world->getEntities() as $entity) { - if($aabb->isVectorInXZ($entity->getPosition())) { - if($entity instanceof Player){ - $this->teleportPlayerToPlot($entity, $plotTo); - } - } - } - $ev = new MyPlotCloneEvent($plotFrom, $plotTo); - $ev->call(); - if($ev->isCancelled()) { - return false; - } - $plotFrom = $ev->getPlot(); - $plotTo = $ev->getClonePlot(); - if(!$this->isLevelLoaded($plotFrom->levelName) or !$this->isLevelLoaded($plotTo->levelName)){ - return false; - } - $plotLevel = $this->getLevelSettings($plotFrom->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield AsyncVariants::getPlotPosition($plotFrom); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = (int) ($plotBeginPos->x + $plotSize); - $zMax = (int) ($plotBeginPos->z + $plotSize); - foreach(yield $this->dataProvider->getMergedPlots($plotFrom) as $mergedPlot){ - $pos = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->subtract(1, 0, 1); - $xMaxPlot = (int) ($pos->x + $plotSize); - $zMaxPlot = (int) ($pos->z + $plotSize); - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - $selection = $styler->getSelection(99997) ?? new Selection(99997); - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); // do not use async because WorldStyler async is very broken right now - $cuboid->copy($level, $vec2, function(float $time, int $changed) : void{ - $this->getLogger()->debug(TF::GREEN . 'Copied ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's to the MyPlot clipboard.'); - }); - - $plotLevel = $this->getLevelSettings($plotTo->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield AsyncVariants::getPlotPosition($plotTo); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = (int) ($plotBeginPos->x + $plotSize); - $zMax = (int) ($plotBeginPos->z + $plotSize); - foreach(yield $this->dataProvider->getMergedPlots($plotTo) as $mergedPlot){ - $pos = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->subtract(1, 0, 1); - $xMaxPlot = (int) ($pos->x + $plotSize); - $zMaxPlot = (int) ($pos->z + $plotSize); - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); - $commonShape = CommonShape::fromSelection($selection); - //$commonShape = $commonShape->async(); // do not use async because WorldStyler async is very broken right now - $commonShape->paste($level, $vec2, true, function (float $time, int $changed) : void { - $this->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); - }); - $styler->removeSelection(99997); - foreach($this->getPlotChunks($plotTo) as [$chunkX, $chunkZ, $chunk]) { - $level->setChunk($chunkX, $chunkZ, $chunk); - } - return true; - }, + $plotFrom = $ev->getPlot(); + $plotTo = $ev->getClonePlot(); + if($this->internalAPI->getLevelSettings($plotFrom->levelName) === null or $this->internalAPI->getLevelSettings($plotTo->levelName) === null) { + $resolver->resolve(false); + return $resolver->getPromise(); + } + $this->internalAPI->clonePlot( + $plotFrom, + $plotTo, + $styler, fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); @@ -916,13 +502,13 @@ function() use ($plotFrom, $plotTo, $styler) { * * @api * - * @param Plot $plot - * @param int $maxBlocksPerTick + * @param SinglePlot $plot + * @param int $maxBlocksPerTick * * @return Promise * @phpstan-return Promise */ - public function clearPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { + public function clearPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promise { $resolver = new PromiseResolver(); $ev = new MyPlotClearEvent($plot, $maxBlocksPerTick); $ev->call(); @@ -931,97 +517,14 @@ public function clearPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { return $resolver->getPromise(); } $plot = $ev->getPlot(); - if(!$this->isLevelLoaded($plot->levelName)) { + if($this->internalAPI->getLevelSettings($plot->levelName) === null) { $resolver->resolve(false); return $resolver->getPromise(); } $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); - $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null){ - $resolver->resolve(false); - return $resolver->getPromise(); - } - Await::f2c( - function() use ($plot, $maxBlocksPerTick, $level) : \Generator { - foreach($level->getEntities() as $entity) { - if((yield $this->getPlotBB($plot))->isVectorInXZ($entity->getPosition())) { - if(!$entity instanceof Player) { - $entity->flagForDespawn(); - }else{ - $this->teleportPlayerToPlot($entity, $plot); - } - } - } - $styler = $this->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if($this->getConfig()->get("FastClearing", false) === true && $styler instanceof WorldStyler) { - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize-1; - $plotBeginPos = yield AsyncVariants::getPlotPosition($plot); - $xMax = (int)($plotBeginPos->x + $plotSize); - $zMax = (int)($plotBeginPos->z + $plotSize); - foreach(yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot){ - $xplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->x; - $zplot = (yield AsyncVariants::getPlotPosition($mergedPlot, false))->z; - $xMaxPlot = (int) ($xplot + $plotSize); - $zMaxPlot = (int) ($zplot + $plotSize); - if($plotBeginPos->x > $xplot) $plotBeginPos->x = $xplot; - if($plotBeginPos->z > $zplot) $plotBeginPos->z = $zplot; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - // Above ground - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight+1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, World::Y_MAX, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), VanillaBlocks::AIR()->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Ground Surface - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFloorBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Ground - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight-1, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFillBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Bottom of world - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 0; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, 0, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]) { - $plotBeginPos->getWorld()->setChunk($chunkX, $chunkZ, $chunk); - } - $this->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this, $plot), 1); - return true; - } - $this->getScheduler()->scheduleTask(new ClearPlotTask($this, $plot, $maxBlocksPerTick)); - return true; - }, + $this->internalAPI->clearPlot( + $plot, + $maxBlocksPerTick, fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); @@ -1033,69 +536,35 @@ function() use ($plot, $maxBlocksPerTick, $level) : \Generator { * * @api * - * @param Plot $plot - * @param Block $plotFillBlock - * @param int $maxBlocksPerTick + * @param SinglePlot $plot + * @param Block $plotFillBlock + * @param int $maxBlocksPerTick * - * @return bool + * @return Promise + * @phpstan-return Promise */ - public function fillPlot(Plot $plot, Block $plotFillBlock, int $maxBlocksPerTick = 256) : bool { + public function fillPlot(SinglePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick = 256) : Promise { + $resolver = new PromiseResolver(); $ev = new MyPlotFillEvent($plot, $maxBlocksPerTick); $ev->call(); if($ev->isCancelled()) { - return false; + $resolver->resolve(false); + return $resolver->getPromise(); } $plot = $ev->getPlot(); - if(!$this->isLevelLoaded($plot->levelName)) { - return false; + if($this->internalAPI->getLevelSettings($plot->levelName) === null) { + $resolver->resolve(false); + return $resolver->getPromise(); } $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); - foreach($this->getServer()->getWorldManager()->getWorldByName($plot->levelName)->getEntities() as $entity) { - if($this->getPlotBB($plot)->isVectorInXZ($entity->getPosition()) && $entity->getPosition()->y <= $this->getLevelSettings($plot->levelName)->groundHeight) { - if(!$entity instanceof Player) { - $entity->flagForDespawn(); - }else{ - $this->teleportPlayerToPlot($entity, $plot); - } - } - } - if($this->getConfig()->get("FastFilling", false) === true) { - $styler = $this->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if(!$styler instanceof WorldStyler) { - return false; - } - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize-1; - $plotBeginPos = $this->getPlotPosition($plot); - // Ground - $selection = $styler->getSelection(99998); - $plotBeginPos->y = 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, $plotLevel->groundHeight, $plotBeginPos->z + $plotSize)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotFillBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Bottom of world - $selection = $styler->getSelection(99998); - $plotBeginPos->y = 0; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, 0, $plotBeginPos->z + $plotSize)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function (float $time, int $changed) : void { - $this->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]) { - $plotBeginPos->getWorld()?->setChunk($chunkX, $chunkZ, $chunk); - } - return true; - } - $this->getScheduler()->scheduleTask(new FillPlotTask($this, $plot, $plotFillBlock, $maxBlocksPerTick)); - return true; + $this->internalAPI->fillPlot( + $plot, + $plotFillBlock, + $maxBlocksPerTick, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -1103,12 +572,12 @@ public function fillPlot(Plot $plot, Block $plotFillBlock, int $maxBlocksPerTick * * @api * - * @param Plot $plot + * @param SinglePlot $plot * * @return Promise * @phpstan-return Promise */ - public function disposePlot(Plot $plot) : Promise { + public function disposePlot(SinglePlot $plot) : Promise { $resolver = new PromiseResolver(); $ev = new MyPlotDisposeEvent($plot); $ev->call(); @@ -1116,8 +585,9 @@ public function disposePlot(Plot $plot) : Promise { $resolver->resolve(false); return $resolver->getPromise(); } - Await::g2c( - $this->dataProvider->deletePlot($plot), + $plot = $ev->getPlot(); + $this->internalAPI->disposePlot( + $plot, fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); @@ -1129,15 +599,13 @@ public function disposePlot(Plot $plot) : Promise { * * @api * - * @noinspection PhpVoidFunctionResultUsedInspection - * - * @param Plot $plot - * @param int $maxBlocksPerTick + * @param SinglePlot $plot + * @param int $maxBlocksPerTick * * @return Promise * @phpstan-return Promise */ - public function resetPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { + public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promise { $resolver = new PromiseResolver(); $ev = new MyPlotResetEvent($plot); $ev->call(); @@ -1145,14 +613,11 @@ public function resetPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { $resolver->resolve(false); return $resolver->getPromise(); } - Await::g2c( - $this->dataProvider->deletePlot($plot), - fn(bool $success) => - $success && - $this->clearPlot($plot, $maxBlocksPerTick)->onCompletion( - fn(bool $success) => $resolver->resolve($success), - fn() => $resolver->reject() - ), + $plot = $ev->getPlot(); + $this->internalAPI->resetPlot( + $plot, + $maxBlocksPerTick, + fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); return $resolver->getPromise(); @@ -1163,13 +628,13 @@ public function resetPlot(Plot $plot, int $maxBlocksPerTick = 256) : Promise { * * @api * - * @param Plot $plot - * @param Biome $biome + * @param SinglePlot $plot + * @param Biome $biome * * @return Promise * @phpstan-return Promise */ - public function setPlotBiome(Plot $plot, Biome $biome) : Promise { + public function setPlotBiome(SinglePlot $plot, Biome $biome) : Promise { $resolver = new PromiseResolver(); $newPlot = clone $plot; $newPlot->biome = str_replace(" ", "_", strtoupper($biome->getName())); @@ -1186,37 +651,13 @@ public function setPlotBiome(Plot $plot, Biome $biome) : Promise { $biome = BiomeIds::PLAINS; } $biome = BiomeRegistry::getInstance()->getBiome($biome); - if(!$this->isLevelLoaded($plot->levelName)){ + if($this->internalAPI->getLevelSettings($plot->levelName) === null){ $resolver->resolve(false); return $resolver->getPromise(); } - Await::f2c( - function() use ($plot, $biome, $resolver) { - $failed = false; - foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ - $merged->biome = $plot->biome; - if(!yield $this->dataProvider->savePlot($merged)) - $failed = true; - } - $plotLevel = $this->getLevelSettings($plot->levelName); - $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null) { - return false; - } - foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]) { - for($x = 0; $x < 16; ++$x) { - for($z = 0; $z < 16; ++$z) { - $pos = new Position(($chunkX << 4) + $x, $plotLevel->groundHeight, ($chunkZ << 4) + $z, $level); - $chunkPlot = $this->getPlotFast($pos->x, $pos->z, $plotLevel); - if($chunkPlot instanceof Plot and $chunkPlot->isSame($plot)) { - $chunk->setBiomeId($x, $z, $biome->getId()); - } - } - } - $level->setChunk($chunkX, $chunkZ, $chunk); - } - return !$failed; - }, + $this->internalAPI->setPlotBiome( + $plot, + $biome, fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); @@ -1228,19 +669,19 @@ function() use ($plot, $biome, $resolver) { * * @api * - * @param Plot $plot - * @param bool $pvp + * @param SinglePlot $plot + * @param bool $pvp * * @return Promise * @phpstan-return Promise */ - public function setPlotPvp(Plot $plot, bool $pvp) : Promise { - $resolver = new PromiseResolver(); + public function setPlotPvp(SinglePlot $plot, bool $pvp) : Promise { $newPlot = clone $plot; $newPlot->pvp = $pvp; $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); if($ev->isCancelled()) { + $resolver = new PromiseResolver(); $resolver->resolve(false); return $resolver->getPromise(); } @@ -1252,19 +693,19 @@ public function setPlotPvp(Plot $plot, bool $pvp) : Promise { * * @api * - * @param Plot $plot - * @param string $player + * @param SinglePlot $plot + * @param string $player * * @return Promise * @phpstan-return Promise */ - public function addPlotHelper(Plot $plot, string $player) : Promise { - $resolver = new PromiseResolver(); + public function addPlotHelper(SinglePlot $plot, string $player) : Promise { $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->addHelper($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { + $resolver = new PromiseResolver(); $resolver->resolve(false); return $resolver->getPromise(); } @@ -1276,19 +717,19 @@ public function addPlotHelper(Plot $plot, string $player) : Promise { * * @api * - * @param Plot $plot - * @param string $player + * @param SinglePlot $plot + * @param string $player * * @return Promise * @phpstan-return Promise */ - public function removePlotHelper(Plot $plot, string $player) : Promise { - $resolver = new PromiseResolver(); + public function removePlotHelper(SinglePlot $plot, string $player) : Promise { $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->removeHelper($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { + $resolver = new PromiseResolver(); $resolver->resolve(false); return $resolver->getPromise(); } @@ -1300,19 +741,19 @@ public function removePlotHelper(Plot $plot, string $player) : Promise { * * @api * - * @param Plot $plot - * @param string $player + * @param SinglePlot $plot + * @param string $player * * @return Promise * @phpstan-return Promise */ - public function addPlotDenied(Plot $plot, string $player) : Promise { - $resolver = new PromiseResolver(); + public function addPlotDenied(SinglePlot $plot, string $player) : Promise { $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->denyPlayer($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { + $resolver = new PromiseResolver(); $resolver->resolve(false); return $resolver->getPromise(); } @@ -1324,19 +765,19 @@ public function addPlotDenied(Plot $plot, string $player) : Promise { * * @api * - * @param Plot $plot - * @param string $player + * @param SinglePlot $plot + * @param string $player * * @return Promise * @phpstan-return Promise */ - public function removePlotDenied(Plot $plot, string $player) : Promise { - $resolver = new PromiseResolver(); + public function removePlotDenied(SinglePlot $plot, string $player) : Promise { $newPlot = clone $plot; $ev = new MyPlotSettingEvent($plot, $newPlot); $newPlot->unDenyPlayer($player) ? $ev->uncancel() : $ev->cancel(); $ev->call(); if($ev->isCancelled()) { + $resolver = new PromiseResolver(); $resolver->resolve(false); return $resolver->getPromise(); } @@ -1348,13 +789,13 @@ public function removePlotDenied(Plot $plot, string $player) : Promise { * * @api * - * @param Plot $plot - * @param float $price + * @param SinglePlot $plot + * @param float $price * * @return Promise * @phpstan-return Promise */ - public function sellPlot(Plot $plot, float $price) : Promise { + public function sellPlot(SinglePlot $plot, float $price) : Promise { $resolver = new PromiseResolver(); if($this->getEconomyProvider() === null or $price < 0) { $resolver->resolve(false); @@ -1378,53 +819,29 @@ public function sellPlot(Plot $plot, float $price) : Promise { * * @api * - * @param Plot $plot - * @param Player $player + * @param SinglePlot $plot + * @param Player $player * * @return Promise * @phpstan-return Promise */ - public function buyPlot(Plot $plot, Player $player) : Promise { + public function buyPlot(SinglePlot $plot, Player $player) : Promise { $resolver = new PromiseResolver(); - if($this->getEconomyProvider() === null or !$this->getEconomyProvider()->reduceMoney($player, $plot->price) or !$this->getEconomyProvider()->addMoney($this->getServer()->getOfflinePlayer($plot->owner), $plot->price)) { + if($this->getEconomyProvider() === null) { + $resolver->resolve(false); + return $resolver->getPromise(); + } + if(!$this->getEconomyProvider()->reduceMoney($player, $plot->price)) { + $resolver->resolve(false); + return $resolver->getPromise(); + } + if(!$this->getEconomyProvider()->addMoney($this->getServer()->getOfflinePlayer($plot->owner), $plot->price)) { + $this->getEconomyProvider()->addMoney($player, $plot->price); $resolver->resolve(false); return $resolver->getPromise(); } - Await::f2c( - function() use($plot, $player) { - $failed = false; - foreach (yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot) { - $newPlot = clone $mergedPlot; - $newPlot->owner = $player->getName(); - $newPlot->helpers = []; - $newPlot->denied = []; - $newPlot->price = 0.0; - $ev = new MyPlotSettingEvent($mergedPlot, $newPlot); - $ev->call(); - if ($ev->isCancelled()) { - $failed = true; - } - $mergedPlot = $ev->getPlot(); - if(! yield $this->dataProvider->savePlot($mergedPlot)) - $failed = true; - } - return !$failed; - }, - fn(bool $success) => $resolver->resolve($success), - fn() => $resolver->reject() - ); - return $resolver->getPromise(); - } - /** - * Returns the PlotLevelSettings of all the loaded levels - * - * @api - * - * @return PlotLevelSettings[] - */ - public function getPlotLevels() : array { - return $this->levels; + return $this->claimPlot($plot, $player->getName()); } /** @@ -1432,30 +849,18 @@ public function getPlotLevels() : array { * * @api * - * @param Plot $plot + * @param SinglePlot $plot * - * @return array> + * @return Promise> */ - public function getPlotChunks(Plot $plot) : array { - if(!$this->isLevelLoaded($plot->levelName)) - return []; - $plotLevel = $this->getLevelSettings($plot->levelName); - $level = $this->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null) - return []; - $plotSize = $plotLevel->plotSize; - $chunks = []; - foreach ($this->dataProvider->getMergedPlots($plot) as $mergedPlot){ - $pos = $this->getPlotPosition($mergedPlot, false); - $xMax = ($pos->x + $plotSize) >> 4; - $zMax = ($pos->z + $plotSize) >> 4; - for($x = $pos->x >> 4; $x <= $xMax; $x++) { - for($z = $pos->z >> 4; $z <= $zMax; $z++) { - $chunks[] = [$x, $z, $level->getChunk($x, $z)]; - } - } - } - return $chunks; + public function getPlotChunks(SinglePlot $plot) : Promise { + $resolver = new PromiseResolver(); + $this->internalAPI->getPlotChunks( + $plot, + fn(array $chunks) => $resolver->resolve($chunks), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -1470,7 +875,7 @@ public function getPlotChunks(Plot $plot) : array { public function getMaxPlotsOfPlayer(Player $player) : int { if($player->hasPermission("myplot.claimplots.unlimited")) return PHP_INT_MAX; - $perms = array_map(fn(PermissionAttachmentInfo $attachment) => [$attachment->getPermission(), $attachment->getValue()], $player->getEffectivePermissions()); + $perms = array_map(fn(PermissionAttachmentInfo $attachment) => $attachment->getValue(), $player->getEffectivePermissions()); // outputs permission string => value $perms = array_merge(PermissionManager::getInstance()->getPermission(DefaultPermissions::ROOT_USER)->getChildren(), $perms); $perms = array_filter($perms, function(string $name) : bool { return (str_starts_with($name, "myplot.claimplots.")); @@ -1491,84 +896,19 @@ public function getMaxPlotsOfPlayer(Player $player) : int { return 0; } - /** - * Finds the exact center of the plot at ground level - * - * @api - * - * @param Plot $plot - * - * @return Position|null - */ - public function getPlotMid(Plot $plot) : ?Position { - if(!$this->isLevelLoaded($plot->levelName)) - return null; - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $pos = $this->getPlotPosition($plot); - return new Position($pos->x + ($plotSize / 2), $pos->y + 1, $pos->z + ($plotSize / 2), $pos->getWorld()); - } - - /** - * Finds the exact center of the Merge at ground level - * - * @api - * - * @param Plot $plot - * - * @return Position|null - */ - public function getMergeMid(Plot $plot) : ?Position { - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $mergedPlots = $this->getProvider()->getMergedPlots($plot); - $minx = $this->getPlotPosition(array_reduce($mergedPlots, function(Plot $a, Plot $b) : Plot { - return $this->getPlotPosition($a, false)->x < $this->getPlotPosition($b, false)->x ? $a : $b; - }, $mergedPlots[0]), false)->x; - $maxx = $this->getPlotPosition(array_reduce($mergedPlots, function(Plot $a, Plot $b) : Plot { - return $this->getPlotPosition($a, false)->x > $this->getPlotPosition($b, false)->x ? $a : $b; - }, $mergedPlots[0]), false)->x + $plotSize; - $minz = $this->getPlotPosition(array_reduce($mergedPlots, function(Plot $a, Plot $b) : Plot { - return $this->getPlotPosition($a, false)->z < $this->getPlotPosition($b, false)->z ? $a : $b; - }, $mergedPlots[0]), false)->z; - $maxz = $this->getPlotPosition(array_reduce($mergedPlots, function(Plot $a, Plot $b) : Plot { - return $this->getPlotPosition($a, false)->z > $this->getPlotPosition($b, false)->z ? $a : $b; - }, $mergedPlots[0]), false)->z + $plotSize; - return new Position(($minx + $maxx) / 2, $plotLevel->groundHeight, ($minz + $maxz) / 2, $this->getServer()->getWorldManager()->getWorldByName($plot->levelName)); - } - - /** - * Teleports the player to the exact center of the plot at nearest open space to the ground level - * - * @internal - * - * @param Plot $plot - * @param Player $player - * - * @return bool - */ - private function teleportMiddle(Player $player, Plot $plot) : bool { - if($plot->isMerged()){ - $mid = $this->getMergeMid($plot); - }else { - $mid = $this->getPlotMid($plot); - } - if ($mid === null) { - return false; - } - return $player->teleport($mid); - } - /* -------------------------- Non-API part -------------------------- */ - public function onLoad() : void { + + public function onLoad() : void{ self::$instance = $this; + $this->getLogger()->debug(TF::BOLD . "Loading Configs"); $this->reloadConfig(); @mkdir($this->getDataFolder() . "worlds"); + $this->getLogger()->debug(TF::BOLD . "Loading MyPlot Generator"); GeneratorManager::getInstance()->addGenerator(MyPlotGenerator::class, "myplot", fn() => null, true); + $this->getLogger()->debug(TF::BOLD . "Loading Languages"); - // Loading Languages /** @var string $lang */ $lang = $this->getConfig()->get("Language", Language::FALLBACK_LANGUAGE); if($this->getConfig()->get("Custom Messages", false) === true) { @@ -1582,25 +922,22 @@ public function onLoad() : void { $this->saveResource(Language::FALLBACK_LANGUAGE.".ini", true); $this->getLogger()->debug("Custom Language ini created"); } - $this->Language = new Language("lang", $this->getDataFolder()); + $this->language = new Language("lang", $this->getDataFolder()); }else{ if(file_exists($this->getDataFolder()."lang.ini")) { unlink($this->getDataFolder()."lang.ini"); unlink($this->getDataFolder().Language::FALLBACK_LANGUAGE.".ini"); $this->getLogger()->debug("Custom Language ini deleted"); } - $this->Language = new Language($lang, $this->getFile() . "resources/"); + $this->language = new Language($lang, $this->getFile() . "resources/"); } - $this->getLogger()->debug(TF::BOLD . "Loading Data Provider settings"); - // Initialize DataProvider - $this->dataProvider = new DataProvider($this); $this->getLogger()->debug(TF::BOLD . "Loading Plot Clearing settings"); if($this->getConfig()->get("FastClearing", false) === true and $this->getServer()->getPluginManager()->getPlugin("WorldStyler") === null) { $this->getConfig()->set("FastClearing", false); $this->getLogger()->info(TF::BOLD . "WorldStyler not found. Legacy clearing will be used."); } + $this->getLogger()->debug(TF::BOLD . "Loading economy settings"); - // Initialize EconomyProvider if($this->getConfig()->get("UseEconomy", false) === true) { if(($plugin = $this->getServer()->getPluginManager()->getPlugin("EconomyAPI")) !== null) { if($plugin instanceof EconomyAPI) { @@ -1615,37 +952,19 @@ public function onLoad() : void { //$this->getConfig()->save(); } } + $this->getLogger()->debug(TF::BOLD . "Loading MyPlot Commands"); - // Register command $this->getServer()->getCommandMap()->register("myplot", new Commands($this)); + + $this->internalAPI = new InternalAPI($this); } public function onEnable() : void { $this->getLogger()->debug(TF::BOLD . "Loading Events"); - $eventListener = new EventListener($this); - $this->getServer()->getPluginManager()->registerEvents($eventListener, $this); - $this->getLogger()->debug(TF::BOLD . "Registering Loaded Levels"); - foreach($this->getServer()->getWorldManager()->getWorlds() as $level) { - $eventListener->onLevelLoad(new WorldLoadEvent($level)); - } - $this->getLogger()->debug(TF::BOLD.TF::GREEN."Enabled!"); - } - - public function addLevelSettings(string $levelName, PlotLevelSettings $settings) : bool { - $this->levels[$levelName] = $settings; - return true; - } - - public function unloadLevelSettings(string $levelName) : bool { - if(isset($this->levels[$levelName])) { - unset($this->levels[$levelName]); - $this->getLogger()->debug("Level " . $levelName . " settings unloaded!"); - return true; - } - return false; + $this->getServer()->getPluginManager()->registerEvents(new EventListener($this, $this->internalAPI), $this); } public function onDisable() : void { - $this->dataProvider->close(); + $this->internalAPI->onDisable(); } -} +} \ No newline at end of file From c74cdd5ac6b1790b96cb4e10dbef83d8cfa9b430 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sun, 6 Mar 2022 18:37:12 -0500 Subject: [PATCH 31/47] Remove unused static getPlotPosition --- src/MyPlot/utils/AsyncVariants.php | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/src/MyPlot/utils/AsyncVariants.php b/src/MyPlot/utils/AsyncVariants.php index 490d8560..a7c7306b 100644 --- a/src/MyPlot/utils/AsyncVariants.php +++ b/src/MyPlot/utils/AsyncVariants.php @@ -2,11 +2,7 @@ declare(strict_types=1); namespace jasonwynn10\MyPlot\utils; -use MyPlot\MyPlot; -use MyPlot\Plot; -use pocketmine\world\Position; - -class AsyncVariants{ +class AsyncVariants { public static function array_reduce(array $array, callable $callback, mixed $initial = null) : \Generator { $result = $initial; foreach($array as $value){ @@ -14,22 +10,4 @@ public static function array_reduce(array $array, callable $callback, mixed $ini } return $result; } - - public static function getPlotPosition(Plot $plot, bool $mergeOrigin = true) : \Generator { - $plugin = MyPlot::getInstance(); - $plotLevel = $plugin->getLevelSettings($plot->levelName); - $origin = yield $plugin->getProvider()->getMergeOrigin($plot); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($mergeOrigin){ - $x = $totalSize * $origin->X; - $z = $totalSize * $origin->Z; - }else{ - $x = $totalSize * $plot->X; - $z = $totalSize * $plot->Z; - } - $level = $plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); - return new Position($x, $plotLevel->groundHeight, $z, $level); - } } \ No newline at end of file From dcedb7540507080f499cf8fec0c930fb06f66e75 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sun, 6 Mar 2022 18:37:40 -0500 Subject: [PATCH 32/47] Extract plot into 3 types --- src/MyPlot/Plot.php | 209 --------------------------------- src/MyPlot/plot/BasePlot.php | 27 +++++ src/MyPlot/plot/MergedPlot.php | 78 ++++++++++++ src/MyPlot/plot/SinglePlot.php | 118 +++++++++++++++++++ 4 files changed, 223 insertions(+), 209 deletions(-) delete mode 100644 src/MyPlot/Plot.php create mode 100644 src/MyPlot/plot/BasePlot.php create mode 100644 src/MyPlot/plot/MergedPlot.php create mode 100644 src/MyPlot/plot/SinglePlot.php diff --git a/src/MyPlot/Plot.php b/src/MyPlot/Plot.php deleted file mode 100644 index f5963f0b..00000000 --- a/src/MyPlot/Plot.php +++ /dev/null @@ -1,209 +0,0 @@ -levelName = $levelName; - $this->X = $X; - $this->Z = $Z; - $this->name = $name; - $this->owner = $owner; - $this->helpers = $helpers; - $this->denied = $denied; - $this->biome = strtoupper($biome); - $settings = MyPlot::getInstance()->getLevelSettings($levelName); - if(!isset($pvp)) { - $this->pvp = !$settings->restrictPVP; - }else{ - $this->pvp = $pvp; - } - if(MyPlot::getInstance()->getConfig()->get('UseEconomy', false) === true) - $this->price = $price < 0 ? $settings->claimPrice : $price; - else - $this->price = 0; - } - - /** - * @api - * - * @param string $username - * - * @return bool - */ - public function isHelper(string $username) : bool { - return in_array($username, $this->helpers, true); - } - - /** - * @api - * - * @param string $username - * - * @return bool - */ - public function addHelper(string $username) : bool { - if(!$this->isHelper($username)) { - $this->unDenyPlayer($username); - $this->helpers[] = $username; - return true; - } - return false; - } - - /** - * @api - * - * @param string $username - * - * @return bool - */ - public function removeHelper(string $username) : bool { - if(!$this->isHelper($username)) { - return false; - } - $key = array_search($username, $this->helpers, true); - if($key === false) { - return false; - } - unset($this->helpers[$key]); - return true; - } - - /** - * @api - * - * @param string $username - * - * @return bool - */ - public function isDenied(string $username) : bool { - return in_array($username, $this->denied, true); - } - - /** - * @api - * - * @param string $username - * - * @return bool - */ - public function denyPlayer(string $username) : bool { - if(!$this->isDenied($username)) { - $this->removeHelper($username); - $this->denied[] = $username; - return true; - } - return false; - } - - /** - * @api - * - * @param string $username - * - * @return bool - */ - public function unDenyPlayer(string $username) : bool { - if(!$this->isDenied($username)) { - return false; - } - $key = array_search($username, $this->denied, true); - if($key === false) { - return false; - } - unset($this->denied[$key]); - return true; - } - - /** - * @api - * - * @param Plot $plot - * @param bool $checkMerge - * - * @return bool - */ - public function isSame(Plot $plot, bool $checkMerge = true) : bool { - if($checkMerge) - $plot = MyPlot::getInstance()->getProvider()->getMergeOrigin($plot); - return $this->X === $plot->X and $this->Z === $plot->Z and $this->levelName === $plot->levelName; - } - - /** - * @api - * - * @return bool - */ - public function isMerged() : bool { - return count(MyPlot::getInstance()->getProvider()->getMergedPlots($this, true)) > 1; // only calculate the adjacent to save resources - } - - /** - * @api - * - * @param int $side - * @param int $step - * - * @return Plot - */ - public function getSide(int $side, int $step = 1) : Plot { - $levelSettings = MyPlot::getInstance()->getLevelSettings($this->levelName); - $pos = MyPlot::getInstance()->getPlotPosition($this, false); - $sidePos = $pos->getSide($side, $step * ($levelSettings->plotSize + $levelSettings->roadWidth)); - $sidePlot = MyPlot::getInstance()->getPlotByPosition($sidePos); - if($sidePlot === null) { - switch($side) { - case Facing::NORTH: - $sidePlot = new self($this->levelName, $this->X, $this->Z - $step); - break; - case Facing::SOUTH: - $sidePlot = new self($this->levelName, $this->X, $this->Z + $step); - break; - case Facing::WEST: - $sidePlot = new self($this->levelName, $this->X - $step, $this->Z); - break; - case Facing::EAST: - $sidePlot = new self($this->levelName, $this->X + $step, $this->Z); - break; - default: - return clone $this; - } - } - return $sidePlot; - } - - public function __toString() : string { - return "(" . $this->X . ";" . $this->Z . ")"; - } -} \ No newline at end of file diff --git a/src/MyPlot/plot/BasePlot.php b/src/MyPlot/plot/BasePlot.php new file mode 100644 index 00000000..8dc0813d --- /dev/null +++ b/src/MyPlot/plot/BasePlot.php @@ -0,0 +1,27 @@ +levelName === $plot->levelName and $this->X === $plot->X and $this->Z === $plot->Z; + } + + public function getSide(int $side, int $step = 1) : BasePlot { + return match($side) { + Facing::NORTH => new BasePlot($this->levelName, $this->X, $this->Z - $step), + Facing::SOUTH => new BasePlot($this->levelName, $this->X, $this->Z + $step), + Facing::EAST => new BasePlot($this->levelName, $this->X + $step, $this->Z), + Facing::WEST => new BasePlot($this->levelName, $this->X - $step, $this->Z), + default => throw new \InvalidArgumentException("Invalid side: ".Facing::toString($side)) + }; + } + + public function __toString() : string { + return "(" . $this->X . ";" . $this->Z . ")"; + } +} \ No newline at end of file diff --git a/src/MyPlot/plot/MergedPlot.php b/src/MyPlot/plot/MergedPlot.php new file mode 100644 index 00000000..ac303393 --- /dev/null +++ b/src/MyPlot/plot/MergedPlot.php @@ -0,0 +1,78 @@ +xWidth = $xWidth; + $this->zWidth = $zWidth; + } + + /** + * TODO: description + * + * @api + * + * @param SinglePlot $plot + * + * @return bool + */ + public function isSame(BasePlot $plot) : bool { + if(parent::isSame($plot)) + return true; + + return ( + new AxisAlignedBB( + min($this->X, $this->X + $this->xWidth), + 0, + min($this->Z, $this->Z + $this->zWidth), + max($this->X, $this->X + $this->xWidth), + 1, + max($this->Z, $this->Z + $this->zWidth) + ) + )->isVectorInXZ(new Vector3($plot->X, 0, $plot->Z)); + } + + public function getSide(int $side, int $step = 1) : BasePlot { + if(Facing::axis($side) === Axis::X) { + if(Facing::isPositive($side) and $this->xWidth > 0) { + return parent::getSide($side, $step); + }elseif(!Facing::isPositive($side) and $this->xWidth < 0) { + return parent::getSide($side, $step); + } + }elseif(Facing::axis($side) === Axis::Z){ + if(Facing::isPositive($side)and $this->zWidth > 0) { + return parent::getSide($side, $step); + }elseif(!Facing::isPositive($side) and $this->xWidth < 0) { + return parent::getSide($side, $step); + } + } + return parent::getSide($side, $step); + } +} \ No newline at end of file diff --git a/src/MyPlot/plot/SinglePlot.php b/src/MyPlot/plot/SinglePlot.php new file mode 100644 index 00000000..467936f5 --- /dev/null +++ b/src/MyPlot/plot/SinglePlot.php @@ -0,0 +1,118 @@ +biome = strtoupper($biome); + $settings = MyPlot::getInstance()->getLevelSettings($levelName); + if(!isset($pvp)) { + $this->pvp = !$settings->restrictPVP; + }else{ + $this->pvp = $pvp; + } + if(MyPlot::getInstance()->getConfig()->get('UseEconomy', false) === true) + $this->price = $price < 0 ? $settings->claimPrice : $price; + else + $this->price = 0; + } + + /** + * @api + * + * @param string $username + * + * @return bool + */ + public function isHelper(string $username) : bool { + return in_array($username, $this->helpers, true); + } + + /** + * @api + * + * @param string $username + * + * @return bool + */ + public function addHelper(string $username) : bool { + if(!$this->isHelper($username)) { + $this->unDenyPlayer($username); + $this->helpers[] = $username; + return true; + } + return false; + } + + /** + * @api + * + * @param string $username + * + * @return bool + */ + public function removeHelper(string $username) : bool { + if(!$this->isHelper($username)) { + return false; + } + $key = array_search($username, $this->helpers, true); + if($key === false) { + return false; + } + unset($this->helpers[$key]); + return true; + } + + /** + * @api + * + * @param string $username + * + * @return bool + */ + public function isDenied(string $username) : bool { + return in_array($username, $this->denied, true); + } + + /** + * @api + * + * @param string $username + * + * @return bool + */ + public function denyPlayer(string $username) : bool { + if(!$this->isDenied($username)) { + $this->removeHelper($username); + $this->denied[] = $username; + return true; + } + return false; + } + + /** + * @api + * + * @param string $username + * + * @return bool + */ + public function unDenyPlayer(string $username) : bool { + if(!$this->isDenied($username)) { + return false; + } + $key = array_search($username, $this->denied, true); + if($key === false) { + return false; + } + unset($this->denied[$key]); + return true; + } +} \ No newline at end of file From ca8480dafcc5eb70e5403164a3963b11c7795a68 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Sun, 6 Mar 2022 18:38:24 -0500 Subject: [PATCH 33/47] Added await-generator virion in poggit --- .poggit.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.poggit.yml b/.poggit.yml index b5efc69e..1348ff25 100644 --- a/.poggit.yml +++ b/.poggit.yml @@ -6,6 +6,8 @@ projects: libs: - src: poggit/libasynql/libasynql version: ^3.3.0 + - src: SOFe/AwaitGenerator/await-generator + version: ^3.1.1 - src: dktapps-pm-pl/pmforms/pmforms version: ^2.0.0 lint: false From 95e0f1a3b0dfc0b18ee6beea03e54fcc5808667d Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Tue, 8 Mar 2022 22:24:36 -0500 Subject: [PATCH 34/47] Making InternalAPI fit our needs better --- plugin.yml | 5 +- src/MyPlot/InternalAPI.php | 136 +++++++++++++++++------ src/MyPlot/MyPlot.php | 72 ++++++++---- src/MyPlot/plot/SinglePlot.php | 4 +- src/MyPlot/provider/CapitalProvider.php | 65 +++++++++++ src/MyPlot/provider/DataProvider.php | 99 +++++++++++++---- src/MyPlot/provider/EconomyProvider.php | 29 ++++- src/MyPlot/provider/EconomySProvider.php | 52 ++++++--- 8 files changed, 364 insertions(+), 98 deletions(-) create mode 100644 src/MyPlot/provider/CapitalProvider.php diff --git a/plugin.yml b/plugin.yml index 3c302b4e..464b0151 100644 --- a/plugin.yml +++ b/plugin.yml @@ -10,10 +10,11 @@ authors: description: "Plots and Protection Plugin for PocketMine-MP Servers" load: STARTUP softdepend: -- EconomyAPI +- Capital - DEVirion -- WorldStyler - EasyCommandAutofill +- EconomyAPI +- WorldStyler permissions: myplot.command: default: true diff --git a/src/MyPlot/InternalAPI.php b/src/MyPlot/InternalAPI.php index 81eae1d8..22a2ff81 100644 --- a/src/MyPlot/InternalAPI.php +++ b/src/MyPlot/InternalAPI.php @@ -1,6 +1,5 @@ getLogger()->debug(TF::BOLD . "Loading Data Provider settings"); $this->dataProvider = new DataProvider($plugin); } + public function getEconomyProvider() : ?EconomyProvider { + return $this->economyProvider; + } + + public function setEconomyProvider(?EconomyProvider $economyProvider) : void{ + $this->economyProvider = $economyProvider; + } + public function getAllLevelSettings() : array{ return $this->levels; } @@ -73,9 +82,9 @@ public function savePlot(SinglePlot $plot, ?callable $onComplete = null, ?callab ); } - private function generatePlotsToSave(SinglePlot $plot) : \Generator{ + public function generatePlotsToSave(SinglePlot $plot) : \Generator{ $failed = false; - foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ + foreach((yield $this->dataProvider->getMergedPlots($plot)) as $merged){ $savePlot = clone $plot; $savePlot->X = $merged->X; $savePlot->Z = $merged->Z; @@ -92,35 +101,51 @@ private function generatePlotsToSave(SinglePlot $plot) : \Generator{ * @param string $username * @param string|null $levelName * @param callable|null $onComplete - * @phpstan-param (callable(array): void)|null $onComplete + * @phpstan-param (callable(array): void)|null $onComplete * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ public function getPlotsOfPlayer(string $username, ?string $levelName, ?callable $onComplete = null, ?callable $onFail = null) : void{ Await::g2c( - $this->dataProvider->getPlotsByOwner($username, $levelName), + $this->generatePlotsOfPlayer($username, $levelName), $onComplete, $onFail === null ? [] : [$onFail] ); } + /** + * @param string $username + * @param string|null $levelName + * + * @return \Generator> + */ + public function generatePlotsOfPlayer(string $username, ?string $levelName) : \Generator { + false && yield; + return $this->dataProvider->getPlotsByOwner($username, $levelName); + } + /** * @param string $levelName * @param int $limitXZ * @param callable|null $onComplete - * @phpstan-param (callable(Plot): void)|null $onComplete + * @phpstan-param (callable(BasePlot): void)|null $onComplete * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ public function getNextFreePlot(string $levelName, int $limitXZ, ?callable $onComplete = null, ?callable $onFail = null) : void{ Await::g2c( - $this->dataProvider->getNextFreePlot($levelName, $limitXZ), + $this->generateNextFreePlot($levelName, $limitXZ), $onComplete, $onFail === null ? [] : [$onFail] ); } - public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?SinglePlot{ + public function generateNextFreePlot(string $levelName, int $limitXZ) : \Generator{ + false && yield; + return $this->dataProvider->getNextFreePlot($levelName, $limitXZ); + } + + public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?BasePlot{ $plotSize = $plotLevel->plotSize; $roadWidth = $plotLevel->roadWidth; $totalSize = $plotSize + $roadWidth; @@ -141,15 +166,45 @@ public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)) return null; - return new SinglePlot($plotLevel->name, $x, $z); + return new BasePlot($plotLevel->name, $x, $z); + } + + /** + * @param string $worldName + * @param int $X + * @param int $Z + * @param callable|null $onComplete + * @phpstan-param (callable(SinglePlot): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlot(string $worldName, int $X, int $Z, ?callable $onComplete = null, ?callable $onFail = null) : void { + Await::g2c( + $this->generatePlot($worldName, $X, $Z), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param string $worldName + * @param int $X + * @param int $Z + * + * @return \Generator + */ + public function generatePlot(string $worldName, int $X, int $Z) : \Generator { + false && yield; + // TODO: if merged return MergedPlot object + return $this->dataProvider->getPlot($worldName, $X, $Z); } /** * @param Position $position * @param callable|null $onComplete - * @phpstan-param (callable(Plot): void)|null $onComplete + * @phpstan-param (callable(BasePlot): void)|null $onComplete * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches + * @phpstan-param (callable(\Throwable): void)|null $catches */ public function getPlotByPosition(Position $position, ?callable $onComplete = null, ?callable $onFail = null) : void{ Await::g2c( @@ -159,7 +214,7 @@ public function getPlotByPosition(Position $position, ?callable $onComplete = nu ); } - private function generatePlotByPosition(Position $position) : \Generator{ + public function generatePlotByPosition(Position $position) : \Generator{ $x = $position->x; $z = $position->z; $levelName = $position->getWorld()->getFolderName(); @@ -211,7 +266,7 @@ public function getPlotPosition(SinglePlot $plot, bool $mergeOrigin, ?callable $ ); } - private function generatePlotPosition(SinglePlot $plot, bool $mergeOrigin) : \Generator{ + public function generatePlotPosition(BasePlot $plot, bool $mergeOrigin) : \Generator{ $plotLevel = $this->getLevelSettings($plot->levelName); $origin = yield $this->dataProvider->getMergeOrigin($plot); $plotSize = $plotLevel->plotSize; @@ -249,7 +304,7 @@ function() use ($position){ /** * @param Position $position * @param callable|null $onComplete - * @phpstan-param (callable(Plot): void)|null $onComplete + * @phpstan-param (callable(BasePlot): void)|null $onComplete * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ @@ -261,7 +316,7 @@ public function getPlotBorderingPosition(Position $position, ?callable $onComple ); } - private function generatePlotBorderingPosition(Position $position) : \Generator{ + public function generatePlotBorderingPosition(Position $position) : \Generator{ if(!$position->isValid()) return null; foreach(Facing::HORIZONTAL as $i){ @@ -334,7 +389,7 @@ public function getPlotBB(SinglePlot $plot, ?callable $onComplete = null, ?calla ); } - private function generatePlotBB(SinglePlot $plot) : \Generator{ + public function generatePlotBB(SinglePlot $plot) : \Generator{ $plotLevel = $this->getLevelSettings($plot->levelName); $plotSize = $plotLevel->plotSize - 1; $pos = yield $this->generatePlotPosition($plot, false); @@ -378,11 +433,12 @@ public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTi ); } - private function generateMergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTick) : \Generator{ + public function generateMergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTick) : \Generator{ if($this->getLevelSettings($plot->levelName) === null) return false; /** @var SinglePlot[][] $toMerge */ $toMerge = []; + /** @var SinglePlot[] $mergedPlots */ $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); $newPlot = $plot->getSide($direction); $alreadyMerged = false; @@ -467,13 +523,13 @@ public function teleportPlayerToPlot(Player $player, SinglePlot $plot, bool $cen ); } - private function generatePlayerTeleport(Player $player, SinglePlot $plot, bool $center) : \Generator{ + public function generatePlayerTeleport(Player $player, BasePlot $plot, bool $center) : \Generator{ if($center){ - $pos = $plot->isMerged() ? yield $this->getMergeMid($plot) : yield $this->getPlotMid($plot); + $pos = $plot instanceof MergedPlot ? yield $this->getMergeMid($plot) : yield $this->getPlotMid($plot); return $player->teleport($pos); } - if($plot->isMerged()){ + if($plot instanceof MergedPlot){ $plotLevel = $this->getLevelSettings($plot->levelName); $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); @@ -502,7 +558,7 @@ private function generatePlayerTeleport(Player $player, SinglePlot $plot, bool $ return $player->teleport($pos); } - private function getPlotMid(SinglePlot $plot) : \Generator{ + private function getPlotMid(BasePlot $plot) : \Generator{ if($this->getLevelSettings($plot->levelName) === null) return null; @@ -516,18 +572,30 @@ private function getMergeMid(SinglePlot $plot) : \Generator{ $plotLevel = $this->getLevelSettings($plot->levelName); $plotSize = $plotLevel->plotSize; $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); - $minx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->x < (yield $this->generatePlotPosition($b, false))->x ? $a : $b; - }), false))->x; - $maxx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + $minx = (yield $this->generatePlotPosition( + yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->x < (yield $this->generatePlotPosition($b, false))->x ? $a : $b; + }), + false + ))->x; + $maxx = (yield $this->generatePlotPosition( + yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ return (yield $this->generatePlotPosition($a, false))->x > (yield $this->generatePlotPosition($b, false))->x ? $a : $b; - }), false))->x + $plotSize; - $minz = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->z < (yield $this->generatePlotPosition($b, false))->z ? $a : $b; - }), false))->z; - $maxz = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + }), + false + ))->x + $plotSize; + $minz = (yield $this->generatePlotPosition( + yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->z < (yield $this->generatePlotPosition($b, false))->z ? $a : $b; + }), + false + ))->z; + $maxz = (yield $this->generatePlotPosition( + yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ return (yield $this->generatePlotPosition($a, false))->z > (yield $this->generatePlotPosition($b, false))->z ? $a : $b; - }), false))->z + $plotSize; + }), + false + ))->z + $plotSize; return new Position(($minx + $maxx) / 2, $plotLevel->groundHeight, ($minz + $maxz) / 2, $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)); } @@ -832,7 +900,7 @@ public function setPlotBiome(SinglePlot $plot, Biome $biome, ?callable $onComple ); } - private function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ + public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ $failed = false; foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ $merged->biome = $plot->biome; @@ -874,7 +942,7 @@ public function getPlotChunks(SinglePlot $plot, ?callable $onComplete = null, ?c ); } - private function generatePlotChunks(SinglePlot $plot) : \Generator{ + public function generatePlotChunks(SinglePlot $plot) : \Generator{ $plotLevel = $this->getLevelSettings($plot->levelName); if($plotLevel === null){ return []; diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 45e2436b..cbeaf1be 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -11,7 +11,9 @@ use MyPlot\events\MyPlotResetEvent; use MyPlot\events\MyPlotSettingEvent; use MyPlot\events\MyPlotTeleportEvent; +use MyPlot\plot\BasePlot; use MyPlot\plot\SinglePlot; +use MyPlot\provider\CapitalProvider; use MyPlot\provider\EconomyProvider; use MyPlot\provider\EconomySProvider; use onebone\economyapi\EconomyAPI; @@ -36,12 +38,12 @@ use pocketmine\world\generator\GeneratorManager; use pocketmine\world\Position; use pocketmine\world\WorldCreationOptions; +use SOFe\Capital\Capital; class MyPlot extends PluginBase { private static MyPlot $instance; private Language $language; - private ?EconomyProvider $economyProvider; private InternalAPI $internalAPI; public static function getInstance() : self { @@ -78,7 +80,7 @@ public function getFallBackLang() : Language { * @return EconomyProvider|null */ public function getEconomyProvider() : ?EconomyProvider { - return $this->economyProvider; + return $this->internalAPI->getEconomyProvider(); } /** @@ -96,7 +98,7 @@ public function setEconomyProvider(?EconomyProvider $provider) : void { $this->getConfig()->set("UseEconomy", true); $this->getLogger()->info("A custom economy provider has been registered. Economy mode now enabled!"); } - $this->economyProvider = $provider; + $this->internalAPI->setEconomyProvider($provider); } /** @@ -247,6 +249,25 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : Promise{ return $resolver->getPromise(); } + /** + * @param string $levelName + * @param int $X + * @param int $Z + * + * @return Promise + */ + public function getPlot(string $levelName, int $X, int $Z) : Promise{ + $resolver = new PromiseResolver(); + $this->internalAPI->getPlot( + $levelName, + $X, + $Z, + fn(?SinglePlot $plot) => $resolver->resolve($plot), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); + } + /** * Finds the plot at a certain position or null if there is no plot at that position * @@ -385,7 +406,7 @@ public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTi * @return Promise * @phpstan-return Promise */ - public function teleportPlayerToPlot(Player $player, SinglePlot $plot, bool $center = false) : Promise { + public function teleportPlayerToPlot(Player $player, BasePlot $plot, bool $center = false) : Promise { $resolver = new PromiseResolver(); $ev = new MyPlotTeleportEvent($plot, $player, $center); $ev->call(); @@ -422,7 +443,7 @@ public function claimPlot(SinglePlot $plot, string $claimer, string $plotName = $newPlot->denied = []; if($plotName !== "") $newPlot->name = $plotName; - $newPlot->price = 0.0; + $newPlot->price = 0; $ev = new MyPlotSettingEvent($plot, $newPlot); $ev->call(); if($ev->isCancelled()){ @@ -790,14 +811,14 @@ public function removePlotDenied(SinglePlot $plot, string $player) : Promise { * @api * * @param SinglePlot $plot - * @param float $price + * @param int $price * * @return Promise * @phpstan-return Promise */ - public function sellPlot(SinglePlot $plot, float $price) : Promise { + public function sellPlot(SinglePlot $plot, int $price) : Promise { $resolver = new PromiseResolver(); - if($this->getEconomyProvider() === null or $price < 0) { + if($this->internalAPI->getEconomyProvider() === null or $price <= 0) { $resolver->resolve(false); return $resolver->getPromise(); } @@ -827,16 +848,16 @@ public function sellPlot(SinglePlot $plot, float $price) : Promise { */ public function buyPlot(SinglePlot $plot, Player $player) : Promise { $resolver = new PromiseResolver(); - if($this->getEconomyProvider() === null) { + if($this->internalAPI->getEconomyProvider() === null) { $resolver->resolve(false); return $resolver->getPromise(); } - if(!$this->getEconomyProvider()->reduceMoney($player, $plot->price)) { + if(!$this->economyProvider->reduceMoney($player, $plot->price)) { $resolver->resolve(false); return $resolver->getPromise(); } - if(!$this->getEconomyProvider()->addMoney($this->getServer()->getOfflinePlayer($plot->owner), $plot->price)) { - $this->getEconomyProvider()->addMoney($player, $plot->price); + if(!$this->economyProvider->addMoney($this->getServer()->getOfflinePlayer($plot->owner), $plot->price)) { + $this->economyProvider->addMoney($player, $plot->price); $resolver->resolve(false); return $resolver->getPromise(); } @@ -931,32 +952,41 @@ public function onLoad() : void{ } $this->language = new Language($lang, $this->getFile() . "resources/"); } - $this->getLogger()->debug(TF::BOLD . "Loading Plot Clearing settings"); + + $this->getLogger()->debug(TF::BOLD . "Loading Plot Clearing settings"); // TODO: finish libEfficientWE if($this->getConfig()->get("FastClearing", false) === true and $this->getServer()->getPluginManager()->getPlugin("WorldStyler") === null) { $this->getConfig()->set("FastClearing", false); $this->getLogger()->info(TF::BOLD . "WorldStyler not found. Legacy clearing will be used."); } $this->getLogger()->debug(TF::BOLD . "Loading economy settings"); + $economyProvider = null; if($this->getConfig()->get("UseEconomy", false) === true) { if(($plugin = $this->getServer()->getPluginManager()->getPlugin("EconomyAPI")) !== null) { if($plugin instanceof EconomyAPI) { - $this->economyProvider = new EconomySProvider($plugin); - $this->getLogger()->debug("Eco set to EconomySProvider"); + $economyProvider = new EconomySProvider($plugin); + $this->getLogger()->debug("Economy set to EconomyAPI"); }else - $this->getLogger()->debug("Eco not instance of EconomyAPI"); + $this->getLogger()->debug("Invalid instance of EconomyAPI"); } - if(!isset($this->economyProvider)) { - $this->getLogger()->info("No supported economy plugin found!"); + if(($plugin = $this->getServer()->getPluginManager()->getPlugin("Capital")) !== null) { + if($plugin instanceof Capital) { + $economyProvider = new CapitalProvider(); + $this->getLogger()->debug("Economy set to Capital"); + }else + $this->getLogger()->debug("Invalid instance of Capital"); + } + if(!isset($economyProvider)) { + $this->getLogger()->warning("No supported economy plugin found!"); $this->getConfig()->set("UseEconomy", false); //$this->getConfig()->save(); } } - $this->getLogger()->debug(TF::BOLD . "Loading MyPlot Commands"); - $this->getServer()->getCommandMap()->register("myplot", new Commands($this)); + $this->internalAPI = new InternalAPI($this, $economyProvider); - $this->internalAPI = new InternalAPI($this); + $this->getLogger()->debug(TF::BOLD . "Loading MyPlot Commands"); + $this->getServer()->getCommandMap()->register("myplot", new Commands($this, $this->internalAPI)); } public function onEnable() : void { diff --git a/src/MyPlot/plot/SinglePlot.php b/src/MyPlot/plot/SinglePlot.php index 467936f5..397f22ca 100644 --- a/src/MyPlot/plot/SinglePlot.php +++ b/src/MyPlot/plot/SinglePlot.php @@ -7,7 +7,7 @@ class SinglePlot extends BasePlot { public string $biome = "PLAINS"; public bool $pvp = true; - public float $price = 0.0; + public int $price = 0; public function __construct(public string $levelName, public int $X, public int $Z, public string $name = "", public string $owner = "", public array $helpers = [], public array $denied = [], string $biome = "PLAINS", ?bool $pvp = null, float $price = -1) { parent::__construct($levelName, $X, $Z); @@ -18,7 +18,7 @@ public function __construct(public string $levelName, public int $X, public int }else{ $this->pvp = $pvp; } - if(MyPlot::getInstance()->getConfig()->get('UseEconomy', false) === true) + if(MyPlot::getInstance()->getEconomyProvider() !== null) $this->price = $price < 0 ? $settings->claimPrice : $price; else $this->price = 0; diff --git a/src/MyPlot/provider/CapitalProvider.php b/src/MyPlot/provider/CapitalProvider.php new file mode 100644 index 00000000..6a554a9b --- /dev/null +++ b/src/MyPlot/provider/CapitalProvider.php @@ -0,0 +1,65 @@ +selector = $api->completeConfig(null); // use null to get the default schema from Capital + }); + } + + /** + * @inheritDoc + */ + public function reduceMoney(Player $player, int $amount, string $reason = 'Unknown') : \Generator { + /** @var Capital $api */ + $api = yield from Capital::get(MainClass::$context); + yield from $api->takeMoney( + oracleName: "MyPlot", + player: $player, + schema: $this->selector, + amount: $amount, + transactionLabels: new LabelSet(["reason" => $reason]), + ); + } + + /** + * @inheritDoc + */ + public function addMoney(Player $player, int $amount, string $reason = 'Unknown') : \Generator { + /** @var Capital $api */ + $api = yield from Capital::get(MainClass::$context); + yield from $api->addMoney( + oracleName: "MyPlot", + player: $player, + schema: $this->selector, + amount: $amount, + transactionLabels: new LabelSet(["reason" => $reason]), + ); + } + + /** + * @inheritDoc + */ + public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = 'Unknown') : \Generator { + /** @var Capital $api */ + $api = yield from Capital::get(MainClass::$context); + yield from $api->pay( + src: $player1, + dest: $player2, + schema: $this->selector, + amount: $amount, + transactionLabels: new LabelSet(["reason" => $reason]), + ); + } +} \ No newline at end of file diff --git a/src/MyPlot/provider/DataProvider.php b/src/MyPlot/provider/DataProvider.php index ce65d052..62a90e05 100644 --- a/src/MyPlot/provider/DataProvider.php +++ b/src/MyPlot/provider/DataProvider.php @@ -3,19 +3,21 @@ namespace MyPlot\provider; use MyPlot\MyPlot; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; +use MyPlot\plot\MergedPlot; +use MyPlot\plot\SinglePlot; use pocketmine\math\Facing; use poggit\libasynql\DataConnector; use poggit\libasynql\libasynql; -final class DataProvider{ +final class DataProvider { - /** @var Plot[] $cache */ + /** @var BasePlot[] $cache */ private array $cache = []; private int $cacheSize; private DataConnector $database; - public function __construct(protected MyPlot $plugin){ + public function __construct(private MyPlot $plugin) { $this->database = libasynql::create($plugin, $plugin->getConfig()->get("Database"), [ 'sqlite' => 'sqlite.sql', 'mysql' => 'mysql.sql', @@ -23,7 +25,7 @@ public function __construct(protected MyPlot $plugin){ $this->cacheSize = $plugin->getConfig()->get("PlotCacheSize", 2048); } - private function cachePlot(Plot $plot) : void{ + private function cachePlot(BasePlot $plot) : void{ if($this->cacheSize > 0){ $key = $plot->levelName . ';' . $plot->X . ';' . $plot->Z; if(isset($this->cache[$key])){ @@ -36,7 +38,7 @@ private function cachePlot(Plot $plot) : void{ } } - private function getPlotFromCache(string $levelName, int $X, int $Z) : ?Plot{ + private function getPlotFromCache(string $levelName, int $X, int $Z) : ?BasePlot{ if($this->cacheSize > 0){ $key = $levelName . ';' . $X . ';' . $Z; if(isset($this->cache[$key])){ @@ -47,7 +49,12 @@ private function getPlotFromCache(string $levelName, int $X, int $Z) : ?Plot{ return null; } - public function savePlot(Plot $plot) : \Generator{ + /** + * @param SinglePlot $plot + * + * @return \Generator + */ + public function savePlot(SinglePlot $plot) : \Generator{ [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.plot', [ 'level' => $plot->levelName, 'X' => $plot->X, @@ -67,8 +74,13 @@ public function savePlot(Plot $plot) : \Generator{ return true; } - public function deletePlot(Plot $plot) : \Generator{ - if($plot->isMerged()){ + /** + * @param BasePlot $plot + * + * @return \Generator + */ + public function deletePlot(BasePlot $plot) : \Generator{ + if($plot instanceof MergedPlot) { $changedRows = yield $this->database->asyncChange('myplot.remove.merge.by-xz', [ 'level' => $plot->levelName, 'X' => $plot->X, @@ -84,10 +96,17 @@ public function deletePlot(Plot $plot) : \Generator{ if($changedRows < 1){ return false; } - $this->cachePlot(new Plot($plot->levelName, $plot->X, $plot->Z)); + $this->cachePlot(new BasePlot($plot->levelName, $plot->X, $plot->Z)); return true; } + /** + * @param string $levelName + * @param int $X + * @param int $Z + * + * @return \Generator + */ public function getPlot(string $levelName, int $X, int $Z) : \Generator{ $plot = $this->getPlotFromCache($levelName, $X, $Z); if($plot !== null){ @@ -98,9 +117,15 @@ public function getPlot(string $levelName, int $X, int $Z) : \Generator{ 'X' => $X, 'Z' => $Z ]); - return new Plot($levelName, $X, $Z, $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + return new SinglePlot($levelName, $X, $Z, $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); } + /** + * @param string $owner + * @param string $levelName + * + * @return \Generator> + */ public function getPlotsByOwner(string $owner, string $levelName = "") : \Generator{ if($levelName !== null){ $rows = yield $this->database->asyncSelect('myplot.get.all-plots.by-owner-and-level', [ @@ -114,11 +139,17 @@ public function getPlotsByOwner(string $owner, string $levelName = "") : \Genera } $plots = []; foreach($rows as $row){ - $plots[] = new Plot($row['level'], $row['X'], $row['Z'], $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + $plots[] = new SinglePlot($row['level'], $row['X'], $row['Z'], $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); } return $plots; } + /** + * @param string $levelName + * @param int $limitXZ + * + * @return \Generator + */ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : \Generator{ for($i = 0; $limitXZ <= 0 or $i < $limitXZ; $i++){ $rows = yield $this->database->asyncSelect('myplot.get.highest-existing.by-interval', [ @@ -135,14 +166,20 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : \Generato for($a = 0; $a <= $i; $a++){ if(($ret = self::findEmptyPlotSquared($a, $i, $plots)) !== null){ [$X, $Z] = $ret; - return new Plot($levelName, $X, $Z); + return new BasePlot($levelName, $X, $Z); } } } return null; } - public function mergePlots(Plot $base, Plot ...$plots) : \Generator{ + /** + * @param BasePlot $base + * @param BasePlot ...$plots + * + * @return \Generator + */ + public function mergePlots(BasePlot $base, BasePlot ...$plots) : \Generator{ $ret = true; foreach($plots as $plot){ [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.merge', [ @@ -160,7 +197,13 @@ public function mergePlots(Plot $base, Plot ...$plots) : \Generator{ return $ret; } - public function getMergedPlots(Plot $plot, bool $adjacent = false) : \Generator{ + /** + * @param BasePlot $plot + * @param bool $adjacent + * + * @return \Generator> + */ + public function getMergedPlots(BasePlot $plot, bool $adjacent = false) : \Generator{ $origin = yield $this->getMergeOrigin($plot); $rows = $this->database->asyncSelect('myplot.get.merge-plots.by-origin', [ 'level' => $plot->levelName, @@ -172,10 +215,10 @@ public function getMergedPlots(Plot $plot, bool $adjacent = false) : \Generator{ $helpers = explode(",", $row["helpers"]); $denied = explode(",", $row["denied"]); $pvp = is_numeric($row["pvp"]) ? (bool) $row["pvp"] : null; - $plots[] = new Plot($row["level"], $row["X"], $row["Z"], $row["name"], $row["owner"], $helpers, $denied, $row["biome"], $pvp, $row["price"]); + $plots[] = new SinglePlot($row["level"], $row["X"], $row["Z"], $row["name"], $row["owner"], $helpers, $denied, $row["biome"], $pvp, $row["price"]); } if($adjacent) - $plots = array_filter($plots, function(Plot $val) use ($plot) : bool{ + $plots = array_filter($plots, function(BasePlot $val) use ($plot) : bool{ foreach(Facing::HORIZONTAL as $i){ if($plot->getSide($i)->isSame($val)) return true; @@ -185,13 +228,31 @@ public function getMergedPlots(Plot $plot, bool $adjacent = false) : \Generator{ return $plots; } - public function getMergeOrigin(Plot $plot) : \Generator{ + /** + * @param BasePlot $plot + * + * @return \Generator + */ + public function getMergeOrigin(BasePlot $plot) : \Generator{ $row = yield $this->database->asyncSelect('myplot.get.merge-origin.by-merged', [ 'level' => $plot->levelName, 'mergedX' => $plot->X, 'mergedZ' => $plot->Z ]); - return new Plot($row['level'], $row['X'], $row['Z'], $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + return new MergedPlot( + $row['level'], + $row['X'], + $row['Z'], + $row['name'], + $row['owner'], + explode(",", $row['helpers']), + explode(",", $row['denied']), + $row['biome'], + $row['pvp'], + $row['price'], + $xWidth, + $zWidth + ); } public function close() : void{ diff --git a/src/MyPlot/provider/EconomyProvider.php b/src/MyPlot/provider/EconomyProvider.php index d986ae4c..123bd055 100644 --- a/src/MyPlot/provider/EconomyProvider.php +++ b/src/MyPlot/provider/EconomyProvider.php @@ -2,11 +2,34 @@ declare(strict_types=1); namespace MyPlot\provider; -use pocketmine\player\IPlayer; use pocketmine\player\Player; interface EconomyProvider { - public function reduceMoney(Player $player, float $amount) : bool; + /** + * @param Player $player + * @param int $amount + * @param string $reason + * + * @return \Generator + */ + public function reduceMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator; - public function addMoney(IPlayer $player, float $amount) : bool; + /** + * @param Player $player + * @param int $amount + * @param string $reason + * + * @return \Generator + */ + public function addMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator; + + /** + * @param Player $player1 + * @param Player $player2 + * @param int $amount + * @param string $reason + * + * @return \Generator + */ + public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = "Unknown") : \Generator; } \ No newline at end of file diff --git a/src/MyPlot/provider/EconomySProvider.php b/src/MyPlot/provider/EconomySProvider.php index 7290330c..b0c3583a 100644 --- a/src/MyPlot/provider/EconomySProvider.php +++ b/src/MyPlot/provider/EconomySProvider.php @@ -5,43 +5,61 @@ use onebone\economyapi\EconomyAPI; use pocketmine\player\IPlayer; use pocketmine\player\Player; +use pocketmine\promise\Promise; +use pocketmine\promise\PromiseResolver; class EconomySProvider implements EconomyProvider { - private EconomyAPI $plugin; + public function __construct(private EconomyAPI $plugin) {} /** - * EconomySProvider constructor. - * - * @param EconomyAPI $plugin + * @inheritDoc */ - public function __construct(EconomyAPI $plugin) { - $this->plugin = $plugin; - } - - public function reduceMoney(Player $player, float $amount) : bool { - if($amount == 0) { + public function reduceMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator { + 0 && yield; + if($amount === 0) { return true; }elseif($amount < 0) { $amount = -$amount; } - $ret = $this->plugin->reduceMoney($player, $amount, true, "MyPlot"); + $ret = $this->plugin->reduceMoney($player, $amount, false, "MyPlot"); if($ret === EconomyAPI::RET_SUCCESS) { $this->plugin->getLogger()->debug("MyPlot Reduced money of " . $player->getName()); return true; } - $this->plugin->getLogger()->debug("MyPlot failed to reduce money of ".$player->getName()); return false; } - public function addMoney(IPlayer $player, float $amount) : bool { - if($amount < 1) + /** + * @inheritDoc + */ + public function addMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator { + 0 && yield; + if($amount === 0) { return true; - $ret = $this->plugin->addMoney($player->getName(), $amount, true, "MyPlot"); + } + $ret = $this->plugin->addMoney($player, $amount, false, "MyPlot"); if($ret === EconomyAPI::RET_SUCCESS) { - $this->plugin->getLogger()->debug("MyPlot Add money of " . $player->getName()); return true; } - $this->plugin->getLogger()->debug("MyPlot failed to add money of ".$player->getName()); return false; } + + /** + * @inheritDoc + */ + public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = "Unknown") : \Generator { + 0 && yield; + if($amount < 1){ + return true; + } + $ret = $this->plugin->reduceMoney($player1, $amount, true, "MyPlot"); + if($ret !== EconomyAPI::RET_SUCCESS) { + return false; + } + $ret = $this->plugin->addMoney($player2, $amount, true, "MyPlot"); + if($ret !== EconomyAPI::RET_SUCCESS) { + return false; + } + return true; + } } \ No newline at end of file From 057d93d424139f5c156ff976b0d319568b3df151 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Wed, 9 Mar 2022 07:16:46 -0500 Subject: [PATCH 35/47] Make the Internal and External APIs consistant --- src/MyPlot/InternalAPI.php | 825 +++++++++++++----- src/MyPlot/MyPlot.php | 380 +++----- src/MyPlot/provider/EconomyWrapper.php | 53 ++ ...ovider.php => InternalCapitalProvider.php} | 2 +- ...ovider.php => InternalEconomyProvider.php} | 2 +- ...vider.php => InternalEconomySProvider.php} | 13 +- 6 files changed, 780 insertions(+), 495 deletions(-) create mode 100644 src/MyPlot/provider/EconomyWrapper.php rename src/MyPlot/provider/{CapitalProvider.php => InternalCapitalProvider.php} (96%) rename src/MyPlot/provider/{EconomyProvider.php => InternalEconomyProvider.php} (95%) rename src/MyPlot/provider/{EconomySProvider.php => InternalEconomySProvider.php} (81%) diff --git a/src/MyPlot/InternalAPI.php b/src/MyPlot/InternalAPI.php index 22a2ff81..c9bfe2b2 100644 --- a/src/MyPlot/InternalAPI.php +++ b/src/MyPlot/InternalAPI.php @@ -7,24 +7,35 @@ use muqsit\worldstyler\shapes\CommonShape; use muqsit\worldstyler\shapes\Cuboid; use muqsit\worldstyler\WorldStyler; +use MyPlot\events\MyPlotClearEvent; +use MyPlot\events\MyPlotCloneEvent; +use MyPlot\events\MyPlotDisposeEvent; +use MyPlot\events\MyPlotFillEvent; use MyPlot\events\MyPlotMergeEvent; +use MyPlot\events\MyPlotResetEvent; +use MyPlot\events\MyPlotSaveEvent; +use MyPlot\events\MyPlotSettingEvent; +use MyPlot\events\MyPlotTeleportEvent; use MyPlot\plot\BasePlot; use MyPlot\plot\MergedPlot; use MyPlot\plot\SinglePlot; use MyPlot\provider\DataProvider; -use MyPlot\provider\EconomyProvider; +use MyPlot\provider\InternalEconomyProvider; use MyPlot\task\ClearBorderTask; use MyPlot\task\ClearPlotTask; use MyPlot\task\FillPlotTask; use MyPlot\task\RoadFillTask; use pocketmine\block\Block; use pocketmine\block\VanillaBlocks; +use pocketmine\data\bedrock\BiomeIds; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; +use pocketmine\promise\PromiseResolver; use pocketmine\utils\TextFormat as TF; use pocketmine\world\biome\Biome; +use pocketmine\world\biome\BiomeRegistry; use pocketmine\world\Position; use pocketmine\world\World; use SOFe\AwaitGenerator\Await; @@ -34,16 +45,16 @@ final class InternalAPI{ private array $levels = []; private DataProvider $dataProvider; - public function __construct(private MyPlot $plugin, private ?EconomyProvider $economyProvider){ + public function __construct(private MyPlot $plugin, private ?InternalEconomyProvider $economyProvider){ $plugin->getLogger()->debug(TF::BOLD . "Loading Data Provider settings"); $this->dataProvider = new DataProvider($plugin); } - public function getEconomyProvider() : ?EconomyProvider { + public function getEconomyProvider() : ?InternalEconomyProvider{ return $this->economyProvider; } - public function setEconomyProvider(?EconomyProvider $economyProvider) : void{ + public function setEconomyProvider(?InternalEconomyProvider $economyProvider) : void{ $this->economyProvider = $economyProvider; } @@ -83,6 +94,9 @@ public function savePlot(SinglePlot $plot, ?callable $onComplete = null, ?callab } public function generatePlotsToSave(SinglePlot $plot) : \Generator{ + $ev = new MyPlotSaveEvent($plot); + $ev->call(); + $plot = $ev->getPlot(); $failed = false; foreach((yield $this->dataProvider->getMergedPlots($plot)) as $merged){ $savePlot = clone $plot; @@ -120,8 +134,7 @@ public function getPlotsOfPlayer(string $username, ?string $levelName, ?callable * @return \Generator> */ public function generatePlotsOfPlayer(string $username, ?string $levelName) : \Generator { - false && yield; - return $this->dataProvider->getPlotsByOwner($username, $levelName); + return yield $this->dataProvider->getPlotsByOwner($username, $levelName); } /** @@ -141,8 +154,7 @@ public function getNextFreePlot(string $levelName, int $limitXZ, ?callable $onCo } public function generateNextFreePlot(string $levelName, int $limitXZ) : \Generator{ - false && yield; - return $this->dataProvider->getNextFreePlot($levelName, $limitXZ); + return yield $this->dataProvider->getNextFreePlot($levelName, $limitXZ); } public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?BasePlot{ @@ -194,9 +206,8 @@ public function getPlot(string $worldName, int $X, int $Z, ?callable $onComplete * @return \Generator */ public function generatePlot(string $worldName, int $X, int $Z) : \Generator { - false && yield; // TODO: if merged return MergedPlot object - return $this->dataProvider->getPlot($worldName, $X, $Z); + return yield $this->dataProvider->getPlot($worldName, $X, $Z); } /** @@ -389,7 +400,7 @@ public function getPlotBB(SinglePlot $plot, ?callable $onComplete = null, ?calla ); } - public function generatePlotBB(SinglePlot $plot) : \Generator{ + public function generatePlotBB(BasePlot $plot) : \Generator{ $plotLevel = $this->getLevelSettings($plot->levelName); $plotSize = $plotLevel->plotSize - 1; $pos = yield $this->generatePlotPosition($plot, false); @@ -524,6 +535,11 @@ public function teleportPlayerToPlot(Player $player, SinglePlot $plot, bool $cen } public function generatePlayerTeleport(Player $player, BasePlot $plot, bool $center) : \Generator{ + $ev = new MyPlotTeleportEvent($plot, $player, $center); + $ev->call(); + if($ev->isCancelled()) + return false; + if($center){ $pos = $plot instanceof MergedPlot ? yield $this->getMergeMid($plot) : yield $this->getPlotMid($plot); return $player->teleport($pos); @@ -591,14 +607,74 @@ private function getMergeMid(SinglePlot $plot) : \Generator{ false ))->z; $maxz = (yield $this->generatePlotPosition( - yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->z > (yield $this->generatePlotPosition($b, false))->z ? $a : $b; - }), - false + yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ + return (yield $this->generatePlotPosition($a, false))->z > (yield $this->generatePlotPosition($b, false))->z ? $a : $b; + }), + false ))->z + $plotSize; return new Position(($minx + $maxx) / 2, $plotLevel->groundHeight, ($minz + $maxz) / 2, $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)); } + /** + * @param SinglePlot $plot + * @param string $claimer + * @param string $plotName + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function claimPlot(SinglePlot $plot, string $claimer, string $plotName, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateClaimPlot($plot, $claimer, $plotName), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateClaimPlot(SinglePlot $plot, string $claimer, string $plotName) : \Generator{ + $newPlot = clone $plot; + $newPlot->owner = $claimer; + $newPlot->helpers = []; + $newPlot->denied = []; + if($plotName !== "") + $newPlot->name = $plotName; + $newPlot->price = 0; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $ev->call(); + if($ev->isCancelled()){ + return false; + } + return yield $this->generatePlotsToSave($ev->getPlot()); + } + + /** + * @param SinglePlot $plot + * @param string $newName + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function renamePlot(SinglePlot $plot, string $newName, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateRenamePlot($plot, $newName), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateRenamePlot(SinglePlot $plot, string $newName) : \Generator{ + $newPlot = clone $plot; + $newPlot->name = $newName; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $ev->call(); + if($ev->isCancelled()){ + return false; + } + return yield $this->generatePlotsToSave($ev->getPlot()); + } + /** * @param SinglePlot $plotFrom * @param SinglePlot $plotTo @@ -608,81 +684,98 @@ private function getMergeMid(SinglePlot $plot) : \Generator{ * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ - public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo, WorldStyler $styler, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::f2c( - function() use ($plotFrom, $plotTo, $styler){ - $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); - $aabb = yield $this->generatePlotBB($plotTo); - foreach($world->getEntities() as $entity){ - if($aabb->isVectorInXZ($entity->getPosition())){ - if($entity instanceof Player){ - $this->generatePlayerTeleport($entity, $plotTo, false); - } - } - } - $plotLevel = $this->getLevelSettings($plotFrom->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plotFrom, true); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = $plotBeginPos->x + $plotSize; - $zMax = $plotBeginPos->z + $plotSize; - foreach(yield $this->dataProvider->getMergedPlots($plotFrom) as $mergedPlot){ - $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); - $xMaxPlot = $pos->x + $plotSize; - $zMaxPlot = $pos->z + $plotSize; - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - $selection = $styler->getSelection(99997) ?? new Selection(99997); - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); // do not use async because WorldStyler async is very broken right now - $cuboid->copy($level, $vec2, function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug(TF::GREEN . 'Copied ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's to the MyPlot clipboard.'); - }); - - $plotLevel = $this->getLevelSettings($plotTo->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plotTo, true); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = $plotBeginPos->x + $plotSize; - $zMax = $plotBeginPos->z + $plotSize; - foreach(yield $this->dataProvider->getMergedPlots($plotTo) as $mergedPlot){ - $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); - $xMaxPlot = $pos->x + $plotSize; - $zMaxPlot = $pos->z + $plotSize; - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); - $commonShape = CommonShape::fromSelection($selection); - //$commonShape = $commonShape->async(); // do not use async because WorldStyler async is very broken right now - $commonShape->paste($level, $vec2, true, function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); - }); - $styler->removeSelection(99997); - foreach((yield $this->generatePlotChunks($plotTo)) as [$chunkX, $chunkZ, $chunk]){ - $level->setChunk($chunkX, $chunkZ, $chunk); - } - return true; - }, + public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateClonePlot($plotFrom, $plotTo), $onComplete, $onFail === null ? [] : [$onFail] ); } + public function generateClonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : \Generator{ + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if(!$styler instanceof WorldStyler){ + return false; + } + $ev = new MyPlotCloneEvent($plotFrom, $plotTo); + $ev->call(); + if($ev->isCancelled()) + return false; + + $plotFrom = $ev->getPlot(); + $plotTo = $ev->getClonePlot(); + if($this->getLevelSettings($plotFrom->levelName) === null or $this->getLevelSettings($plotTo->levelName) === null){ + return false; + } + + $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); + $aabb = yield $this->generatePlotBB($plotTo); + foreach($world->getEntities() as $entity){ + if($aabb->isVectorInXZ($entity->getPosition())){ + if($entity instanceof Player){ + yield $this->generatePlayerTeleport($entity, $plotTo, false); + } + } + } + $plotLevel = $this->getLevelSettings($plotFrom->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plotFrom, true); + $level = $plotBeginPos->getWorld(); + $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); + $plotBeginPos->y = 0; + $xMax = $plotBeginPos->x + $plotSize; + $zMax = $plotBeginPos->z + $plotSize; + foreach(yield $this->dataProvider->getMergedPlots($plotFrom) as $mergedPlot){ + $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); + $xMaxPlot = $pos->x + $plotSize; + $zMaxPlot = $pos->z + $plotSize; + if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; + if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + $selection = $styler->getSelection(99997) ?? new Selection(99997); + $selection->setPosition(1, $plotBeginPos); + $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); + $selection->setPosition(2, $vec2); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); // do not use async because WorldStyler async is very broken right now + $cuboid->copy($level, $vec2, function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug(TF::GREEN . 'Copied ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's to the MyPlot clipboard.'); + }); + + $plotLevel = $this->getLevelSettings($plotTo->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plotTo, true); + $level = $plotBeginPos->getWorld(); + $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); + $plotBeginPos->y = 0; + $xMax = $plotBeginPos->x + $plotSize; + $zMax = $plotBeginPos->z + $plotSize; + foreach(yield $this->dataProvider->getMergedPlots($plotTo) as $mergedPlot){ + $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); + $xMaxPlot = $pos->x + $plotSize; + $zMaxPlot = $pos->z + $plotSize; + if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; + if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + $selection->setPosition(1, $plotBeginPos); + $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); + $selection->setPosition(2, $vec2); + $commonShape = CommonShape::fromSelection($selection); + //$commonShape = $commonShape->async(); // do not use async because WorldStyler async is very broken right now + $commonShape->paste($level, $vec2, true, function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); + }); + $styler->removeSelection(99997); + foreach((yield $this->generatePlotChunks($plotTo)) as [$chunkX, $chunkZ, $chunk]){ + $level->setChunk($chunkX, $chunkZ, $chunk); + } + return true; + } + /** * @param SinglePlot $plot * @param int $maxBlocksPerTick @@ -691,97 +784,110 @@ function() use ($plotFrom, $plotTo, $styler){ * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ - public function clearPlot(SinglePlot $plot, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::f2c( - function() use ($plot, $maxBlocksPerTick) : \Generator{ - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null){ - return false; - } - foreach($level->getEntities() as $entity){ - if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition())){ - if(!$entity instanceof Player){ - $entity->flagForDespawn(); - }else{ - $this->generatePlayerTeleport($entity, $plot, false); - } - } - } - $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if($this->plugin->getConfig()->get("FastClearing", false) === true && $styler instanceof WorldStyler){ - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plot, true); - $xMax = $plotBeginPos->x + $plotSize; - $zMax = $plotBeginPos->z + $plotSize; - foreach(yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot){ - $xplot = (yield $this->generatePlotPosition($mergedPlot, false))->x; - $zplot = (yield $this->generatePlotPosition($mergedPlot, false))->z; - $xMaxPlot = (int) ($xplot + $plotSize); - $zMaxPlot = (int) ($zplot + $plotSize); - if($plotBeginPos->x > $xplot) $plotBeginPos->x = $xplot; - if($plotBeginPos->z > $zplot) $plotBeginPos->z = $zplot; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } - // Above ground - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight + 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, World::Y_MAX, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), VanillaBlocks::AIR()->getFullId(), function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Ground Surface - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFloorBlock->getFullId(), function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Ground - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight - 1, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFillBlock->getFullId(), function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Bottom of world - $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 0; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, 0, $zMax)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - foreach($this->plugin->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ - $plotBeginPos->getWorld()->setChunk($chunkX, $chunkZ, $chunk); - } - $this->plugin->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this->plugin, $plot), 1); - return true; - } - $this->plugin->getScheduler()->scheduleTask(new ClearPlotTask($this->plugin, $plot, $maxBlocksPerTick)); - return true; - }, + public function clearPlot(BasePlot $plot, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateClearPlot($plot, $maxBlocksPerTick), $onComplete, $onFail === null ? [] : [$onFail] ); } + public function generateClearPlot(BasePlot $plot, int $maxBlocksPerTick) : \Generator{ + $ev = new MyPlotClearEvent($plot, $maxBlocksPerTick); + $ev->call(); + if($ev->isCancelled()){ + return false; + } + $plot = $ev->getPlot(); + if($this->getLevelSettings($plot->levelName) === null){ + return false; + } + $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); + + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($level === null){ + return false; + } + foreach($level->getEntities() as $entity){ + if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition())){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->generatePlayerTeleport($entity, $plot, false); + } + } + } + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if($this->plugin->getConfig()->get("FastClearing", false) === true && $styler instanceof WorldStyler){ + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plot, true); + $xMax = $plotBeginPos->x + $plotSize; + $zMax = $plotBeginPos->z + $plotSize; + foreach(yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot){ + $xplot = (yield $this->generatePlotPosition($mergedPlot, false))->x; + $zplot = (yield $this->generatePlotPosition($mergedPlot, false))->z; + $xMaxPlot = (int) ($xplot + $plotSize); + $zMaxPlot = (int) ($zplot + $plotSize); + if($plotBeginPos->x > $xplot) $plotBeginPos->x = $xplot; + if($plotBeginPos->z > $zplot) $plotBeginPos->z = $zplot; + if($xMax < $xMaxPlot) $xMax = $xMaxPlot; + if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + } + // Above ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = $plotLevel->groundHeight + 1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, World::Y_MAX, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), VanillaBlocks::AIR()->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Ground Surface + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = $plotLevel->groundHeight; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFloorBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = 1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight - 1, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Bottom of world + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $plotBeginPos->y = 0; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($xMax, 0, $zMax)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + foreach($this->plugin->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ + $plotBeginPos->getWorld()->setChunk($chunkX, $chunkZ, $chunk); + } + $this->plugin->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this->plugin, $plot), 1); + return true; + } + $this->plugin->getScheduler()->scheduleTask(new ClearPlotTask($this->plugin, $plot, $maxBlocksPerTick)); + return true; + } + /** * @param SinglePlot $plot * @param Block $plotFillBlock @@ -791,61 +897,74 @@ function() use ($plot, $maxBlocksPerTick) : \Generator{ * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ - public function fillPlot(SinglePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::f2c( - function() use ($plot, $plotFillBlock, $maxBlocksPerTick){ - foreach($this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)->getEntities() as $entity){ - if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition()) && $entity->getPosition()->y <= $this->getLevelSettings($plot->levelName)->groundHeight){ - if(!$entity instanceof Player){ - $entity->flagForDespawn(); - }else{ - $this->generatePlayerTeleport($entity, $plot, false); - } - } - } - if($this->plugin->getConfig()->get("FastFilling", false) === true){ - $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if(!$styler instanceof WorldStyler){ - return false; - } - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plot, false); - // Ground - $selection = $styler->getSelection(99998); - $plotBeginPos->y = 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, $plotLevel->groundHeight, $plotBeginPos->z + $plotSize)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotFillBlock->getFullId(), function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - // Bottom of world - $selection = $styler->getSelection(99998); - $plotBeginPos->y = 0; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, 0, $plotBeginPos->z + $plotSize)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - foreach((yield $this->generatePlotChunks($plot)) as [$chunkX, $chunkZ, $chunk]){ - $plotBeginPos->getWorld()?->setChunk($chunkX, $chunkZ, $chunk); - } - return true; - } - $this->plugin->getScheduler()->scheduleTask(new FillPlotTask($this->plugin, $plot, $plotFillBlock, $maxBlocksPerTick)); - return true; - }, + public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateFillPlot($plot, $plotFillBlock, $maxBlocksPerTick), $onComplete, $onFail === null ? [] : [$onFail] ); } + public function generateFillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick) : \Generator{ + $ev = new MyPlotFillEvent($plot, $maxBlocksPerTick); + $ev->call(); + if($ev->isCancelled()){ + return false; + } + $plot = $ev->getPlot(); + if($this->getLevelSettings($plot->levelName) === null){ + return false; + } + $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); + + foreach($this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)->getEntities() as $entity){ + if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition()) && $entity->getPosition()->y <= $this->getLevelSettings($plot->levelName)->groundHeight){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->generatePlayerTeleport($entity, $plot, false); + } + } + } + if($this->plugin->getConfig()->get("FastFilling", false) === true){ + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if(!$styler instanceof WorldStyler){ + return false; + } + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize - 1; + $plotBeginPos = yield $this->generatePlotPosition($plot, false); + // Ground + $selection = $styler->getSelection(99998); + $plotBeginPos->y = 1; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, $plotLevel->groundHeight, $plotBeginPos->z + $plotSize)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + // Bottom of world + $selection = $styler->getSelection(99998); + $plotBeginPos->y = 0; + $selection->setPosition(1, $plotBeginPos); + $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, 0, $plotBeginPos->z + $plotSize)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + foreach((yield $this->generatePlotChunks($plot)) as [$chunkX, $chunkZ, $chunk]){ + $plotBeginPos->getWorld()?->setChunk($chunkX, $chunkZ, $chunk); + } + return true; + } + $this->plugin->getScheduler()->scheduleTask(new FillPlotTask($this->plugin, $plot, $plotFillBlock, $maxBlocksPerTick)); + return true; + } + /** * @param SinglePlot $plot * @param callable|null $onComplete @@ -853,37 +972,55 @@ function() use ($plot, $plotFillBlock, $maxBlocksPerTick){ * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ - public function disposePlot(SinglePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ + public function disposePlot(BasePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ Await::g2c( - $this->dataProvider->deletePlot($plot), + $this->generateDisposePlot($plot), $onComplete, $onFail === null ? [] : [$onFail] ); } + public function generateDisposePlot(BasePlot $plot) : \Generator{ + $ev = new MyPlotDisposeEvent($plot); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + return yield $this->dataProvider->deletePlot($plot); + } + /** * @param SinglePlot $plot * @param int $maxBlocksPerTick * @param callable|null $onComplete - * @phpstan-param (callable(bool): void)|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - * - * @noinspection PhpVoidFunctionResultUsedInspection + * @phpstan-param (callable(\Throwable): void)|null $catches */ public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ - $this->disposePlot( - $plot, - fn(bool $success) => $success && $this->clearPlot( - $plot, - $maxBlocksPerTick, - $onComplete, - $onFail - ), - $onFail + Await::g2c( + $this->generateResetPlot($plot, $maxBlocksPerTick), + $onComplete, + $onFail === null ? [] : [$onFail] ); } + public function generateResetPlot(SinglePlot $plot, int $maxBlocksPerTick) : \Generator{ + $ev = new MyPlotResetEvent($plot); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + if(!yield $this->generateDisposePlot($plot)){ + return false; + } + if(!yield $this->generateClearPlot($plot, $maxBlocksPerTick)){ + yield $this->generatePlotsToSave($plot); + return false; + } + return true; + } + /** * @param SinglePlot $plot * @param Biome $biome @@ -901,6 +1038,23 @@ public function setPlotBiome(SinglePlot $plot, Biome $biome, ?callable $onComple } public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ + $newPlot = clone $plot; + $newPlot->biome = str_replace(" ", "_", strtoupper($biome->getName())); + $ev = new MyPlotSettingEvent($plot, $newPlot); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + if(defined(BiomeIds::class . "::" . $plot->biome) and is_int(constant(BiomeIds::class . "::" . $plot->biome))){ + $biome = constant(BiomeIds::class . "::" . $plot->biome); + }else{ + $biome = BiomeIds::PLAINS; + } + $biome = BiomeRegistry::getInstance()->getBiome($biome); + if($this->getLevelSettings($plot->levelName) === null){ + return false; + } + $failed = false; foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ $merged->biome = $plot->biome; @@ -927,6 +1081,203 @@ public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ return !$failed; } + /** + * @param SinglePlot $plot + * @param bool $pvp + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function setPlotPvp(SinglePlot $plot, bool $pvp, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlotPvp($plot, $pvp), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generatePlotPvp(SinglePlot $plot, bool $pvp) : \Generator{ + $newPlot = clone $plot; + $newPlot->pvp = $pvp; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + return yield $this->dataProvider->savePlot($plot); + } + + /** + * @param SinglePlot $plot + * @param string $player + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function addPlotHelper(SinglePlot $plot, string $player, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateAddPlotHelper($plot, $player), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateAddPlotHelper(SinglePlot $plot, string $player) : \Generator{ + $newPlot = clone $plot; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $newPlot->addHelper($player) ? $ev->uncancel() : $ev->cancel(); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + return yield $this->dataProvider->savePlot($plot); + } + + /** + * @param SinglePlot $plot + * @param string $player + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function removePlotHelper(SinglePlot $plot, string $player, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateRemovePlotHelper($plot, $player), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateRemovePlotHelper(SinglePlot $plot, string $player) : \Generator{ + $newPlot = clone $plot; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $newPlot->removeHelper($player) ? $ev->uncancel() : $ev->cancel(); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + return yield $this->dataProvider->savePlot($plot); + } + + /** + * @param SinglePlot $plot + * @param string $player + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function addPlotDenied(SinglePlot $plot, string $player, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateAddPlotDenied($plot, $player), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateAddPlotDenied(SinglePlot $plot, string $player) : \Generator{ + $newPlot = clone $plot; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $newPlot->denyPlayer($player) ? $ev->uncancel() : $ev->cancel(); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + return yield $this->dataProvider->savePlot($plot); + } + + /** + * @param SinglePlot $plot + * @param string $player + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function removePlotDenied(SinglePlot $plot, string $player, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateRemovePlotDenied($plot, $player), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateRemovePlotDenied(SinglePlot $plot, string $player) : \Generator{ + $newPlot = clone $plot; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $newPlot->unDenyPlayer($player) ? $ev->uncancel() : $ev->cancel(); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + return yield $this->dataProvider->savePlot($plot); + } + + /** + * @param SinglePlot $plot + * @param int $price + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function sellPlot(SinglePlot $plot, int $price, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateSellPlot($plot, $price), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateSellPlot(SinglePlot $plot, int $price) : \Generator{ + if($this->economyProvider === null or $price <= 0){ + return false; + } + + $newPlot = clone $plot; + $newPlot->price = $price; + $ev = new MyPlotSettingEvent($plot, $newPlot); + $ev->call(); + if($ev->isCancelled()) + return false; + $plot = $ev->getPlot(); + return yield $this->dataProvider->savePlot($plot); + } + + /** + * @param SinglePlot $plot + * @param Player $player + * @param callable|null $onComplete + * @phpstan-param (callable(bool): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function buyPlot(SinglePlot $plot, Player $player, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generateBuyPlot($plot, $player), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + public function generateBuyPlot(SinglePlot $plot, Player $player) : \Generator{ + if($this->economyProvider === null){ + return false; + } + if(!yield $this->economyProvider->reduceMoney($player, $plot->price)){ + return false; + } + if(!yield $this->economyProvider->addMoney($this->plugin->getServer()->getOfflinePlayer($plot->owner), $plot->price)){ + yield $this->economyProvider->addMoney($player, $plot->price); + return false; + } + + return yield $this->generateClaimPlot($plot, $player->getName(), ''); + } + /** * @param SinglePlot $plot * @param callable|null $onComplete @@ -942,7 +1293,7 @@ public function getPlotChunks(SinglePlot $plot, ?callable $onComplete = null, ?c ); } - public function generatePlotChunks(SinglePlot $plot) : \Generator{ + public function generatePlotChunks(BasePlot $plot) : \Generator{ $plotLevel = $this->getLevelSettings($plot->levelName); if($plotLevel === null){ return []; diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index cbeaf1be..71851b30 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -2,23 +2,15 @@ declare(strict_types=1); namespace MyPlot; -use muqsit\worldstyler\WorldStyler; -use MyPlot\events\MyPlotClearEvent; -use MyPlot\events\MyPlotCloneEvent; -use MyPlot\events\MyPlotDisposeEvent; -use MyPlot\events\MyPlotFillEvent; use MyPlot\events\MyPlotGenerationEvent; -use MyPlot\events\MyPlotResetEvent; -use MyPlot\events\MyPlotSettingEvent; -use MyPlot\events\MyPlotTeleportEvent; use MyPlot\plot\BasePlot; use MyPlot\plot\SinglePlot; -use MyPlot\provider\CapitalProvider; -use MyPlot\provider\EconomyProvider; -use MyPlot\provider\EconomySProvider; +use MyPlot\provider\EconomyWrapper; +use MyPlot\provider\InternalCapitalProvider; +use MyPlot\provider\InternalEconomyProvider; +use MyPlot\provider\InternalEconomySProvider; use onebone\economyapi\EconomyAPI; use pocketmine\block\Block; -use pocketmine\data\bedrock\BiomeIds; use pocketmine\lang\Language; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; @@ -33,7 +25,6 @@ use pocketmine\utils\Config; use pocketmine\utils\TextFormat as TF; use pocketmine\world\biome\Biome; -use pocketmine\world\biome\BiomeRegistry; use pocketmine\world\format\Chunk; use pocketmine\world\generator\GeneratorManager; use pocketmine\world\Position; @@ -45,6 +36,7 @@ class MyPlot extends PluginBase private static MyPlot $instance; private Language $language; private InternalAPI $internalAPI; + private ?EconomyWrapper $economyProvider; public static function getInstance() : self { return self::$instance; @@ -75,30 +67,32 @@ public function getFallBackLang() : Language { /** * Returns the EconomyProvider that is being used * + * @return InternalEconomyProvider|null * @api * - * @return EconomyProvider|null */ - public function getEconomyProvider() : ?EconomyProvider { - return $this->internalAPI->getEconomyProvider(); + public function getEconomyProvider() : ?EconomyWrapper{ + return $this->economyProvider; } /** * Allows setting the economy provider to a custom provider or to null to disable economy mode * + * @param bool $enable + * * @api * - * @param EconomyProvider|null $provider */ - public function setEconomyProvider(?EconomyProvider $provider) : void { - if($provider === null) { + public function toggleEconomy(bool $enable) : void{ + if(!$enable){ + $this->getLogger()->info("Economy mode has been disabled via API"); + $this->internalAPI->setEconomyProvider(null); + $this->economyProvider = null; $this->getConfig()->set("UseEconomy", false); - $this->getLogger()->info("Economy mode disabled!"); }else{ - $this->getConfig()->set("UseEconomy", true); - $this->getLogger()->info("A custom economy provider has been registered. Economy mode now enabled!"); + $this->getLogger()->info("Economy mode has been enabled via API"); + $this->internalAPI->setEconomyProvider($this->checkEconomy()); } - $this->internalAPI->setEconomyProvider($provider); } /** @@ -108,7 +102,7 @@ public function setEconomyProvider(?EconomyProvider $provider) : void { * * @return PlotLevelSettings[] */ - public function getPlotLevels() : array { + public function getAllLevelSettings() : array{ return $this->internalAPI->getAllLevelSettings(); } @@ -152,7 +146,6 @@ public function unloadLevelSettings(string $levelName) : bool { return $this->internalAPI->unloadLevelSettings($levelName); } - /** * Generate a new plot level with optional settings * @@ -408,12 +401,6 @@ public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTi */ public function teleportPlayerToPlot(Player $player, BasePlot $plot, bool $center = false) : Promise { $resolver = new PromiseResolver(); - $ev = new MyPlotTeleportEvent($plot, $player, $center); - $ev->call(); - if($ev->isCancelled()){ - $resolver->resolve(false); - return $resolver->getPromise(); - } $this->internalAPI->teleportPlayerToPlot( $player, $plot, @@ -437,21 +424,15 @@ public function teleportPlayerToPlot(Player $player, BasePlot $plot, bool $cente * @phpstan-return Promise */ public function claimPlot(SinglePlot $plot, string $claimer, string $plotName = "") : Promise{ - $newPlot = clone $plot; - $newPlot->owner = $claimer; - $newPlot->helpers = []; - $newPlot->denied = []; - if($plotName !== "") - $newPlot->name = $plotName; - $newPlot->price = 0; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $ev->call(); - if($ev->isCancelled()){ - $resolver = new PromiseResolver(); - $resolver->resolve(false); - return $resolver->getPromise(); - } - return $this->savePlot($ev->getPlot()); + $resolver = new PromiseResolver(); + $this->internalAPI->claimPlot( + $plot, + $claimer, + $plotName, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -466,16 +447,14 @@ public function claimPlot(SinglePlot $plot, string $claimer, string $plotName = * @phpstan-return Promise */ public function renamePlot(SinglePlot $plot, string $newName = "") : Promise{ - $newPlot = clone $plot; - $newPlot->name = $newName; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $ev->call(); - if($ev->isCancelled()){ - $resolver = new PromiseResolver(); - $resolver->resolve(false); - return $resolver->getPromise(); - } - return $this->savePlot($ev->getPlot()); + $resolver = new PromiseResolver(); + $this->internalAPI->renamePlot( + $plot, + $newName, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -491,27 +470,9 @@ public function renamePlot(SinglePlot $plot, string $newName = "") : Promise{ */ public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : Promise { $resolver = new PromiseResolver(); - $styler = $this->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if(!$styler instanceof WorldStyler) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $ev = new MyPlotCloneEvent($plotFrom, $plotTo); - $ev->call(); - if($ev->isCancelled()) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $plotFrom = $ev->getPlot(); - $plotTo = $ev->getClonePlot(); - if($this->internalAPI->getLevelSettings($plotFrom->levelName) === null or $this->internalAPI->getLevelSettings($plotTo->levelName) === null) { - $resolver->resolve(false); - return $resolver->getPromise(); - } $this->internalAPI->clonePlot( $plotFrom, $plotTo, - $styler, fn(bool $success) => $resolver->resolve($success), fn(\Throwable $e) => $resolver->reject() ); @@ -529,20 +490,8 @@ public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : Promise { * @return Promise * @phpstan-return Promise */ - public function clearPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promise { + public function clearPlot(BasePlot $plot, int $maxBlocksPerTick = 256) : Promise{ $resolver = new PromiseResolver(); - $ev = new MyPlotClearEvent($plot, $maxBlocksPerTick); - $ev->call(); - if($ev->isCancelled()) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $plot = $ev->getPlot(); - if($this->internalAPI->getLevelSettings($plot->levelName) === null) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); $this->internalAPI->clearPlot( $plot, $maxBlocksPerTick, @@ -564,20 +513,8 @@ public function clearPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promi * @return Promise * @phpstan-return Promise */ - public function fillPlot(SinglePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick = 256) : Promise { + public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick = 256) : Promise{ $resolver = new PromiseResolver(); - $ev = new MyPlotFillEvent($plot, $maxBlocksPerTick); - $ev->call(); - if($ev->isCancelled()) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $plot = $ev->getPlot(); - if($this->internalAPI->getLevelSettings($plot->levelName) === null) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); $this->internalAPI->fillPlot( $plot, $plotFillBlock, @@ -600,13 +537,6 @@ public function fillPlot(SinglePlot $plot, Block $plotFillBlock, int $maxBlocksP */ public function disposePlot(SinglePlot $plot) : Promise { $resolver = new PromiseResolver(); - $ev = new MyPlotDisposeEvent($plot); - $ev->call(); - if($ev->isCancelled()) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $plot = $ev->getPlot(); $this->internalAPI->disposePlot( $plot, fn(bool $success) => $resolver->resolve($success), @@ -628,13 +558,6 @@ public function disposePlot(SinglePlot $plot) : Promise { */ public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promise { $resolver = new PromiseResolver(); - $ev = new MyPlotResetEvent($plot); - $ev->call(); - if($ev->isCancelled()) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $plot = $ev->getPlot(); $this->internalAPI->resetPlot( $plot, $maxBlocksPerTick, @@ -657,25 +580,6 @@ public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promi */ public function setPlotBiome(SinglePlot $plot, Biome $biome) : Promise { $resolver = new PromiseResolver(); - $newPlot = clone $plot; - $newPlot->biome = str_replace(" ", "_", strtoupper($biome->getName())); - $ev = new MyPlotSettingEvent($plot, $newPlot); - $ev->call(); - if($ev->isCancelled()) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $plot = $ev->getPlot(); - if(defined(BiomeIds::class."::".$plot->biome) and is_int(constant(BiomeIds::class."::".$plot->biome))) { - $biome = constant(BiomeIds::class."::".$plot->biome); - }else{ - $biome = BiomeIds::PLAINS; - } - $biome = BiomeRegistry::getInstance()->getBiome($biome); - if($this->internalAPI->getLevelSettings($plot->levelName) === null){ - $resolver->resolve(false); - return $resolver->getPromise(); - } $this->internalAPI->setPlotBiome( $plot, $biome, @@ -696,17 +600,15 @@ public function setPlotBiome(SinglePlot $plot, Biome $biome) : Promise { * @return Promise * @phpstan-return Promise */ - public function setPlotPvp(SinglePlot $plot, bool $pvp) : Promise { - $newPlot = clone $plot; - $newPlot->pvp = $pvp; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $ev->call(); - if($ev->isCancelled()) { - $resolver = new PromiseResolver(); - $resolver->resolve(false); - return $resolver->getPromise(); - } - return $this->savePlot($ev->getPlot()); + public function setPlotPvp(SinglePlot $plot, bool $pvp) : Promise{ + $resolver = new PromiseResolver(); + $this->internalAPI->setPlotPvp( + $plot, + $pvp, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -720,17 +622,15 @@ public function setPlotPvp(SinglePlot $plot, bool $pvp) : Promise { * @return Promise * @phpstan-return Promise */ - public function addPlotHelper(SinglePlot $plot, string $player) : Promise { - $newPlot = clone $plot; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $newPlot->addHelper($player) ? $ev->uncancel() : $ev->cancel(); - $ev->call(); - if($ev->isCancelled()) { - $resolver = new PromiseResolver(); - $resolver->resolve(false); - return $resolver->getPromise(); - } - return $this->savePlot($ev->getPlot()); + public function addPlotHelper(SinglePlot $plot, string $player) : Promise{ + $resolver = new PromiseResolver(); + $this->internalAPI->addPlotHelper( + $plot, + $player, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -744,17 +644,15 @@ public function addPlotHelper(SinglePlot $plot, string $player) : Promise { * @return Promise * @phpstan-return Promise */ - public function removePlotHelper(SinglePlot $plot, string $player) : Promise { - $newPlot = clone $plot; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $newPlot->removeHelper($player) ? $ev->uncancel() : $ev->cancel(); - $ev->call(); - if($ev->isCancelled()) { - $resolver = new PromiseResolver(); - $resolver->resolve(false); - return $resolver->getPromise(); - } - return $this->savePlot($ev->getPlot()); + public function removePlotHelper(SinglePlot $plot, string $player) : Promise{ + $resolver = new PromiseResolver(); + $this->internalAPI->removePlotHelper( + $plot, + $player, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -768,17 +666,15 @@ public function removePlotHelper(SinglePlot $plot, string $player) : Promise { * @return Promise * @phpstan-return Promise */ - public function addPlotDenied(SinglePlot $plot, string $player) : Promise { - $newPlot = clone $plot; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $newPlot->denyPlayer($player) ? $ev->uncancel() : $ev->cancel(); - $ev->call(); - if($ev->isCancelled()) { - $resolver = new PromiseResolver(); - $resolver->resolve(false); - return $resolver->getPromise(); - } - return $this->savePlot($ev->getPlot()); + public function addPlotDenied(SinglePlot $plot, string $player) : Promise{ + $resolver = new PromiseResolver(); + $this->internalAPI->addPlotDenied( + $plot, + $player, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -792,17 +688,15 @@ public function addPlotDenied(SinglePlot $plot, string $player) : Promise { * @return Promise * @phpstan-return Promise */ - public function removePlotDenied(SinglePlot $plot, string $player) : Promise { - $newPlot = clone $plot; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $newPlot->unDenyPlayer($player) ? $ev->uncancel() : $ev->cancel(); - $ev->call(); - if($ev->isCancelled()) { - $resolver = new PromiseResolver(); - $resolver->resolve(false); - return $resolver->getPromise(); - } - return $this->savePlot($ev->getPlot()); + public function removePlotDenied(SinglePlot $plot, string $player) : Promise{ + $resolver = new PromiseResolver(); + $this->internalAPI->removePlotDenied( + $plot, + $player, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -816,23 +710,15 @@ public function removePlotDenied(SinglePlot $plot, string $player) : Promise { * @return Promise * @phpstan-return Promise */ - public function sellPlot(SinglePlot $plot, int $price) : Promise { + public function sellPlot(SinglePlot $plot, int $price) : Promise{ $resolver = new PromiseResolver(); - if($this->internalAPI->getEconomyProvider() === null or $price <= 0) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - - $newPlot = clone $plot; - $newPlot->price = $price; - $ev = new MyPlotSettingEvent($plot, $newPlot); - $ev->call(); - if($ev->isCancelled()) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - $plot = $ev->getPlot(); - return $this->savePlot($plot); + $this->internalAPI->sellPlot( + $plot, + $price, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -846,23 +732,15 @@ public function sellPlot(SinglePlot $plot, int $price) : Promise { * @return Promise * @phpstan-return Promise */ - public function buyPlot(SinglePlot $plot, Player $player) : Promise { + public function buyPlot(SinglePlot $plot, Player $player) : Promise{ $resolver = new PromiseResolver(); - if($this->internalAPI->getEconomyProvider() === null) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - if(!$this->economyProvider->reduceMoney($player, $plot->price)) { - $resolver->resolve(false); - return $resolver->getPromise(); - } - if(!$this->economyProvider->addMoney($this->getServer()->getOfflinePlayer($plot->owner), $plot->price)) { - $this->economyProvider->addMoney($player, $plot->price); - $resolver->resolve(false); - return $resolver->getPromise(); - } - - return $this->claimPlot($plot, $player->getName()); + $this->internalAPI->buyPlot( + $plot, + $player, + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); } /** @@ -908,9 +786,9 @@ public function getMaxPlotsOfPlayer(Player $player) : int { * @var string $name * @var Permission $perm */ - foreach($perms as $name => $perm) { + foreach($perms as $name => $perm){ $maxPlots = substr($name, 18); - if(is_numeric($maxPlots)) { + if(is_numeric($maxPlots)){ return (int) $maxPlots; } } @@ -919,6 +797,33 @@ public function getMaxPlotsOfPlayer(Player $player) : int { /* -------------------------- Non-API part -------------------------- */ + private function checkEconomy() : InternalEconomySProvider{ + $this->getLogger()->debug(TF::BOLD . "Loading economy settings"); + $this->economyProvider = $economyProvider = null; + if(($plugin = $this->getServer()->getPluginManager()->getPlugin("EconomyAPI")) !== null){ + if($plugin instanceof EconomyAPI){ + $economyProvider = new InternalEconomySProvider($plugin); + $this->economyProvider = new EconomyWrapper($economyProvider); + $this->getLogger()->info("Economy set to EconomyAPI"); + }else + $this->getLogger()->debug("Invalid instance of EconomyAPI"); + } + if(($plugin = $this->getServer()->getPluginManager()->getPlugin("Capital")) !== null){ + if($plugin instanceof Capital){ + $economyProvider = new InternalCapitalProvider(); + $this->economyProvider = new EconomyWrapper($economyProvider); + $this->getLogger()->info("Economy set to Capital"); + }else + $this->getLogger()->debug("Invalid instance of Capital"); + } + if(!isset($economyProvider)){ + $this->getLogger()->warning("No supported economy plugin found!"); + $this->getConfig()->set("UseEconomy", false); + //$this->getConfig()->save(); + } + return $economyProvider; + } + public function onLoad() : void{ self::$instance = $this; @@ -954,36 +859,15 @@ public function onLoad() : void{ } $this->getLogger()->debug(TF::BOLD . "Loading Plot Clearing settings"); // TODO: finish libEfficientWE - if($this->getConfig()->get("FastClearing", false) === true and $this->getServer()->getPluginManager()->getPlugin("WorldStyler") === null) { + if($this->getConfig()->get("FastClearing", false) === true and $this->getServer()->getPluginManager()->getPlugin("WorldStyler") === null){ $this->getConfig()->set("FastClearing", false); $this->getLogger()->info(TF::BOLD . "WorldStyler not found. Legacy clearing will be used."); } - $this->getLogger()->debug(TF::BOLD . "Loading economy settings"); - $economyProvider = null; - if($this->getConfig()->get("UseEconomy", false) === true) { - if(($plugin = $this->getServer()->getPluginManager()->getPlugin("EconomyAPI")) !== null) { - if($plugin instanceof EconomyAPI) { - $economyProvider = new EconomySProvider($plugin); - $this->getLogger()->debug("Economy set to EconomyAPI"); - }else - $this->getLogger()->debug("Invalid instance of EconomyAPI"); - } - if(($plugin = $this->getServer()->getPluginManager()->getPlugin("Capital")) !== null) { - if($plugin instanceof Capital) { - $economyProvider = new CapitalProvider(); - $this->getLogger()->debug("Economy set to Capital"); - }else - $this->getLogger()->debug("Invalid instance of Capital"); - } - if(!isset($economyProvider)) { - $this->getLogger()->warning("No supported economy plugin found!"); - $this->getConfig()->set("UseEconomy", false); - //$this->getConfig()->save(); - } - } - - $this->internalAPI = new InternalAPI($this, $economyProvider); + $this->internalAPI = new InternalAPI( + $this, + $this->getConfig()->get("UseEconomy", false) === true ? $this->checkEconomy() : null + ); $this->getLogger()->debug(TF::BOLD . "Loading MyPlot Commands"); $this->getServer()->getCommandMap()->register("myplot", new Commands($this, $this->internalAPI)); diff --git a/src/MyPlot/provider/EconomyWrapper.php b/src/MyPlot/provider/EconomyWrapper.php new file mode 100644 index 00000000..fff6d544 --- /dev/null +++ b/src/MyPlot/provider/EconomyWrapper.php @@ -0,0 +1,53 @@ +provider->reduceMoney($player, $amount, $reason), + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); + } + + /** + * @inheritDoc + */ + public function addMoney(Player $player, int $amount, string $reason = "Unknown") : Promise{ + $resolver = new PromiseResolver(); + Await::g2c( + $this->provider->addMoney($player, $amount, $reason), + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); + } + + /** + * @inheritDoc + */ + public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = "Unknown") : Promise{ + $resolver = new PromiseResolver(); + Await::g2c( + $this->provider->transactMoney($player1, $player2, $amount, $reason), + fn(bool $success) => $resolver->resolve($success), + fn(\Throwable $e) => $resolver->reject() + ); + return $resolver->getPromise(); + } +} \ No newline at end of file diff --git a/src/MyPlot/provider/CapitalProvider.php b/src/MyPlot/provider/InternalCapitalProvider.php similarity index 96% rename from src/MyPlot/provider/CapitalProvider.php rename to src/MyPlot/provider/InternalCapitalProvider.php index 6a554a9b..cbac080d 100644 --- a/src/MyPlot/provider/CapitalProvider.php +++ b/src/MyPlot/provider/InternalCapitalProvider.php @@ -8,7 +8,7 @@ use SOFe\Capital\Plugin\MainClass; use SOFe\Capital\Schema; -class CapitalProvider implements EconomyProvider{ +class InternalCapitalProvider implements InternalEconomyProvider{ private Schema\Complete $selector; diff --git a/src/MyPlot/provider/EconomyProvider.php b/src/MyPlot/provider/InternalEconomyProvider.php similarity index 95% rename from src/MyPlot/provider/EconomyProvider.php rename to src/MyPlot/provider/InternalEconomyProvider.php index 123bd055..e511217d 100644 --- a/src/MyPlot/provider/EconomyProvider.php +++ b/src/MyPlot/provider/InternalEconomyProvider.php @@ -4,7 +4,7 @@ use pocketmine\player\Player; -interface EconomyProvider { +interface InternalEconomyProvider{ /** * @param Player $player * @param int $amount diff --git a/src/MyPlot/provider/EconomySProvider.php b/src/MyPlot/provider/InternalEconomySProvider.php similarity index 81% rename from src/MyPlot/provider/EconomySProvider.php rename to src/MyPlot/provider/InternalEconomySProvider.php index b0c3583a..43e9c246 100644 --- a/src/MyPlot/provider/EconomySProvider.php +++ b/src/MyPlot/provider/InternalEconomySProvider.php @@ -3,22 +3,19 @@ namespace MyPlot\provider; use onebone\economyapi\EconomyAPI; -use pocketmine\player\IPlayer; use pocketmine\player\Player; -use pocketmine\promise\Promise; -use pocketmine\promise\PromiseResolver; -class EconomySProvider implements EconomyProvider { - public function __construct(private EconomyAPI $plugin) {} +class InternalEconomySProvider implements InternalEconomyProvider{ + public function __construct(private EconomyAPI $plugin){ } /** * @inheritDoc */ - public function reduceMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator { + public function reduceMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator{ 0 && yield; - if($amount === 0) { + if($amount === 0){ return true; - }elseif($amount < 0) { + }elseif($amount < 0){ $amount = -$amount; } $ret = $this->plugin->reduceMoney($player, $amount, false, "MyPlot"); From e92efbb26e180837eb916acdab309f4fd684aa31 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Wed, 9 Mar 2022 07:54:43 -0500 Subject: [PATCH 36/47] Updated subcommands to use new API --- src/MyPlot/Commands.php | 131 ++++++------- src/MyPlot/subcommand/AddHelperSubCommand.php | 58 +++--- src/MyPlot/subcommand/AutoSubCommand.php | 43 +++-- src/MyPlot/subcommand/BiomeSubCommand.php | 99 +++++----- src/MyPlot/subcommand/BuySubCommand.php | 89 +++++---- src/MyPlot/subcommand/ClaimSubCommand.php | 91 ++++----- src/MyPlot/subcommand/ClearSubCommand.php | 66 +++---- src/MyPlot/subcommand/CloneSubCommand.php | 81 ++++---- .../subcommand/DenyPlayerSubCommand.php | 104 ++++++----- src/MyPlot/subcommand/DisposeSubCommand.php | 59 +++--- src/MyPlot/subcommand/FillSubCommand.php | 67 ++++--- src/MyPlot/subcommand/GenerateSubCommand.php | 44 +++-- src/MyPlot/subcommand/GiveSubCommand.php | 101 +++++----- src/MyPlot/subcommand/HelpSubCommand.php | 26 +-- src/MyPlot/subcommand/HomeSubCommand.php | 79 ++++---- src/MyPlot/subcommand/HomesSubCommand.php | 49 ++--- src/MyPlot/subcommand/InfoSubCommand.php | 82 ++++----- src/MyPlot/subcommand/KickSubCommand.php | 76 ++++---- src/MyPlot/subcommand/ListSubCommand.php | 69 +++---- src/MyPlot/subcommand/MergeSubCommand.php | 173 +++++++++--------- src/MyPlot/subcommand/MiddleSubCommand.php | 42 +++-- src/MyPlot/subcommand/MyPlotSubCommand.php | 27 +++ src/MyPlot/subcommand/NameSubCommand.php | 47 ++--- src/MyPlot/subcommand/PvpSubCommand.php | 49 ++--- .../subcommand/RemoveHelperSubCommand.php | 56 +++--- src/MyPlot/subcommand/ResetSubCommand.php | 64 +++---- src/MyPlot/subcommand/SellSubCommand.php | 61 +++--- src/MyPlot/subcommand/SetOwnerSubCommand.php | 55 +++--- src/MyPlot/subcommand/SubCommand.php | 60 ++---- src/MyPlot/subcommand/UnDenySubCommand.php | 60 +++--- src/MyPlot/subcommand/WarpSubCommand.php | 60 +++--- 31 files changed, 1098 insertions(+), 1070 deletions(-) create mode 100644 src/MyPlot/subcommand/MyPlotSubCommand.php diff --git a/src/MyPlot/Commands.php b/src/MyPlot/Commands.php index 43f4a51e..36cb5875 100644 --- a/src/MyPlot/Commands.php +++ b/src/MyPlot/Commands.php @@ -24,19 +24,18 @@ use MyPlot\subcommand\ListSubCommand; use MyPlot\subcommand\MergeSubCommand; use MyPlot\subcommand\MiddleSubCommand; +use MyPlot\subcommand\MyPlotSubCommand; use MyPlot\subcommand\NameSubCommand; use MyPlot\subcommand\PvpSubCommand; use MyPlot\subcommand\RemoveHelperSubCommand; use MyPlot\subcommand\ResetSubCommand; use MyPlot\subcommand\SellSubCommand; use MyPlot\subcommand\SetOwnerSubCommand; -use MyPlot\subcommand\SubCommand; use MyPlot\subcommand\UnDenySubCommand; use MyPlot\subcommand\WarpSubCommand; use pocketmine\command\Command; use pocketmine\command\CommandSender; use pocketmine\network\mcpe\protocol\AvailableCommandsPacket; -use pocketmine\network\mcpe\protocol\types\command\CommandData; use pocketmine\network\mcpe\protocol\types\command\CommandEnum; use pocketmine\network\mcpe\protocol\types\command\CommandParameter; use pocketmine\player\Player; @@ -44,66 +43,59 @@ use pocketmine\plugin\PluginOwnedTrait; use pocketmine\utils\TextFormat; -class Commands extends Command implements PluginOwned -{ +class Commands extends Command implements PluginOwned{ use PluginOwnedTrait; - /** @var SubCommand[] $subCommands */ + /** @var MyPlotSubCommand[] $subCommands */ private array $subCommands = []; - /** @var SubCommand[] $aliasSubCommands */ + /** @var MyPlotSubCommand[] $aliasSubCommands */ private array $aliasSubCommands = []; - /** - * Commands constructor. - * - * @param MyPlot $plugin - */ - public function __construct(MyPlot $plugin) { - parent::__construct($plugin->getLanguage()->get("command.name"), $plugin->getLanguage()->get("command.desc"), $plugin->getLanguage()->get("command.usage"), [$plugin->getLanguage()->get("command.alias")]); + public function __construct(private MyPlot $owningPlugin, private InternalAPI $internalAPI){ + parent::__construct($owningPlugin->getLanguage()->get("command.name"), $owningPlugin->getLanguage()->get("command.desc"), $owningPlugin->getLanguage()->get("command.usage"), [$owningPlugin->getLanguage()->get("command.alias")]); $this->setPermission("myplot.command"); - $this->owningPlugin = $plugin; - $this->loadSubCommand(new HelpSubCommand($plugin, "help", $this)); - $this->loadSubCommand(new ClaimSubCommand($plugin, "claim")); - $this->loadSubCommand(new GenerateSubCommand($plugin, "generate")); - $this->loadSubCommand(new InfoSubCommand($plugin, "info")); - $this->loadSubCommand(new AddHelperSubCommand($plugin, "addhelper")); - $this->loadSubCommand(new RemoveHelperSubCommand($plugin, "removehelper")); - $this->loadSubCommand(new AutoSubCommand($plugin, "auto")); - $this->loadSubCommand(new ClearSubCommand($plugin, "clear")); - $this->loadSubCommand(new FillSubCommand($plugin, "fill")); - $this->loadSubCommand(new DisposeSubCommand($plugin, "dispose")); - $this->loadSubCommand(new ResetSubCommand($plugin, "reset")); - $this->loadSubCommand(new BiomeSubCommand($plugin, "biome")); - $this->loadSubCommand(new HomeSubCommand($plugin, "home")); - $this->loadSubCommand(new HomesSubCommand($plugin, "homes")); - $this->loadSubCommand(new NameSubCommand($plugin, "name")); - $this->loadSubCommand(new GiveSubCommand($plugin, "give")); - $this->loadSubCommand(new WarpSubCommand($plugin, "warp")); - $this->loadSubCommand(new MiddleSubCommand($plugin, "middle")); - $this->loadSubCommand(new DenyPlayerSubCommand($plugin, "denyplayer")); - $this->loadSubCommand(new UnDenySubCommand($plugin, "undenyplayer")); - $this->loadSubCommand(new SetOwnerSubCommand($plugin, "setowner")); - $this->loadSubCommand(new ListSubCommand($plugin, "list")); - $this->loadSubCommand(new PvpSubCommand($plugin, "pvp")); - $this->loadSubCommand(new KickSubCommand($plugin, "kick")); - $this->loadSubCommand(new MergeSubCommand($plugin, "merge")); - if($plugin->getEconomyProvider() !== null) { - $this->loadSubCommand(new SellSubCommand($plugin, "sell")); - $this->loadSubCommand(new BuySubCommand($plugin, "buy")); + $this->loadSubCommand(new HelpSubCommand($owningPlugin, $internalAPI, "help", $this)); + $this->loadSubCommand(new ClaimSubCommand($owningPlugin, $internalAPI, "claim")); + $this->loadSubCommand(new GenerateSubCommand($owningPlugin, $internalAPI, "generate")); + $this->loadSubCommand(new InfoSubCommand($owningPlugin, $internalAPI, "info")); + $this->loadSubCommand(new AddHelperSubCommand($owningPlugin, $internalAPI, "addhelper")); + $this->loadSubCommand(new RemoveHelperSubCommand($owningPlugin, $internalAPI, "removehelper")); + $this->loadSubCommand(new AutoSubCommand($owningPlugin, $internalAPI, "auto")); + $this->loadSubCommand(new ClearSubCommand($owningPlugin, $internalAPI, "clear")); + $this->loadSubCommand(new FillSubCommand($owningPlugin, $internalAPI, "fill")); + $this->loadSubCommand(new DisposeSubCommand($owningPlugin, $internalAPI, "dispose")); + $this->loadSubCommand(new ResetSubCommand($owningPlugin, $internalAPI, "reset")); + $this->loadSubCommand(new BiomeSubCommand($owningPlugin, $internalAPI, "biome")); + $this->loadSubCommand(new HomeSubCommand($owningPlugin, $internalAPI, "home")); + $this->loadSubCommand(new HomesSubCommand($owningPlugin, $internalAPI, "homes")); + $this->loadSubCommand(new NameSubCommand($owningPlugin, $internalAPI, "name")); + $this->loadSubCommand(new GiveSubCommand($owningPlugin, $internalAPI, "give")); + $this->loadSubCommand(new WarpSubCommand($owningPlugin, $internalAPI, "warp")); + $this->loadSubCommand(new MiddleSubCommand($owningPlugin, $internalAPI, "middle")); + $this->loadSubCommand(new DenyPlayerSubCommand($owningPlugin, $internalAPI, "denyplayer")); + $this->loadSubCommand(new UnDenySubCommand($owningPlugin, $internalAPI, "undenyplayer")); + $this->loadSubCommand(new SetOwnerSubCommand($owningPlugin, $internalAPI, "setowner")); + $this->loadSubCommand(new ListSubCommand($owningPlugin, $internalAPI, "list")); + $this->loadSubCommand(new PvpSubCommand($owningPlugin, $internalAPI, "pvp")); + $this->loadSubCommand(new KickSubCommand($owningPlugin, $internalAPI, "kick")); + $this->loadSubCommand(new MergeSubCommand($owningPlugin, $internalAPI, "merge")); + if($internalAPI->getEconomyProvider() !== null){ + $this->loadSubCommand(new SellSubCommand($owningPlugin, $internalAPI, "sell")); + $this->loadSubCommand(new BuySubCommand($owningPlugin, $internalAPI, "buy")); } - $styler = $plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if($styler !== null) { - $this->loadSubCommand(new CloneSubCommand($plugin, "clone")); + $styler = $owningPlugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if($styler !== null){ + $this->loadSubCommand(new CloneSubCommand($owningPlugin, $internalAPI, "clone")); } - $plugin->getLogger()->debug("Commands Registered to MyPlot"); + $owningPlugin->getLogger()->debug("Commands Registered to MyPlot"); - $autofill = $plugin->getServer()->getPluginManager()->getPlugin("EasyCommandAutofill"); - if($autofill instanceof Main) { + $autofill = $owningPlugin->getServer()->getPluginManager()->getPlugin("EasyCommandAutofill"); + if($autofill instanceof Main and $autofill->getDescription()->getVersion() === '3.0.2'){ $overloads = []; $enumCount = 0; $tree = 0; ksort($this->subCommands, SORT_NATURAL | SORT_FLAG_CASE); - foreach($this->subCommands as $subCommandName => $subCommand) { + foreach($this->subCommands as $subCommandName => $subCommand){ $overloads[$tree][0] = CommandParameter::enum("MyPlotSubCommand", new CommandEnum($subCommandName, [$subCommandName]), CommandParameter::FLAG_FORCE_COLLAPSE_ENUM, false); $usage = $subCommand->getUsage(); @@ -141,65 +133,54 @@ public function __construct(MyPlot $plugin) { } /** - * @return SubCommand[] + * @return MyPlotSubCommand[] */ public function getCommands() : array { return $this->subCommands; } - public function loadSubCommand(SubCommand $command) : void { + public function loadSubCommand(MyPlotSubCommand $command) : void{ $this->subCommands[$command->getName()] = $command; - if($command->getAlias() != "") { + if($command->getAlias() != ""){ $this->aliasSubCommands[$command->getAlias()] = $command; } } - public function unloadSubCommand(string $name) : void { + public function unloadSubCommand(string $name) : void{ $subcommand = $this->subCommands[$name] ?? $this->aliasSubCommands[$name] ?? null; - if($subcommand !== null) { + if($subcommand !== null){ unset($this->subCommands[$subcommand->getName()]); unset($this->aliasSubCommands[$subcommand->getAlias()]); } } - /** - * @param CommandSender $sender - * @param string $alias - * @param string[] $args - * - * @return bool - * @throws \ReflectionException - */ - public function execute(CommandSender $sender, string $alias, array $args) : bool { - /** @var MyPlot $plugin */ - $plugin = $this->getOwningPlugin(); - if($plugin->isDisabled()) { - $sender->sendMessage($plugin->getLanguage()->get("plugin.disabled")); + public function execute(CommandSender $sender, string $commandLabel, array $args) : bool{ + if($this->owningPlugin->isDisabled()){ + $sender->sendMessage($this->owningPlugin->getLanguage()->get("plugin.disabled")); return true; } - if(!isset($args[0])) { + if(!isset($args[0])){ $args[0] = "help"; - if($sender instanceof Player and $plugin->getConfig()->get("UI Forms", true) === true and class_exists('dktapps\\pmforms\\MenuForm')) { - $sender->sendForm(new MainForm($sender, $this->subCommands)); + if($sender instanceof Player and $this->owningPlugin->getConfig()->get("UI Forms", true) === true and class_exists('cosmicpe\\form\\PaginatedForm')){ + $sender->sendForm(new MainForm(1, $sender, $this->internalAPI)); return true; } } - $subCommand = strtolower((string)array_shift($args)); + $subCommand = strtolower((string) array_shift($args)); if(isset($this->subCommands[$subCommand])) { $command = $this->subCommands[$subCommand]; }elseif(isset($this->aliasSubCommands[$subCommand])) { $command = $this->aliasSubCommands[$subCommand]; }else{ - $sender->sendMessage(TextFormat::RED . $plugin->getLanguage()->get("command.unknown")); + $sender->sendMessage(TextFormat::RED . $this->owningPlugin->getLanguage()->get("command.unknown")); return true; } if($command->canUse($sender)) { if(!$command->execute($sender, $args)) { - $usage = $plugin->getLanguage()->translateString("subcommand.usage", [$command->getUsage()]); - $sender->sendMessage($usage); + $sender->sendMessage($this->owningPlugin->getLanguage()->translateString("subcommand.usage", [$command->getUsage()])); } }else{ - $sender->sendMessage(TextFormat::RED . $plugin->getLanguage()->get("command.unknown")); + $sender->sendMessage(TextFormat::RED . $this->owningPlugin->getLanguage()->get("command.unknown")); } return true; } diff --git a/src/MyPlot/subcommand/AddHelperSubCommand.php b/src/MyPlot/subcommand/AddHelperSubCommand.php index 34d08f36..e66b1530 100644 --- a/src/MyPlot/subcommand/AddHelperSubCommand.php +++ b/src/MyPlot/subcommand/AddHelperSubCommand.php @@ -2,12 +2,11 @@ declare(strict_types=1); namespace MyPlot\subcommand; -use MyPlot\forms\MyPlotForm; use MyPlot\forms\subforms\AddHelperForm; -use MyPlot\Plot; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class AddHelperSubCommand extends SubCommand { @@ -21,34 +20,37 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $helperName = $args[0]; - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.addhelper")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - $helper = $this->plugin->getServer()->getPlayerByPrefix($helperName); - if($helper === null) - $helper = $this->plugin->getServer()->getOfflinePlayer($helperName); - if($this->plugin->addPlotHelper($plot, $helper->getName())) { - $sender->sendMessage($this->translateString("addhelper.success", [$helper->getName()])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $helperName = $args[0]; + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.addhelper")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + $helper = $this->plugin->getServer()->getPlayerByPrefix($helperName); + if($helper === null) + $helper = $this->plugin->getServer()->getOfflinePlayer($helperName); + if(yield $this->internalAPI->generateAddPlotHelper($plot, $helper->getName())){ + $sender->sendMessage($this->translateString("addhelper.success", [$helper->getName()])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } + } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) instanceof Plot) - return new AddHelperForm($plot); - return null; + public function getFormClass() : ?string{ + return AddHelperForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/AutoSubCommand.php b/src/MyPlot/subcommand/AutoSubCommand.php index 1819a725..3be53bc9 100644 --- a/src/MyPlot/subcommand/AutoSubCommand.php +++ b/src/MyPlot/subcommand/AutoSubCommand.php @@ -2,10 +2,10 @@ declare(strict_types=1); namespace MyPlot\subcommand; -use MyPlot\forms\MyPlotForm; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class AutoSubCommand extends SubCommand { @@ -19,30 +19,29 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $levelName = $sender->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("auto.notplotworld")); - return true; - } - if(($plot = $this->plugin->getNextFreePlot($levelName)) !== null) { - if($this->plugin->teleportPlayerToPlot($sender, $plot, true)) { - $sender->sendMessage($this->translateString("auto.success", [$plot->X, $plot->Z])); - /** @noinspection PhpParamsInspection */ - $cmd = new ClaimSubCommand($this->plugin, "claim"); - if(isset($args[0]) and strtolower($args[0]) == "true" and $cmd->canUse($sender)) { - $cmd->execute($sender, isset($args[1]) ? [$args[1]] : []); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + $levelName = $sender->getWorld()->getFolderName(); + if($this->internalAPI->getLevelSettings($levelName) === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("auto.notplotworld")); + return; + } + $plot = yield $this->internalAPI->generateNextFreePlot($levelName, 0); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("auto.noplots")); + return; + } + if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, true)){ + $sender->sendMessage($this->translateString("auto.success", [$plot->X, $plot->Z])); + $cmd = new ClaimSubCommand($this->plugin, $this->internalAPI, "claim"); + if(isset($args[0]) and strtolower($args[0]) === "true" and $cmd->canUse($sender)) + $cmd->execute($sender, isset($args[1]) ? [$args[1]] : []); + return; } - }else { $sender->sendMessage(TextFormat::RED . $this->translateString("error")); } - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("auto.noplots")); - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/BiomeSubCommand.php b/src/MyPlot/subcommand/BiomeSubCommand.php index 847386d9..40a99659 100644 --- a/src/MyPlot/subcommand/BiomeSubCommand.php +++ b/src/MyPlot/subcommand/BiomeSubCommand.php @@ -2,14 +2,13 @@ declare(strict_types=1); namespace MyPlot\subcommand; -use MyPlot\forms\MyPlotForm; use MyPlot\forms\subforms\BiomeForm; -use MyPlot\Plot; use pocketmine\command\CommandSender; use pocketmine\data\bedrock\BiomeIds; use pocketmine\player\Player; use pocketmine\utils\TextFormat; use pocketmine\world\biome\BiomeRegistry; +use SOFe\AwaitGenerator\Await; class BiomeSubCommand extends SubCommand { @@ -25,56 +24,58 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - $biomes = TextFormat::WHITE . implode(", ", array_keys(self::BIOMES)); - $sender->sendMessage($this->translateString("biome.possible", [$biomes])); - return true; - } - $player = $sender->getServer()->getPlayerExact($sender->getName()); - if($player === null) - return true; - $biome = strtoupper($args[0]); - $plot = $this->plugin->getPlotByPosition($player->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.biome")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if(is_numeric($biome)) { - $biome = (int) $biome; - if($biome > 27 or $biome < 0) { - $sender->sendMessage(TextFormat::RED . $this->translateString("biome.invalid")); - $biomes = implode(", ", array_keys(self::BIOMES)); - $sender->sendMessage(TextFormat::RED . $this->translateString("biome.possible", [$biomes])); - return true; + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $biomes = TextFormat::WHITE . implode(", ", array_keys(self::BIOMES)); + $sender->sendMessage($this->translateString("biome.possible", [$biomes])); + return; + } + $player = $sender->getServer()->getPlayerExact($sender->getName()); + if($player === null) + return; + $biome = strtoupper($args[0]); + $plot = yield $this->internalAPI->generatePlotByPosition($player->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.biome")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(is_numeric($biome)){ + $biome = (int) $biome; + if($biome > 27 or $biome < 0){ + $sender->sendMessage(TextFormat::RED . $this->translateString("biome.invalid")); + $biomes = implode(", ", array_keys(self::BIOMES)); + $sender->sendMessage(TextFormat::RED . $this->translateString("biome.possible", [$biomes])); + return; + } + $biome = BiomeRegistry::getInstance()->getBiome($biome); + }else{ + $biome = ($biome === "NETHER" ? "HELL" : $biome); + $biome = ($biome === "ICE PLAINS" ? "ICE_PLAINS" : $biome); + if(!defined(BiomeIds::class . "::" . $biome) or !is_int(constant(BiomeIds::class . "::" . $biome))){ + $sender->sendMessage(TextFormat::RED . $this->translateString("biome.invalid")); + $biomes = implode(", ", array_keys(self::BIOMES)); + $sender->sendMessage(TextFormat::RED . $this->translateString("biome.possible", [$biomes])); + return; + } + $biome = BiomeRegistry::getInstance()->getBiome(constant(BiomeIds::class . "::" . $biome)); + } + if(yield $this->internalAPI->generatePlotBiome($plot, $biome)){ + $sender->sendMessage($this->translateString("biome.success", [$biome->getName()])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - $biome = BiomeRegistry::getInstance()->getBiome($biome); - }else{ - $biome = ($biome === "NETHER" ? "HELL" : $biome); - $biome = ($biome === "ICE PLAINS" ? "ICE_PLAINS" : $biome); - if(!defined(BiomeIds::class."::".$biome) or !is_int(constant(BiomeIds::class."::".$biome))) { - $sender->sendMessage(TextFormat::RED . $this->translateString("biome.invalid")); - $biomes = implode(", ", array_keys(self::BIOMES)); - $sender->sendMessage(TextFormat::RED . $this->translateString("biome.possible", [$biomes])); - return true; - } - $biome = BiomeRegistry::getInstance()->getBiome(constant(BiomeIds::class."::".$biome)); - } - if($this->plugin->setPlotBiome($plot, $biome)) { - $sender->sendMessage($this->translateString("biome.success", [$biome->getName()])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and $this->plugin->getPlotByPosition($player->getPosition()) instanceof Plot) - return new BiomeForm(array_keys(self::BIOMES)); - return null; + public function getFormClass() : ?string{ + return BiomeForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/BuySubCommand.php b/src/MyPlot/subcommand/BuySubCommand.php index 84de1816..36f49cbd 100644 --- a/src/MyPlot/subcommand/BuySubCommand.php +++ b/src/MyPlot/subcommand/BuySubCommand.php @@ -2,10 +2,10 @@ declare(strict_types=1); namespace MyPlot\subcommand; -use MyPlot\forms\MyPlotForm; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class BuySubCommand extends SubCommand { @@ -19,54 +19,47 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if($this->plugin->getEconomyProvider() === null){ - /** @noinspection PhpParamsInspection */ - $command = new ClaimSubCommand($this->plugin, "claim"); - return $command->execute($sender, []); - } - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null){ - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner === $sender->getName() and !$sender->hasPermission("myplot.admin.buy")){ - $sender->sendMessage(TextFormat::RED . $this->translateString("buy.noself")); - return true; - } - if($plot->price <= 0){ - $sender->sendMessage(TextFormat::RED . $this->translateString("buy.notforsale")); - return true; - } - $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); - $plotsOfPlayer = 0; - foreach($this->plugin->getPlotLevels() as $level => $settings) { - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName((string)$level); - if($level !== null and $level->isLoaded()) { - $plotsOfPlayer += count($this->plugin->getPlotsOfPlayer($sender->getName(), $level->getFolderName())); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if($this->internalAPI->getEconomyProvider() === null){ + /** @noinspection PhpParamsInspection */ + $command = new ClaimSubCommand($this->plugin, "claim"); + $command->execute($sender, []); + return; + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner === $sender->getName() and !$sender->hasPermission("myplot.admin.buy")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("buy.noself")); + return; + } + if($plot->price <= 0){ + $sender->sendMessage(TextFormat::RED . $this->translateString("buy.notforsale")); + return; + } + $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); + if(count(yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), null)) >= $maxPlots){ + $sender->sendMessage(TextFormat::RED . $this->translateString("claim.maxplots", [$maxPlots])); + return; + } + $price = $plot->price; + if(strtolower($args[0] ?? "") !== $this->translateString("confirm")){ + $sender->sendMessage($this->translateString("buy.confirm", ["$plot->X;$plot->Z", $price])); + return; + } + $oldOwner = $this->plugin->getServer()->getPlayerExact($plot->owner); + if(yield $this->internalAPI->generateBuyPlot($plot, $sender)){ + $sender->sendMessage($this->translateString("buy.success", ["$plot->X;$plot->Z", $price])); + $oldOwner?->sendMessage($this->translateString("buy.sold", [$sender->getName(), "$plot->X;$plot->Z", $price])); // TODO: queue messages for sending when player rejoins + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - } - if($plotsOfPlayer >= $maxPlots) { - $sender->sendMessage(TextFormat::RED . $this->translateString("claim.maxplots", [$maxPlots])); - return true; - } - $price = $plot->price; - if(strtolower($args[0] ?? "") !== $this->translateString("confirm")){ - $sender->sendMessage($this->translateString("buy.confirm", ["$plot->X;$plot->Z", $price])); - return true; - } - $oldOwner = $this->plugin->getServer()->getPlayerExact($plot->owner); - if($this->plugin->buyPlot($plot, $sender)) { - $sender->sendMessage($this->translateString("buy.success", ["$plot->X;$plot->Z", $price])); - $oldOwner?->sendMessage($this->translateString("buy.sold", [$sender->getName(), "$plot->X;$plot->Z", $price])); // TODO: queue messages for sending when player rejoins - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - // TODO: Implement getForm() method. - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/ClaimSubCommand.php b/src/MyPlot/subcommand/ClaimSubCommand.php index b72d64bc..aa3142bc 100644 --- a/src/MyPlot/subcommand/ClaimSubCommand.php +++ b/src/MyPlot/subcommand/ClaimSubCommand.php @@ -2,12 +2,11 @@ declare(strict_types=1); namespace MyPlot\subcommand; -use MyPlot\forms\MyPlotForm; use MyPlot\forms\subforms\ClaimForm; -use MyPlot\MyPlot; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class ClaimSubCommand extends SubCommand { @@ -21,52 +20,54 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $name = ""; - if(isset($args[0])) { - $name = $args[0]; - } - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner != "") { - if($plot->owner === $sender->getName()) { - $sender->sendMessage(TextFormat::RED . $this->translateString("claim.yourplot")); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("claim.alreadyclaimed", [$plot->owner])); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + $name = ""; + if(isset($args[0])){ + $name = $args[0]; + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner != ""){ + if($plot->owner === $sender->getName()){ + $sender->sendMessage(TextFormat::RED . $this->translateString("claim.yourplot")); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("claim.alreadyclaimed", [$plot->owner])); + } + return; + } + $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); + $plotsOfPlayer = 0; + foreach($this->internalAPI->getAllLevelSettings() as $worldName => $settings){ + $worldName = $this->plugin->getServer()->getWorldManager()->getWorldByName($worldName); + if($worldName !== null and $worldName->isLoaded()){ + $plotsOfPlayer += count(yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $worldName->getFolderName())); + } + } + if($plotsOfPlayer >= $maxPlots){ + $sender->sendMessage(TextFormat::RED . $this->translateString("claim.maxplots", [$maxPlots])); + return; + } + $economy = $this->internalAPI->getEconomyProvider(); + if($economy !== null and !(yield $economy->reduceMoney($sender, $plot->price, 'used plot claim command'))){ + $sender->sendMessage(TextFormat::RED . $this->translateString("claim.nomoney")); + return; + } + if(yield $this->internalAPI->generateClaimPlot($plot, $sender->getName(), $name)){ + $sender->sendMessage($this->translateString("claim.success")); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - return true; - } - $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); - $plotsOfPlayer = 0; - foreach($this->plugin->getPlotLevels() as $level => $settings) { - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName((string)$level); - if($level !== null and $level->isLoaded()) { - $plotsOfPlayer += count($this->plugin->getPlotsOfPlayer($sender->getName(), $level->getFolderName())); - } - } - if($plotsOfPlayer >= $maxPlots) { - $sender->sendMessage(TextFormat::RED . $this->translateString("claim.maxplots", [$maxPlots])); - return true; - } - $economy = $this->plugin->getEconomyProvider(); - if($economy !== null and !$economy->reduceMoney($sender, $plot->price)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("claim.nomoney")); - return true; - } - if($this->plugin->claimPlot($plot, $sender->getName(), $name)) { - $sender->sendMessage($this->translateString("claim.success")); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) !== null) - return new ClaimForm($player, $plot); - return null; + public function getFormClass() : ?string{ + return ClaimForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/ClearSubCommand.php b/src/MyPlot/subcommand/ClearSubCommand.php index d59ed16a..a488e5ea 100644 --- a/src/MyPlot/subcommand/ClearSubCommand.php +++ b/src/MyPlot/subcommand/ClearSubCommand.php @@ -2,10 +2,10 @@ declare(strict_types=1); namespace MyPlot\subcommand; -use MyPlot\forms\MyPlotForm; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class ClearSubCommand extends SubCommand { @@ -19,39 +19,39 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.clear")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if(isset($args[0]) and $args[0] == $this->translateString("confirm")) { - $economy = $this->plugin->getEconomyProvider(); - $price = $this->plugin->getLevelSettings($plot->levelName)->clearPrice; - if($economy !== null and !$economy->reduceMoney($sender, $price)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("clear.nomoney")); - return true; + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.clear")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(!isset($args[0]) or $args[0] !== $this->translateString("confirm")){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("clear.confirm", [$plotId])); + return; + } + $economy = $this->internalAPI->getEconomyProvider(); + $price = $this->internalAPI->getLevelSettings($plot->levelName)->clearPrice; + if($economy !== null and !(yield $economy->reduceMoney($sender, $price, 'used plot clear command'))){ + $sender->sendMessage(TextFormat::RED . $this->translateString("clear.nomoney")); + return; + } + $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); + if(!is_int($maxBlocksPerTick)) + $maxBlocksPerTick = 256; + if(yield $this->internalAPI->generateClearPlot($plot, $maxBlocksPerTick)){ + $sender->sendMessage($this->translateString("clear.success")); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); - if(!is_int($maxBlocksPerTick)) - $maxBlocksPerTick = 256; - if($this->plugin->clearPlot($plot, $maxBlocksPerTick)) { - $sender->sendMessage($this->translateString("clear.success")); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } - }else{ - $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; - $sender->sendMessage($this->translateString("clear.confirm", [$plotId])); - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/CloneSubCommand.php b/src/MyPlot/subcommand/CloneSubCommand.php index db0e3747..690bded3 100644 --- a/src/MyPlot/subcommand/CloneSubCommand.php +++ b/src/MyPlot/subcommand/CloneSubCommand.php @@ -7,6 +7,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class CloneSubCommand extends SubCommand { @@ -20,46 +21,50 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - /** @var string[] $plotIdArray */ - $plotIdArray = explode(";", $args[0]); - if(count($plotIdArray) != 2 or !is_numeric($plotIdArray[0]) or !is_numeric($plotIdArray[1])) { - $sender->sendMessage(TextFormat::RED . $this->translateString("clone.wrongid")); - return true; - } - $levelName = $args[1] ?? $sender->getWorld()->getFolderName(); - $selectedPlot = $this->plugin->getProvider()->getPlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1]); - $standingPlot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($standingPlot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($standingPlot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.clone")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if($selectedPlot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.clone")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - $plotLevel = $this->plugin->getLevelSettings($standingPlot->levelName); - $economy = $this->plugin->getEconomyProvider(); - if($economy !== null and !$economy->reduceMoney($sender, $plotLevel->clonePrice)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("clone.nomoney")); - return true; - } - if($this->plugin->clonePlot($selectedPlot, $standingPlot)) { - $sender->sendMessage($this->translateString("clone.success", [$selectedPlot->__toString(), $standingPlot->__toString()])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $plotIdArray = explode(";", $args[0]); + if(count($plotIdArray) < 2 or !is_numeric($plotIdArray[0]) or !is_numeric($plotIdArray[1])){ + $sender->sendMessage(TextFormat::RED . $this->translateString("clone.wrongid")); + return; + } + $levelName = $args[1] ?? $sender->getWorld()->getFolderName(); + $selectedPlot = yield $this->internalAPI->generatePlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1]); + $standingPlot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($standingPlot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($standingPlot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.clone")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if($selectedPlot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.clone")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + $plotLevel = $this->plugin->getLevelSettings($standingPlot->levelName); + $economy = $this->internalAPI->getEconomyProvider(); + if($economy !== null and !(yield $economy->reduceMoney($sender, $plotLevel->clonePrice))){ + $sender->sendMessage(TextFormat::RED . $this->translateString("clone.nomoney")); + return; + } + if(yield $this->internalAPI->generateClonePlot($selectedPlot, $standingPlot)){ + $sender->sendMessage($this->translateString("clone.success", [$selectedPlot->__toString(), $standingPlot->__toString()])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } + } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - return $player !== null ? new CloneForm($player) : null; + public function getFormClass() : ?string{ + return CloneForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/DenyPlayerSubCommand.php b/src/MyPlot/subcommand/DenyPlayerSubCommand.php index 9554edd5..76b2c344 100644 --- a/src/MyPlot/subcommand/DenyPlayerSubCommand.php +++ b/src/MyPlot/subcommand/DenyPlayerSubCommand.php @@ -4,10 +4,10 @@ use MyPlot\forms\MyPlotForm; use MyPlot\forms\subforms\DenyPlayerForm; -use MyPlot\Plot; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class DenyPlayerSubCommand extends SubCommand { @@ -21,60 +21,64 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $dplayer = $args[0]; - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.denyplayer")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if($dplayer === "*") { - if($this->plugin->addPlotDenied($plot, $dplayer)) { - $sender->sendMessage($this->translateString("denyplayer.success1", [$dplayer])); - foreach($this->plugin->getServer()->getOnlinePlayers() as $player) { - if($this->plugin->getPlotBB($plot)->isVectorInside($player) and !($player->getName() === $plot->owner) and !$player->hasPermission("myplot.admin.denyplayer.bypass") and !$plot->isHelper($player->getName())) - $this->plugin->teleportPlayerToPlot($player, $plot); - else { - $sender->sendMessage($this->translateString("denyplayer.cannotdeny", [$player->getName()])); - $player->sendMessage($this->translateString("denyplayer.attempteddeny", [$sender->getName()])); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $dplayer = $args[0]; + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.denyplayer")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if($dplayer === "*"){ + if(yield $this->internalAPI->generateAddPlotDenied($plot, $dplayer)){ + $sender->sendMessage($this->translateString("denyplayer.success1", [$dplayer])); + foreach($this->plugin->getServer()->getOnlinePlayers() as $player){ + if((yield $this->internalAPI->generatePlotBB($plot))->isVectorInside($player) and !($player->getName() === $plot->owner) and !$player->hasPermission("myplot.admin.denyplayer.bypass") and !$plot->isHelper($player->getName())) + $this->internalAPI->generatePlayerTeleport($player, $plot, false); + else{ + $sender->sendMessage($this->translateString("denyplayer.cannotdeny", [$player->getName()])); + $player->sendMessage($this->translateString("denyplayer.attempteddeny", [$sender->getName()])); + } + } + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); } + return; + } + + $dplayer = $this->plugin->getServer()->getPlayerByPrefix($dplayer); + if(!$dplayer instanceof Player){ + $sender->sendMessage($this->translateString("denyplayer.notaplayer")); + return; + } + if($dplayer->hasPermission("myplot.admin.denyplayer.bypass") or $dplayer->getName() === $plot->owner){ + $sender->sendMessage($this->translateString("denyplayer.cannotdeny", [$dplayer->getName()])); + $dplayer->sendMessage($this->translateString("denyplayer.attempteddeny", [$sender->getName()])); + return; + } + if(yield $this->plugin->addPlotDenied($plot, $dplayer->getName())){ + $sender->sendMessage($this->translateString("denyplayer.success1", [$dplayer->getName()])); + $dplayer->sendMessage($this->translateString("denyplayer.success2", [$plot->X, $plot->Z, $sender->getName()])); + if((yield $this->internalAPI->generatePlotBB($plot))->isVectorInside($dplayer)) + $this->internalAPI->generatePlayerTeleport($dplayer, $plot, false); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); } - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); } - return true; - } - $dplayer = $this->plugin->getServer()->getPlayerByPrefix($dplayer); - if(!$dplayer instanceof Player) { - $sender->sendMessage($this->translateString("denyplayer.notaplayer")); - return true; - } - if($dplayer->hasPermission("myplot.admin.denyplayer.bypass") or $dplayer->getName() === $plot->owner) { - $sender->sendMessage($this->translateString("denyplayer.cannotdeny", [$dplayer->getName()])); - $dplayer->sendMessage($this->translateString("denyplayer.attempteddeny", [$sender->getName()])); - return true; - } - if($this->plugin->addPlotDenied($plot, $dplayer->getName())) { - $sender->sendMessage($this->translateString("denyplayer.success1", [$dplayer->getName()])); - $dplayer->sendMessage($this->translateString("denyplayer.success2", [$plot->X, $plot->Z, $sender->getName()])); - if($this->plugin->getPlotBB($plot)->isVectorInside($dplayer)) - $this->plugin->teleportPlayerToPlot($dplayer, $plot); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) instanceof Plot) - return new DenyPlayerForm($plot); - return null; + public function getFormClass() : ?string{ + return DenyPlayerForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/DisposeSubCommand.php b/src/MyPlot/subcommand/DisposeSubCommand.php index 737cc494..6d1d7fc1 100644 --- a/src/MyPlot/subcommand/DisposeSubCommand.php +++ b/src/MyPlot/subcommand/DisposeSubCommand.php @@ -6,6 +6,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class DisposeSubCommand extends SubCommand { @@ -19,36 +20,36 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.dispose")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if(isset($args[0]) and $args[0] == $this->translateString("confirm")) { - $economy = $this->plugin->getEconomyProvider(); - $price = $this->plugin->getLevelSettings($plot->levelName)->disposePrice; - if($economy !== null and !$economy->reduceMoney($sender, $price)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("dispose.nomoney")); - return true; + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.dispose")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(!isset($args[0]) or $args[0] !== $this->translateString("confirm")){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("dispose.confirm", [$plotId])); + return; + } + $economy = $this->internalAPI->getEconomyProvider(); + $price = $this->plugin->getLevelSettings($plot->levelName)->disposePrice; + if($economy !== null and !(yield $economy->reduceMoney($sender, $price))){ + $sender->sendMessage(TextFormat::RED . $this->translateString("dispose.nomoney")); + return; + } + if(yield $this->plugin->disposePlot($plot)){ + $sender->sendMessage(TextFormat::GREEN . $this->translateString("dispose.success")); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - if($this->plugin->disposePlot($plot)) { - $sender->sendMessage($this->translateString("dispose.success")); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } - }else{ - $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; - $sender->sendMessage($this->translateString("dispose.confirm", [$plotId])); - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/FillSubCommand.php b/src/MyPlot/subcommand/FillSubCommand.php index ecd4251d..f856a37a 100644 --- a/src/MyPlot/subcommand/FillSubCommand.php +++ b/src/MyPlot/subcommand/FillSubCommand.php @@ -11,6 +11,7 @@ use pocketmine\item\StringToItemParser; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class FillSubCommand extends SubCommand { /** @@ -28,37 +29,47 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) < 1) { - return false; - } - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED.$this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.fill")) { - $sender->sendMessage(TextFormat::RED.$this->translateString("notowner")); - return true; - } - - if(($item = StringToItemParser::getInstance()->parse($args[0])) instanceof Item and $item->getBlock() instanceof Air) { - $maxBlocksPerTick = (int)$this->plugin->getConfig()->get("FillBlocksPerTick", 256); - if($this->plugin->fillPlot($plot, $item->getBlock(), $maxBlocksPerTick)) { - $sender->sendMessage($this->translateString("fill.success", [$item->getBlock()->getName()])); - }else { - $sender->sendMessage(TextFormat::RED.$this->translateString("error")); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) < 1 or !($item = StringToItemParser::getInstance()->parse($args[0])) instanceof Item or !$item->getBlock() instanceof Air){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.fill")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(!isset($args[1]) or $args[1] !== $this->translateString("confirm")){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("fill.confirm", [$plotId])); + return; + } + $economy = $this->internalAPI->getEconomyProvider(); + $price = $this->internalAPI->getLevelSettings($plot->levelName)->fillPrice; + if($economy !== null and !(yield $economy->reduceMoney($sender, $price, 'used plot fill command'))){ + $sender->sendMessage(TextFormat::RED . $this->translateString("fill.nomoney")); + return; + } + $maxBlocksPerTick = $this->plugin->getConfig()->get("FillBlocksPerTick", 256); + if(!is_int($maxBlocksPerTick)) + $maxBlocksPerTick = 256; + if(yield $this->plugin->fillPlot($plot, $item->getBlock(), $maxBlocksPerTick)){ + $sender->sendMessage($this->translateString("fill.success", [$item->getBlock()->getName()])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - }else { - return false; - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($this->plugin->getPlotByPosition($player->getPosition()) instanceof Plot) { - return new FillForm(); - } - return null; + public function getFormClass() : ?string{ + return FillForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/GenerateSubCommand.php b/src/MyPlot/subcommand/GenerateSubCommand.php index 0ac34f9a..d1beb301 100644 --- a/src/MyPlot/subcommand/GenerateSubCommand.php +++ b/src/MyPlot/subcommand/GenerateSubCommand.php @@ -5,10 +5,11 @@ use MyPlot\forms\MyPlotForm; use MyPlot\forms\subforms\GenerateForm; use MyPlot\MyPlotGenerator; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class GenerateSubCommand extends SubCommand { @@ -22,27 +23,32 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $levelName = $args[0]; - if($sender->getServer()->getWorldManager()->isWorldGenerated($levelName)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("generate.exists", [$levelName])); - return true; - } - if($this->plugin->generateLevel($levelName, $args[2] ?? MyPlotGenerator::NAME)) { - if(isset($args[1]) and $args[1] == true and $sender instanceof Player) { - $this->plugin->teleportPlayerToPlot($sender, new Plot($levelName, 0, 0)); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $levelName = $args[0]; + if($sender->getServer()->getWorldManager()->isWorldGenerated($levelName)){ + $sender->sendMessage(TextFormat::RED . $this->translateString("generate.exists", [$levelName])); + return; + } + if($this->plugin->generateLevel($levelName, $args[2] ?? MyPlotGenerator::NAME)){ + if(isset($args[1]) and $args[1] == true and $sender instanceof Player){ + yield $this->internalAPI->generatePlayerTeleport($sender, new BasePlot($levelName, 0, 0), false); + } + $sender->sendMessage($this->translateString("generate.success", [$levelName])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("generate.error")); + } } - $sender->sendMessage($this->translateString("generate.success", [$levelName])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("generate.error")); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - return new GenerateForm(); + public function getFormClass() : ?string{ + return GenerateForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/GiveSubCommand.php b/src/MyPlot/subcommand/GiveSubCommand.php index c4e03e30..bb89dadd 100644 --- a/src/MyPlot/subcommand/GiveSubCommand.php +++ b/src/MyPlot/subcommand/GiveSubCommand.php @@ -8,6 +8,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class GiveSubCommand extends SubCommand { @@ -21,61 +22,57 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $newOwner = $args[0]; - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName()) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - $newOwner = $this->plugin->getServer()->getPlayerByPrefix($newOwner); - if(!$newOwner instanceof Player) { - $sender->sendMessage(TextFormat::RED . $this->translateString("give.notonline")); - return true; - }elseif($newOwner->getName() === $sender->getName()) { - $sender->sendMessage(TextFormat::RED . $this->translateString("give.toself")); - return true; - } - $maxPlots = $this->plugin->getMaxPlotsOfPlayer($newOwner); - $plotsOfPlayer = 0; - foreach($this->plugin->getPlotLevels() as $level => $settings) { - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName((string)$level); - if($level !== null and $level->isLoaded()) { - $plotsOfPlayer += count($this->plugin->getPlotsOfPlayer($newOwner->getName(), $level->getFolderName())); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) < 1){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $newOwner = $args[0]; + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName()){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + $newOwner = $this->plugin->getServer()->getPlayerByPrefix($newOwner); + if(!$newOwner instanceof Player){ + $sender->sendMessage(TextFormat::RED . $this->translateString("give.notonline")); + return; + }elseif($newOwner->getName() === $sender->getName()){ + $sender->sendMessage(TextFormat::RED . $this->translateString("give.toself")); + return; + } + $maxPlots = $this->plugin->getMaxPlotsOfPlayer($newOwner); + if(count(yield $this->internalAPI->generatePlotsOfPlayer($newOwner->getName(), null)) >= $maxPlots){ + $sender->sendMessage(TextFormat::RED . $this->translateString("give.maxedout", [$maxPlots])); + return; + } + if(count($args) < 2 or $args[1] !== $this->translateString("confirm")){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $newOwnerName = TextFormat::GREEN . $newOwner->getName() . TextFormat::WHITE; + $sender->sendMessage($this->translateString("give.confirm", [$plotId, $newOwnerName])); + return; + } + if(yield $this->internalAPI->generateClaimPlot($plot, $newOwner->getName(), '')){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $oldOwnerName = TextFormat::GREEN . $sender->getName() . TextFormat::WHITE; + $newOwnerName = TextFormat::GREEN . $newOwner->getName() . TextFormat::WHITE; + $sender->sendMessage($this->translateString("give.success", [$newOwnerName])); + $newOwner->sendMessage($this->translateString("give.received", [$oldOwnerName, $plotId])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - } - if($plotsOfPlayer >= $maxPlots) { - $sender->sendMessage(TextFormat::RED . $this->translateString("give.maxedout", [$maxPlots])); - return true; - } - if(count($args) == 2 and $args[1] == $this->translateString("confirm")) { - if($this->plugin->claimPlot($plot, $newOwner->getName())) { - $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; - $oldOwnerName = TextFormat::GREEN . $sender->getName() . TextFormat::WHITE; - $newOwnerName = TextFormat::GREEN . $newOwner->getName() . TextFormat::WHITE; - $sender->sendMessage($this->translateString("give.success", [$newOwnerName])); - $newOwner->sendMessage($this->translateString("give.received", [$oldOwnerName, $plotId])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } - }else{ - $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; - $newOwnerName = TextFormat::GREEN . $newOwner->getName() . TextFormat::WHITE; - $sender->sendMessage($this->translateString("give.confirm", [$plotId, $newOwnerName])); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and $this->plugin->getPlotByPosition($player->getPosition()) instanceof Plot) - return new GiveForm(); - return null; + public function getFormClass() : ?string{ + return GiveForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/HelpSubCommand.php b/src/MyPlot/subcommand/HelpSubCommand.php index 5109aeda..0a7ce6ae 100644 --- a/src/MyPlot/subcommand/HelpSubCommand.php +++ b/src/MyPlot/subcommand/HelpSubCommand.php @@ -4,34 +4,24 @@ use MyPlot\Commands; use MyPlot\forms\MyPlotForm; +use MyPlot\InternalAPI; use MyPlot\MyPlot; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; -class HelpSubCommand extends SubCommand -{ - private Commands $cmds; - - /** - * HelpSubCommand constructor. - * - * @param MyPlot $plugin - * @param string $name - * @param Commands $cmds - */ - public function __construct(MyPlot $plugin, string $name, Commands $cmds) { - parent::__construct($plugin, $name); - $this->cmds = $cmds; +class HelpSubCommand extends SubCommand{ + public function __construct(MyPlot $plugin, InternalAPI $api, string $name, private Commands $cmds){ + parent::__construct($plugin, $api, $name); } - public function canUse(CommandSender $sender) : bool { + public function canUse(CommandSender $sender) : bool{ return $sender->hasPermission("myplot.command.help"); } /** * @param CommandSender $sender - * @param string[] $args + * @param string[] $args * @return bool */ public function execute(CommandSender $sender, array $args) : bool { @@ -64,8 +54,4 @@ public function execute(CommandSender $sender, array $args) : bool { } return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/HomeSubCommand.php b/src/MyPlot/subcommand/HomeSubCommand.php index a1df8e07..6edf1cef 100644 --- a/src/MyPlot/subcommand/HomeSubCommand.php +++ b/src/MyPlot/subcommand/HomeSubCommand.php @@ -5,9 +5,11 @@ use MyPlot\forms\MyPlotForm; use MyPlot\forms\subforms\HomeForm; use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class HomeSubCommand extends SubCommand { @@ -21,46 +23,49 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - $plotNumber = 1; - }elseif(is_numeric($args[0])) { - $plotNumber = (int) $args[0]; - }else{ - return false; - } - $levelName = $args[1] ?? $sender->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("error", [$levelName])); - return true; - } - $plots = $this->plugin->getPlotsOfPlayer($sender->getName(), $levelName); - if(count($plots) === 0) { - $sender->sendMessage(TextFormat::RED . $this->translateString("home.noplots")); - return true; - } - if(!isset($plots[$plotNumber - 1])) { - $sender->sendMessage(TextFormat::RED . $this->translateString("home.notexist", [$plotNumber])); - return true; - } - usort($plots, function(Plot $plot1, Plot $plot2) { - if($plot1->levelName == $plot2->levelName) { - return 0; + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $plotNumber = 1; + }elseif(is_numeric($args[0])){ + $plotNumber = (int) $args[0]; + }else{ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $levelName = $args[1] ?? $sender->getWorld()->getFolderName(); + if($this->internalAPI->getLevelSettings($levelName) === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("error", [$levelName])); + return; + } + $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); + if(count($plots) === 0){ + $sender->sendMessage(TextFormat::RED . $this->translateString("home.noplots")); + return; + } + if(!isset($plots[$plotNumber - 1])){ + $sender->sendMessage(TextFormat::RED . $this->translateString("home.notexist", [$plotNumber])); + return; + } + usort($plots, function(BasePlot $plot1, BasePlot $plot2){ + if($plot1->levelName == $plot2->levelName){ + return 0; + } + return ($plot1->levelName < $plot2->levelName) ? -1 : 1; + }); + $plot = $plots[$plotNumber - 1]; + if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, false)){ + $sender->sendMessage($this->translateString("home.success", [$plot->__toString(), $plot->levelName])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("home.error")); + } } - return ($plot1->levelName < $plot2->levelName) ? -1 : 1; - }); - $plot = $plots[$plotNumber - 1]; - if($this->plugin->teleportPlayerToPlot($sender, $plot)) { - $sender->sendMessage($this->translateString("home.success", [$plot->__toString(), $plot->levelName])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("home.error")); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and count($this->plugin->getPlotsOfPlayer($player->getName(), $player->getWorld()->getFolderName())) > 0) - return new HomeForm($player); - return null; + public function getFormClass() : ?string{ + return HomeForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/HomesSubCommand.php b/src/MyPlot/subcommand/HomesSubCommand.php index e8102c5e..690766cb 100644 --- a/src/MyPlot/subcommand/HomesSubCommand.php +++ b/src/MyPlot/subcommand/HomesSubCommand.php @@ -6,6 +6,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class HomesSubCommand extends SubCommand { @@ -19,31 +20,31 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $levelName = $args[0] ?? $sender->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("error", [$levelName])); - return true; - } - $plots = $this->plugin->getPlotsOfPlayer($sender->getName(), $levelName); - if(count($plots) === 0) { - $sender->sendMessage(TextFormat::RED . $this->translateString("homes.noplots")); - return true; - } - $sender->sendMessage(TextFormat::DARK_GREEN . $this->translateString("homes.header")); - for($i = 0; $i < count($plots); $i++) { - $plot = $plots[$i]; - $message = TextFormat::DARK_GREEN . ($i + 1) . ") "; - $message .= TextFormat::WHITE . $plot->levelName . " " . $plot; - if($plot->name !== "") { - $message .= " = " . $plot->name; + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + $levelName = $args[0] ?? $sender->getWorld()->getFolderName(); + if($this->internalAPI->getLevelSettings($levelName) === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("error", [$levelName])); + return; + } + $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); + if(count($plots) === 0){ + $sender->sendMessage(TextFormat::RED . $this->translateString("homes.noplots")); + return; + } + $sender->sendMessage(TextFormat::DARK_GREEN . $this->translateString("homes.header")); + for($i = 0; $i < count($plots); $i++){ + $plot = $plots[$i]; + $message = TextFormat::DARK_GREEN . ($i + 1) . ") "; + $message .= TextFormat::WHITE . $plot->levelName . " " . $plot; + if($plot->name !== ""){ + $message .= " = " . $plot->name; + } + $sender->sendMessage($message); + } } - $sender->sendMessage($message); - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; // we can just list homes in the home form - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/InfoSubCommand.php b/src/MyPlot/subcommand/InfoSubCommand.php index c101eb9b..8dc5144d 100644 --- a/src/MyPlot/subcommand/InfoSubCommand.php +++ b/src/MyPlot/subcommand/InfoSubCommand.php @@ -4,10 +4,10 @@ use MyPlot\forms\MyPlotForm; use MyPlot\forms\subforms\InfoForm; -use MyPlot\Plot; use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class InfoSubCommand extends SubCommand { @@ -21,52 +21,50 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(isset($args[0])) { - if(isset($args[1]) and is_numeric($args[1])) { - $key = max(((int) $args[1] - 1), 1); - /** @var Plot[] $plots */ - $plots = []; - foreach($this->plugin->getPlotLevels() as $levelName => $settings) { - $plots = array_merge($plots, $this->plugin->getPlotsOfPlayer($args[0], $levelName)); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(isset($args[0])){ + if(isset($args[1]) and is_numeric($args[1])){ + $key = max(((int) $args[1] - 1), 1); + $plots = yield $this->internalAPI->generatePlotsOfPlayer($args[0], null); + if(isset($plots[$key])){ + $plot = $plots[$key]; + $sender->sendMessage($this->translateString("info.about", [TextFormat::GREEN . $plot])); + $sender->sendMessage($this->translateString("info.owner", [TextFormat::GREEN . $plot->owner])); + $sender->sendMessage($this->translateString("info.plotname", [TextFormat::GREEN . $plot->name])); + $helpers = implode(", ", $plot->helpers); + $sender->sendMessage($this->translateString("info.helpers", [TextFormat::GREEN . $helpers])); + $denied = implode(", ", $plot->denied); + $sender->sendMessage($this->translateString("info.denied", [TextFormat::GREEN . $denied])); + $sender->sendMessage($this->translateString("info.biome", [TextFormat::GREEN . $plot->biome])); + return; + } + $sender->sendMessage(TextFormat::RED . $this->translateString("info.notfound")); + return; + } + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; } - if(isset($plots[$key])) { - $plot = $plots[$key]; - $sender->sendMessage($this->translateString("info.about", [TextFormat::GREEN . $plot])); - $sender->sendMessage($this->translateString("info.owner", [TextFormat::GREEN . $plot->owner])); - $sender->sendMessage($this->translateString("info.plotname", [TextFormat::GREEN . $plot->name])); - $helpers = implode(", ", $plot->helpers); - $sender->sendMessage($this->translateString("info.helpers", [TextFormat::GREEN . $helpers])); - $denied = implode(", ", $plot->denied); - $sender->sendMessage($this->translateString("info.denied", [TextFormat::GREEN . $denied])); - $sender->sendMessage($this->translateString("info.biome", [TextFormat::GREEN . $plot->biome])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("info.notfound")); + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; } - }else{ - return false; + $sender->sendMessage($this->translateString("info.about", [TextFormat::GREEN . $plot])); + $sender->sendMessage($this->translateString("info.owner", [TextFormat::GREEN . $plot->owner])); + $sender->sendMessage($this->translateString("info.plotname", [TextFormat::GREEN . $plot->name])); + $helpers = implode(", ", $plot->helpers); + $sender->sendMessage($this->translateString("info.helpers", [TextFormat::GREEN . $helpers])); + $denied = implode(", ", $plot->denied); + $sender->sendMessage($this->translateString("info.denied", [TextFormat::GREEN . $denied])); + $sender->sendMessage($this->translateString("info.biome", [TextFormat::GREEN . $plot->biome])); } - }else{ - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - $sender->sendMessage($this->translateString("info.about", [TextFormat::GREEN . $plot])); - $sender->sendMessage($this->translateString("info.owner", [TextFormat::GREEN . $plot->owner])); - $sender->sendMessage($this->translateString("info.plotname", [TextFormat::GREEN . $plot->name])); - $helpers = implode(", ", $plot->helpers); - $sender->sendMessage($this->translateString("info.helpers", [TextFormat::GREEN . $helpers])); - $denied = implode(", ", $plot->denied); - $sender->sendMessage($this->translateString("info.denied", [TextFormat::GREEN . $denied])); - $sender->sendMessage($this->translateString("info.biome", [TextFormat::GREEN . $plot->biome])); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) instanceof Plot) - return new InfoForm($plot); - return null; + public function getFormClass() : ?string{ + return InfoForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/KickSubCommand.php b/src/MyPlot/subcommand/KickSubCommand.php index d90c5d7c..9197ff48 100644 --- a/src/MyPlot/subcommand/KickSubCommand.php +++ b/src/MyPlot/subcommand/KickSubCommand.php @@ -8,6 +8,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class KickSubCommand extends SubCommand { @@ -21,43 +22,48 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if (!isset($args[0])) return false; - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if ($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.kick")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - $target = $this->plugin->getServer()->getPlayerByPrefix($args[0]); - if ($target === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("kick.noPlayer")); - return true; - } - if (($targetPlot = $this->plugin->getPlotByPosition($target->getPosition())) === null or !$plot->isSame($targetPlot)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("kick.notInPlot")); - return true; - } - if ($target->hasPermission("myplot.admin.kick.bypass")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("kick.cannotkick")); - $target->sendMessage($this->translateString("kick.attemptkick", [$target->getName()])); - return true; - } - if ($this->plugin->teleportPlayerToPlot($target, $plot)) { - $sender->sendMessage($this->translateString("kick.success1", [$target->getName(), $plot->__toString()])); - $target->sendMessage($this->translateString("kick.success2", [$sender->getName(), $plot->__toString()])); - return true; - } - $sender->sendMessage($this->translateString("error")); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(!isset($args[0])){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.kick")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + $target = $this->plugin->getServer()->getPlayerByPrefix($args[0]); + if($target === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("kick.noPlayer")); + return; + } + if(($targetPlot = yield $this->internalAPI->generatePlotByPosition($target->getPosition())) === null or !$plot->isSame($targetPlot)){ + $sender->sendMessage(TextFormat::RED . $this->translateString("kick.notInPlot")); + return; + } + if($target->hasPermission("myplot.admin.kick.bypass")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("kick.cannotkick")); + $target->sendMessage($this->translateString("kick.attemptkick", [$target->getName()])); + return; + } + if(!yield $this->internalAPI->generatePlayerTeleport($target, $plot, false)){ + $sender->sendMessage($this->translateString("kick.success1", [$target->getName(), $plot->__toString()])); + $target->sendMessage($this->translateString("kick.success2", [$sender->getName(), $plot->__toString()])); + }else{ + $sender->sendMessage($this->translateString("error")); + } + } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) instanceof Plot) - return new KickForm($plot); - return null; + public function getFormClass() : ?string{ + return KickForm::class; } } diff --git a/src/MyPlot/subcommand/ListSubCommand.php b/src/MyPlot/subcommand/ListSubCommand.php index 6977cf49..ca6a583c 100644 --- a/src/MyPlot/subcommand/ListSubCommand.php +++ b/src/MyPlot/subcommand/ListSubCommand.php @@ -6,6 +6,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat as TF; +use SOFe\AwaitGenerator\Await; class ListSubCommand extends SubCommand { public function canUse(CommandSender $sender) : bool { @@ -18,44 +19,44 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if($sender->hasPermission("myplot.admin.list")) { - if(count($args) > 0) { - foreach($this->plugin->getPlotLevels() as $levelName => $settings) { - $plots = $this->plugin->getPlotsOfPlayer($args[0], $levelName); - foreach($plots as $plot) { - $name = $plot->name; - $x = $plot->X; - $z = $plot->Z; - $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if($sender->hasPermission("myplot.admin.list")){ + if(count($args) > 0){ + foreach($this->internalAPI->getAllLevelSettings() as $levelName => $settings){ + $plots = yield $this->internalAPI->generatePlotsOfPlayer($args[0], $levelName); + foreach($plots as $plot){ + $name = $plot->name; + $x = $plot->X; + $z = $plot->Z; + $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); + } + } + }else{ + foreach($this->internalAPI->getAllLevelSettings() as $levelName => $settings){ + $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); + foreach($plots as $plot){ + $name = $plot->name; + $x = $plot->X; + $z = $plot->Z; + $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); + } + } } - } - }else{ - foreach($this->plugin->getPlotLevels() as $levelName => $settings) { - $plots = $this->plugin->getPlotsOfPlayer($sender->getName(), $levelName); - foreach($plots as $plot) { - $name = $plot->name; - $x = $plot->X; - $z = $plot->Z; - $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); + }elseif($sender->hasPermission("myplot.command.list")){ + foreach($this->internalAPI->getAllLevelSettings() as $levelName => $settings){ + $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); + foreach($plots as $plot){ + $name = $plot->name; + $x = $plot->X; + $z = $plot->Z; + $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); + } } } } - }elseif($sender->hasPermission("myplot.command.list")) { - foreach($this->plugin->getPlotLevels() as $levelName => $settings) { - $plots = $this->plugin->getPlotsOfPlayer($sender->getName(), $levelName); - foreach($plots as $plot) { - $name = $plot->name; - $x = $plot->X; - $z = $plot->Z; - $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); - } - } - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; // this will probably be merged into the homes command - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/MergeSubCommand.php b/src/MyPlot/subcommand/MergeSubCommand.php index 2c364588..b24db51f 100644 --- a/src/MyPlot/subcommand/MergeSubCommand.php +++ b/src/MyPlot/subcommand/MergeSubCommand.php @@ -7,6 +7,7 @@ use pocketmine\math\Facing; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class MergeSubCommand extends SubCommand { @@ -20,92 +21,94 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.merge")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if(!isset($args[0])) { - $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; - $sender->sendMessage($this->translateString("merge.confirmface", [$plotId])); - return true; - }elseif($args[0] === $this->translateString("confirm")) { - $rotation = ($sender->getLocation()->getYaw() - 180) % 360; - if($rotation < 0) { - $rotation += 360.0; + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender) : \Generator{ + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.merge")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(!isset($args[0])){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("merge.confirmface", [$plotId])); + return; + }elseif($args[0] === $this->translateString("confirm")){ + $rotation = ($sender->getLocation()->getYaw() - 180) % 360; + if($rotation < 0){ + $rotation += 360.0; + } + if((0 <= $rotation and $rotation < 45) or (315 <= $rotation and $rotation < 360)){ + $direction = Facing::NORTH; //North + $args[0] = $this->translateString("merge.north"); + }elseif(45 <= $rotation and $rotation < 135){ + $direction = Facing::EAST; //East + $args[0] = $this->translateString("merge.east"); + }elseif(135 <= $rotation and $rotation < 225){ + $direction = Facing::SOUTH; //South + $args[0] = $this->translateString("merge.south"); + }elseif(225 <= $rotation and $rotation < 315){ + $direction = Facing::WEST; //West + $args[0] = $this->translateString("merge.west"); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + return; + } + }else{ + switch(strtolower($args[0])){ + case "north": + case "-z": + case "z-": + case $this->translateString("merge.north"): + $direction = Facing::NORTH; + $args[0] = $this->translateString("merge.north"); + break; + case "east": + case "+x": + case "x+": + case $this->translateString("merge.east"): + $direction = Facing::EAST; + $args[0] = $this->translateString("merge.east"); + break; + case "south": + case "+z": + case "z+": + case $this->translateString("merge.south"): + $direction = Facing::SOUTH; + $args[0] = $this->translateString("merge.south"); + break; + case "west": + case "-x": + case "x-": + case $this->translateString("merge.west"): + $direction = Facing::WEST; + $args[0] = $this->translateString("merge.west"); + break; + default: + $sender->sendMessage(TextFormat::RED . $this->translateString("merge.direction")); + return; + } + if(!isset($args[1]) or $args[1] !== $this->translateString("confirm")){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("merge.confirmarg", [$plotId, $args[0], implode(' ', $args) . " " . $this->translateString("confirm")])); + return; + } + } + $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); + if(!is_int($maxBlocksPerTick)) + $maxBlocksPerTick = 256; + if(yield $this->internalAPI->generateMergePlots($plot, $direction, $maxBlocksPerTick)){ + $plot = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("merge.success", [$plot, $args[0]])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - if((0 <= $rotation and $rotation < 45) or (315 <= $rotation and $rotation < 360)) { - $direction = Facing::NORTH; //North - $args[0] = $this->translateString("merge.north"); - }elseif(45 <= $rotation and $rotation < 135) { - $direction = Facing::EAST; //East - $args[0] = $this->translateString("merge.east"); - }elseif(135 <= $rotation and $rotation < 225) { - $direction = Facing::SOUTH; //South - $args[0] = $this->translateString("merge.south"); - }elseif(225 <= $rotation and $rotation < 315) { - $direction = Facing::WEST; //West - $args[0] = $this->translateString("merge.west"); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - return true; - } - }else{ - switch(strtolower($args[0])) { - case "north": - case "-z": - case "z-": - case $this->translateString("merge.north"): - $direction = Facing::NORTH; - $args[0] = $this->translateString("merge.north"); - break; - case "east": - case "+x": - case "x+": - case $this->translateString("merge.east"): - $direction = Facing::EAST; - $args[0] = $this->translateString("merge.east"); - break; - case "south": - case "+z": - case "z+": - case $this->translateString("merge.south"): - $direction = Facing::SOUTH; - $args[0] = $this->translateString("merge.south"); - break; - case "west": - case "-x": - case "x-": - case $this->translateString("merge.west"): - $direction = Facing::WEST; - $args[0] = $this->translateString("merge.west"); - break; - default: - $sender->sendMessage(TextFormat::RED . $this->translateString("merge.direction")); - return true; - } - if(!isset($args[1]) or $args[1] !== $this->translateString("confirm")) { - $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; - $sender->sendMessage($this->translateString("merge.confirmarg", [$plotId, $args[0], implode(' ', $args)." ".$this->translateString("confirm")])); - return true; - } - } - $maxBlocksPerTick = (int) $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); - if($this->plugin->mergePlots($plot, $direction, $maxBlocksPerTick)) { - $plot = TextFormat::GREEN . $plot . TextFormat::WHITE; - $sender->sendMessage($this->translateString("merge.success", [$plot, $args[0]])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/MiddleSubCommand.php b/src/MyPlot/subcommand/MiddleSubCommand.php index cfd9d7a3..61db57bd 100644 --- a/src/MyPlot/subcommand/MiddleSubCommand.php +++ b/src/MyPlot/subcommand/MiddleSubCommand.php @@ -6,6 +6,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class MiddleSubCommand extends SubCommand { @@ -19,26 +20,27 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) != 0) { - return false; - } - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.middle")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if($this->plugin->teleportPlayerToPlot($sender, $plot, true)) { - $sender->sendMessage(TextFormat::GREEN . $this->translateString("middle.success")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) != 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.middle")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, true)){ + $sender->sendMessage(TextFormat::GREEN . $this->translateString("middle.success")); + } + } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/MyPlotSubCommand.php b/src/MyPlot/subcommand/MyPlotSubCommand.php new file mode 100644 index 00000000..4e4aab39 --- /dev/null +++ b/src/MyPlot/subcommand/MyPlotSubCommand.php @@ -0,0 +1,27 @@ +plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.name")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if($this->plugin->renamePlot($plot, $args[0])) { - $sender->sendMessage($this->translateString("name.success")); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.name")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(yield $this->internalAPI->generateRenamePlot($plot, $args[0])){ + $sender->sendMessage($this->translateString("name.success")); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } + } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) instanceof Plot) - return new NameForm($player, $plot); - return null; + public function getFormClass() : ?string{ + return NameForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/PvpSubCommand.php b/src/MyPlot/subcommand/PvpSubCommand.php index 2e2459e7..9d20a6dc 100644 --- a/src/MyPlot/subcommand/PvpSubCommand.php +++ b/src/MyPlot/subcommand/PvpSubCommand.php @@ -6,6 +6,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class PvpSubCommand extends SubCommand { @@ -19,30 +20,30 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED.$this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.pvp")) { - $sender->sendMessage(TextFormat::RED.$this->translateString("notowner")); - return true; - } - $levelSettings = $this->plugin->getLevelSettings($sender->getWorld()->getFolderName()); - if($levelSettings->restrictPVP) { - $sender->sendMessage(TextFormat::RED.$this->translateString("pvp.world")); - return true; - } - if($this->plugin->setPlotPvp($plot, !$plot->pvp)) { - $sender->sendMessage($this->translateString("pvp.success", [!$plot->pvp ? "enabled" : "disabled"])); - }else { - $sender->sendMessage(TextFormat::RED.$this->translateString("error")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.pvp")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + $levelSettings = $this->plugin->getLevelSettings($sender->getWorld()->getFolderName()); + if($levelSettings->restrictPVP){ + $sender->sendMessage(TextFormat::RED . $this->translateString("pvp.world")); + return; + } + if(yield $this->internalAPI->generatePlotPvp($plot, !$plot->pvp)){ + $sender->sendMessage($this->translateString("pvp.success", [!$plot->pvp ? "enabled" : "disabled"])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } + } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/RemoveHelperSubCommand.php b/src/MyPlot/subcommand/RemoveHelperSubCommand.php index 7ef7d1d2..7fff1afc 100644 --- a/src/MyPlot/subcommand/RemoveHelperSubCommand.php +++ b/src/MyPlot/subcommand/RemoveHelperSubCommand.php @@ -8,6 +8,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class RemoveHelperSubCommand extends SubCommand { @@ -21,34 +22,37 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $helperName = $args[0]; - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.removehelper")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - $helper = $this->plugin->getServer()->getPlayerByPrefix($helperName); - if($helper === null) - $helper = $this->plugin->getServer()->getOfflinePlayer($helperName); - if($this->plugin->removePlotHelper($plot, $helper->getName())) { - $sender->sendMessage($this->translateString("removehelper.success", [$helper->getName()])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $helperName = $args[0]; + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.removehelper")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + $helper = $this->plugin->getServer()->getPlayerByPrefix($helperName); + if($helper === null) + $helper = $this->plugin->getServer()->getOfflinePlayer($helperName); + if(yield $this->internalAPI->generateRemovePlotHelper($plot, $helper->getName())){ + $sender->sendMessage($this->translateString("removehelper.success", [$helper->getName()])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } + } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) instanceof Plot) - return new RemoveHelperForm($plot); - return null; + public function getFormClass() : ?string{ + return RemoveHelperForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/ResetSubCommand.php b/src/MyPlot/subcommand/ResetSubCommand.php index 6a2705e0..0064b865 100644 --- a/src/MyPlot/subcommand/ResetSubCommand.php +++ b/src/MyPlot/subcommand/ResetSubCommand.php @@ -6,6 +6,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class ResetSubCommand extends SubCommand { @@ -19,38 +20,39 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.reset")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if(isset($args[0]) and $args[0] == $this->translateString("confirm")) { - $economy = $this->plugin->getEconomyProvider(); - $price = $this->plugin->getLevelSettings($plot->levelName)->resetPrice; - if($economy !== null and !$economy->reduceMoney($sender, $price)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("reset.nomoney")); - return true; + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.reset")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(!isset($args[0]) and $args[0] !== $this->translateString("confirm")){ + $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("reset.confirm", [$plotId])); + return; + } + $economy = $this->internalAPI->getEconomyProvider(); + $price = $this->plugin->getLevelSettings($plot->levelName)->resetPrice; + if($economy !== null and !(yield $economy->reduceMoney($sender, $price))){ + $sender->sendMessage(TextFormat::RED . $this->translateString("reset.nomoney")); + return; + } + $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); + if(!is_int($maxBlocksPerTick)) + $maxBlocksPerTick = 256; + if(yield $this->internalAPI->generateResetPlot($plot, $maxBlocksPerTick)){ + $sender->sendMessage($this->translateString("reset.success")); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - /** @var int $maxBlocksPerTick */ - $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); - if($this->plugin->resetPlot($plot, $maxBlocksPerTick)) { - $sender->sendMessage($this->translateString("reset.success")); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } - }else{ - $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; - $sender->sendMessage($this->translateString("reset.confirm", [$plotId])); - } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - return null; - } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/SellSubCommand.php b/src/MyPlot/subcommand/SellSubCommand.php index 7a515371..6a822a92 100644 --- a/src/MyPlot/subcommand/SellSubCommand.php +++ b/src/MyPlot/subcommand/SellSubCommand.php @@ -6,6 +6,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class SellSubCommand extends SubCommand { @@ -19,34 +20,38 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null){ - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.sell")){ - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - if(!is_numeric($args[0])) - return false; - $price = (float)$args[0]; - if($this->plugin->sellPlot($plot, $price) and $price > 0) { - $sender->sendMessage($this->translateString("sell.success", ["$plot->X;$plot->Z", $price])); - }elseif($price <= 0){ - $sender->sendMessage(TextFormat::RED . $this->translateString("sell.unlisted", ["$plot->X;$plot->Z"])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.sell")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + if(!is_numeric($args[0])){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $price = (int) $args[0]; + if($price <= 0){ + $sender->sendMessage(TextFormat::RED . $this->translateString("sell.unlisted", ["$plot->X;$plot->Z"])); + return; + } + if(yield $this->internalAPI->generateSellPlot($plot, $price)){ + $sender->sendMessage($this->translateString("sell.success", ["$plot->X;$plot->Z", $price])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } + } + ); return true; } - - public function getForm(?Player $player = null) : ?MyPlotForm { - // TODO: Implement getForm() method. - return null; - } } diff --git a/src/MyPlot/subcommand/SetOwnerSubCommand.php b/src/MyPlot/subcommand/SetOwnerSubCommand.php index 34f09c1e..babb60c2 100644 --- a/src/MyPlot/subcommand/SetOwnerSubCommand.php +++ b/src/MyPlot/subcommand/SetOwnerSubCommand.php @@ -8,6 +8,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class SetOwnerSubCommand extends SubCommand { public function canUse(CommandSender $sender) : bool { @@ -20,38 +21,34 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); - $plotsOfPlayer = 0; - foreach($this->plugin->getPlotLevels() as $level => $settings) { - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($level); - if($level !== null and $level->isLoaded()) { - $plotsOfPlayer += count($this->plugin->getPlotsOfPlayer($sender->getName(), $level->getFolderName())); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); + if(count($this->internalAPI->generatePlotsOfPlayer($sender->getName(), null)) >= $maxPlots){ + $sender->sendMessage(TextFormat::RED . $this->translateString("setowner.maxplots", [$maxPlots])); + return; + } + if(yield $this->internalAPI->generateClaimPlot($plot, $args[0], '')){ + $sender->sendMessage($this->translateString("setowner.success", [$args[0]])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - } - if($plotsOfPlayer >= $maxPlots) { - $sender->sendMessage(TextFormat::RED . $this->translateString("setowner.maxplots", [$maxPlots])); - return true; - } - if($this->plugin->claimPlot($plot, $args[0])) { - $sender->sendMessage($this->translateString("setowner.success", [$args[0]])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and $this->plugin->getPlotByPosition($player->getPosition()) instanceof Plot) - return new OwnerForm(); - return null; + public function getFormClass() : ?string{ + return OwnerForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/SubCommand.php b/src/MyPlot/subcommand/SubCommand.php index dc4b9b22..9e66fa6b 100644 --- a/src/MyPlot/subcommand/SubCommand.php +++ b/src/MyPlot/subcommand/SubCommand.php @@ -3,41 +3,21 @@ namespace MyPlot\subcommand; use MyPlot\forms\MyPlotForm; +use MyPlot\InternalAPI; use MyPlot\MyPlot; use pocketmine\command\CommandSender; use pocketmine\player\Player; -abstract class SubCommand -{ - protected MyPlot $plugin; - private string $name; +abstract class SubCommand implements MyPlotSubCommand{ + public function __construct(protected MyPlot $plugin, protected InternalAPI $internalAPI, private string $name){ } - public function __construct(MyPlot $plugin, string $name) { - $this->plugin = $plugin; - $this->name = $name; - } - - /** - * @return MyPlot - */ - public final function getPlugin() : MyPlot { - return $this->plugin; - } - - /** - * @param string $str - * @param (float|int|string)[] $params - * @param string $onlyPrefix - * - * @return string - */ - protected function translateString(string $str, array $params = [], string $onlyPrefix = null) : string { - return $this->plugin->getLanguage()->translateString($str, $params, $onlyPrefix); - } + protected function translateString(string $str, array $params = [], ?string $onlyPrefix = null) : string{ + return $this->plugin->getLanguage()->translateString($str, $params, $onlyPrefix); + } public abstract function canUse(CommandSender $sender) : bool; - public function getUsage() : string { + public function getUsage() : string{ $usage = $this->plugin->getFallBackLang()->get($this->name . ".usage"); // TODO: use normal language when command autofill gains support return ($usage == $this->name . ".usage") ? "" : $usage; } @@ -47,23 +27,19 @@ public function getName() : string { return ($name == $this->name . ".name") ? "" : $name; } - public function getDescription() : string { - $desc = $this->plugin->getLanguage()->get($this->name . ".desc"); - return ($desc == $this->name . ".desc") ? "" : $desc; - } + public function getDescription() : string{ + $desc = $this->plugin->getLanguage()->get($this->name . ".desc"); + return ($desc == $this->name . ".desc") ? "" : $desc; + } - public function getAlias() : string { - $alias = $this->plugin->getLanguage()->get($this->name . ".alias"); - return ($alias == $this->name . ".alias") ? "" : $alias; - } + public function getAlias() : string{ + $alias = $this->plugin->getLanguage()->get($this->name . ".alias"); + return ($alias == $this->name . ".alias") ? "" : $alias; + } - public abstract function getForm(?Player $player = null) : ?MyPlotForm; + public function getFormClass() : ?string{ + return null; + } - /** - * @param CommandSender $sender - * @param string[] $args - * - * @return bool - */ public abstract function execute(CommandSender $sender, array $args) : bool; } \ No newline at end of file diff --git a/src/MyPlot/subcommand/UnDenySubCommand.php b/src/MyPlot/subcommand/UnDenySubCommand.php index 2f480525..60f8ae07 100644 --- a/src/MyPlot/subcommand/UnDenySubCommand.php +++ b/src/MyPlot/subcommand/UnDenySubCommand.php @@ -8,6 +8,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class UnDenySubCommand extends SubCommand { @@ -21,37 +22,40 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $dplayerName = $args[0]; - $plot = $this->plugin->getPlotByPosition($sender->getPosition()); - if($plot === null) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); - return true; - } - if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.undenyplayer")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); - return true; - } - $dplayer = $this->plugin->getServer()->getPlayerByPrefix($dplayerName); - if($dplayer === null) - $dplayer = $this->plugin->getServer()->getOfflinePlayer($dplayerName); - if($this->plugin->removePlotDenied($plot, $dplayer->getName())) { - $sender->sendMessage($this->translateString("undenyplayer.success1", [$dplayer->getName()])); - if($dplayer instanceof Player) { - $dplayer->sendMessage($this->translateString("undenyplayer.success2", [$plot->X, $plot->Z, $sender->getName()])); + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $dplayerName = $args[0]; + $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + if($plot === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); + return; + } + if($plot->owner !== $sender->getName() and !$sender->hasPermission("myplot.admin.undenyplayer")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); + return; + } + $dplayer = $this->plugin->getServer()->getPlayerByPrefix($dplayerName); + if($dplayer === null) + $dplayer = $this->plugin->getServer()->getOfflinePlayer($dplayerName); + if(yield $this->internalAPI->generateRemovePlotDenied($plot, $dplayer->getName())){ + $sender->sendMessage($this->translateString("undenyplayer.success1", [$dplayer->getName()])); + if($dplayer instanceof Player){ + $dplayer->sendMessage($this->translateString("undenyplayer.success2", [$plot->X, $plot->Z, $sender->getName()])); + } + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("error")); + } } - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("error")); - } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - if($player !== null and ($plot = $this->plugin->getPlotByPosition($player->getPosition())) instanceof Plot) - return new UndenyPlayerForm($plot); - return null; + public function getFormClass() : ?string{ + return UndenyPlayerForm::class; } } \ No newline at end of file diff --git a/src/MyPlot/subcommand/WarpSubCommand.php b/src/MyPlot/subcommand/WarpSubCommand.php index 91a59a4d..f7a6a268 100644 --- a/src/MyPlot/subcommand/WarpSubCommand.php +++ b/src/MyPlot/subcommand/WarpSubCommand.php @@ -7,6 +7,7 @@ use pocketmine\command\CommandSender; use pocketmine\player\Player; use pocketmine\utils\TextFormat; +use SOFe\AwaitGenerator\Await; class WarpSubCommand extends SubCommand { @@ -20,35 +21,40 @@ public function canUse(CommandSender $sender) : bool { * * @return bool */ - public function execute(CommandSender $sender, array $args) : bool { - if(count($args) === 0) { - return false; - } - $levelName = $args[1] ?? $sender->getWorld()->getFolderName(); - if(!$this->plugin->isLevelLoaded($levelName)) { - $sender->sendMessage(TextFormat::RED . $this->translateString("warp.notinplotworld")); - return true; - } - $plotIdArray = explode(";", $args[0]); - if(count($plotIdArray) != 2 or !is_numeric($plotIdArray[0]) or !is_numeric($plotIdArray[1])) { - $sender->sendMessage(TextFormat::RED . $this->translateString("warp.wrongid")); - return true; - } - $plot = $this->plugin->getProvider()->getPlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1]); - if($plot->owner == "" and !$sender->hasPermission("myplot.admin.warp")) { - $sender->sendMessage(TextFormat::RED . $this->translateString("warp.unclaimed")); - return true; - } - if($this->plugin->teleportPlayerToPlot($sender, $plot)) { - $plot = TextFormat::GREEN . $plot . TextFormat::WHITE; - $sender->sendMessage($this->translateString("warp.success", [$plot])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("generate.error")); - } + public function execute(CommandSender $sender, array $args) : bool{ + Await::f2c( + function() use ($sender, $args) : \Generator{ + if(count($args) === 0){ + $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); + return; + } + $levelName = $args[1] ?? $sender->getWorld()->getFolderName(); + if($this->internalAPI->getLevelSettings($levelName) === null){ + $sender->sendMessage(TextFormat::RED . $this->translateString("warp.notinplotworld")); + return; + } + $plotIdArray = explode(";", $args[0]); + if(count($plotIdArray) != 2 or !is_numeric($plotIdArray[0]) or !is_numeric($plotIdArray[1])){ + $sender->sendMessage(TextFormat::RED . $this->translateString("warp.wrongid")); + return; + } + $plot = yield $this->internalAPI->generatePlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1]); + if($plot->owner == "" and !$sender->hasPermission("myplot.admin.warp")){ + $sender->sendMessage(TextFormat::RED . $this->translateString("warp.unclaimed")); + return; + } + if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, false)){ + $plot = TextFormat::GREEN . $plot . TextFormat::WHITE; + $sender->sendMessage($this->translateString("warp.success", [$plot])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("generate.error")); + } + } + ); return true; } - public function getForm(?Player $player = null) : ?MyPlotForm { - return $player !== null ? new WarpForm($player) : null; + public function getFormClass() : ?string{ + return WarpForm::class; } } \ No newline at end of file From 55a9eb19355bb90b06b88862c7706dc6d67678f5 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Wed, 9 Mar 2022 07:56:32 -0500 Subject: [PATCH 37/47] Finalize some classes --- src/MyPlot/EventListener.php | 9 +++------ src/MyPlot/MyPlot.php | 5 ++--- src/MyPlot/provider/EconomyWrapper.php | 2 +- src/MyPlot/provider/InternalCapitalProvider.php | 2 +- src/MyPlot/provider/InternalEconomySProvider.php | 2 +- 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/MyPlot/EventListener.php b/src/MyPlot/EventListener.php index 769d70d0..f4d8ad1e 100644 --- a/src/MyPlot/EventListener.php +++ b/src/MyPlot/EventListener.php @@ -29,19 +29,16 @@ use pocketmine\utils\TextFormat; use pocketmine\world\World; -class EventListener implements Listener -{ - public function __construct(private MyPlot $plugin, private InternalAPI $api) {} +final class EventListener implements Listener{ + public function __construct(private MyPlot $plugin, private InternalAPI $api){ } /** * @ignoreCancelled false * @priority LOWEST * * @param WorldLoadEvent $event - * - * @throws \ReflectionException */ - public function onLevelLoad(WorldLoadEvent $event) : void { + public function onLevelLoad(WorldLoadEvent $event) : void{ if(file_exists($this->plugin->getDataFolder()."worlds".DIRECTORY_SEPARATOR.$event->getWorld()->getFolderName().".yml")) { $this->plugin->getLogger()->debug("MyPlot level " . $event->getWorld()->getFolderName() . " loaded!"); $settings = $event->getWorld()->getProvider()->getWorldData()->getGeneratorOptions(); diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 71851b30..226f756b 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -31,14 +31,13 @@ use pocketmine\world\WorldCreationOptions; use SOFe\Capital\Capital; -class MyPlot extends PluginBase -{ +final class MyPlot extends PluginBase{ private static MyPlot $instance; private Language $language; private InternalAPI $internalAPI; private ?EconomyWrapper $economyProvider; - public static function getInstance() : self { + public static function getInstance() : self{ return self::$instance; } diff --git a/src/MyPlot/provider/EconomyWrapper.php b/src/MyPlot/provider/EconomyWrapper.php index fff6d544..c9e15dbf 100644 --- a/src/MyPlot/provider/EconomyWrapper.php +++ b/src/MyPlot/provider/EconomyWrapper.php @@ -8,7 +8,7 @@ use pocketmine\promise\PromiseResolver; use SOFe\AwaitGenerator\Await; -class EconomyWrapper{ +final class EconomyWrapper{ public function __construct(private InternalEconomyProvider $provider){ } diff --git a/src/MyPlot/provider/InternalCapitalProvider.php b/src/MyPlot/provider/InternalCapitalProvider.php index cbac080d..f67d2e66 100644 --- a/src/MyPlot/provider/InternalCapitalProvider.php +++ b/src/MyPlot/provider/InternalCapitalProvider.php @@ -8,7 +8,7 @@ use SOFe\Capital\Plugin\MainClass; use SOFe\Capital\Schema; -class InternalCapitalProvider implements InternalEconomyProvider{ +final class InternalCapitalProvider implements InternalEconomyProvider{ private Schema\Complete $selector; diff --git a/src/MyPlot/provider/InternalEconomySProvider.php b/src/MyPlot/provider/InternalEconomySProvider.php index 43e9c246..78d5a351 100644 --- a/src/MyPlot/provider/InternalEconomySProvider.php +++ b/src/MyPlot/provider/InternalEconomySProvider.php @@ -5,7 +5,7 @@ use onebone\economyapi\EconomyAPI; use pocketmine\player\Player; -class InternalEconomySProvider implements InternalEconomyProvider{ +final class InternalEconomySProvider implements InternalEconomyProvider{ public function __construct(private EconomyAPI $plugin){ } /** From a6d053536baa4e7f91eb15c42652a57c2e0f11cb Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Wed, 9 Mar 2022 18:32:30 -0500 Subject: [PATCH 38/47] fix some sql bugs --- resources/mysql.sql | 4 ++-- resources/sqlite.sql | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/resources/mysql.sql b/resources/mysql.sql index e62c0ed0..c1b5946f 100644 --- a/resources/mysql.sql +++ b/resources/mysql.sql @@ -123,7 +123,6 @@ WHERE mergedPlotsV2.level = :level AND mergedZ = :mergedZ; -- # } -- # } --- # } -- # {merge-plots -- # {by-origin -- # :level string @@ -182,4 +181,5 @@ WHERE level = :level AND Z = :z; -- # } -- # } --- # } \ No newline at end of file +-- # } +-- #} \ No newline at end of file diff --git a/resources/sqlite.sql b/resources/sqlite.sql index 2018d14f..bae7eadc 100644 --- a/resources/sqlite.sql +++ b/resources/sqlite.sql @@ -120,7 +120,6 @@ WHERE mergedPlotsV2.level = :level AND mergedZ = :mergedZ; -- # } -- # } --- # } -- # {merge-plots -- # {by-origin -- # :level string @@ -164,17 +163,20 @@ WHERE level = :level -- # :X int -- # :Z int -- # :biome string +-- # :pvp bool false +-- # :price int UPDATE plotsV2 SET name = '', owner = '', helpers = '', denied = '', biome = :biome, - pvp = 0, - price = 0.0 + pvp = :pvp, + price = :price WHERE level = :level AND X = :X AND Z = :Z; -- # } -- # } --- # } \ No newline at end of file +-- # } +-- #} \ No newline at end of file From 3a4ab3614b1254c6214a87e59d597b0aa13f81e4 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Wed, 9 Mar 2022 18:37:21 -0500 Subject: [PATCH 39/47] Added sql for merge entry deletion --- resources/mysql.sql | 14 ++++++++++++++ resources/sqlite.sql | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/resources/mysql.sql b/resources/mysql.sql index c1b5946f..e2054531 100644 --- a/resources/mysql.sql +++ b/resources/mysql.sql @@ -181,5 +181,19 @@ WHERE level = :level AND Z = :z; -- # } -- # } +-- # {merge-entry +-- # :level string +-- # :originX int +-- # :originZ int +-- # :mergedX int +-- # :mergedZ int +DELETE +FROM mergedPlotsV2 +WHERE level = :level + AND originX = :originX + AND originZ = :originZ + AND mergedX = :mergedX + AND mergedZ = :mergedZ; +-- # } -- # } -- #} \ No newline at end of file diff --git a/resources/sqlite.sql b/resources/sqlite.sql index bae7eadc..828bf7dc 100644 --- a/resources/sqlite.sql +++ b/resources/sqlite.sql @@ -178,5 +178,19 @@ WHERE level = :level AND Z = :Z; -- # } -- # } +-- # {merge-entry +-- # :level string +-- # :originX int +-- # :originZ int +-- # :mergedX int +-- # :mergedZ int +DELETE +FROM mergedPlotsV2 +WHERE level = :level + AND originX = :originX + AND originZ = :originZ + AND mergedX = :mergedX + AND mergedZ = :mergedZ; +-- # } -- # } -- #} \ No newline at end of file From 90ef3b576237c73e91e5c33be917213ac1af97aa Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Thu, 10 Mar 2022 03:39:48 -0500 Subject: [PATCH 40/47] Formatted SQL --- resources/mysql.sql | 51 ++++++++++++++++++++++++++++++-------------- resources/sqlite.sql | 45 ++++++++++++++++++++++++++------------ 2 files changed, 66 insertions(+), 30 deletions(-) diff --git a/resources/mysql.sql b/resources/mysql.sql index e2054531..5b20831b 100644 --- a/resources/mysql.sql +++ b/resources/mysql.sql @@ -41,7 +41,8 @@ CREATE TABLE IF NOT EXISTS mergedPlotsV2 -- # :biome string -- # :pvp bool false -- # :price int -INSERT INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) +INSERT +INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) VALUES (:level, :X, :Z, :name, :owner, :helpers, :denied, :biome, :pvp, :price) ON DUPLICATE KEY UPDATE name = VALUES(:name), owner = VALUES(:owner), @@ -57,7 +58,8 @@ ON DUPLICATE KEY UPDATE name = VALUES(:name), -- # :originZ int -- # :mergedX int -- # :mergedZ int -INSERT IGNORE INTO mergedPlotsV2 (`level`, `originX`, `originZ`, `mergedX`, `mergedZ`) +INSERT IGNORE +INTO mergedPlotsV2 (`level`, `originX`, `originZ`, `mergedX`, `mergedZ`) VALUES (:level, :originX, :originZ, :mergedX, :mergedZ); -- # } -- # } @@ -101,11 +103,11 @@ FROM plotsV2 WHERE (level = :level AND ((abs(X) = :number AND abs(Z) <= :number) OR (abs(Z) = :number AND abs(X) <= :number))); -- # } -- # } --- # {merge-origin --- # {by-merged +-- # {merge-plots +-- # {by-origin -- # :level string --- # :mergedX int --- # :mergedZ int +-- # :originX int +-- # :originZ int SELECT plotsV2.level, X, Z, @@ -117,17 +119,20 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level - AND mergedX = :mergedX - AND mergedZ = :mergedZ; + AND originX = :originX + AND originZ = :originZ; -- # } -- # } -- # {merge-plots --- # {by-origin +-- # {by-merged -- # :level string --- # :originX int --- # :originZ int +-- # :mergedX int +-- # :mergedZ int SELECT plotsV2.level, X, Z, @@ -139,11 +144,25 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedPlotsV2.mergedX = plotsV2.X AND - mergedPlotsV2.mergedZ = plotsV2.Z + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level - AND originX = :originX - AND originZ = :originZ; + AND originX = ( + SELECT originX + FROM mergedPlotsV2 + WHERE mergedX = :mergedX + AND mergedZ = :mergedZ + AND mergedPlotsV2.level = :level +) + AND originZ = ( + SELECT originZ + FROM mergedPlotsV2 + WHERE mergedX = :mergedX + AND mergedZ = :mergedZ + AND mergedPlotsV2.level = :level +); -- # } -- # } -- # } diff --git a/resources/sqlite.sql b/resources/sqlite.sql index 828bf7dc..7b13bc0d 100644 --- a/resources/sqlite.sql +++ b/resources/sqlite.sql @@ -98,11 +98,11 @@ FROM plotsV2 WHERE (level = :level AND ((abs(X) = :number AND abs(Z) <= :number) OR (abs(Z) = :number AND abs(X) <= :number))); -- # } -- # } --- # {merge-origin --- # {by-merged +-- # {merge-plots +-- # {by-origin -- # :level string --- # :mergedX int --- # :mergedZ int +-- # :originX int +-- # :originZ int SELECT plotsV2.level, X, Z, @@ -114,17 +114,20 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level - AND mergedX = :mergedX - AND mergedZ = :mergedZ; + AND originX = :originX + AND originZ = :originZ; -- # } -- # } -- # {merge-plots --- # {by-origin +-- # {by-merged -- # :level string --- # :originX int --- # :originZ int +-- # :mergedX int +-- # :mergedZ int SELECT plotsV2.level, X, Z, @@ -136,11 +139,25 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedPlotsV2.mergedX = plotsV2.X AND - mergedPlotsV2.mergedZ = plotsV2.Z + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level - AND originX = :originX - AND originZ = :originZ; + AND originX = ( + SELECT originX + FROM mergedPlotsV2 + WHERE mergedX = :mergedX + AND mergedZ = :mergedZ + AND mergedPlotsV2.level = :level +) + AND originZ = ( + SELECT originZ + FROM mergedPlotsV2 + WHERE mergedX = :mergedX + AND mergedZ = :mergedZ + AND mergedPlotsV2.level = :level +); -- # } -- # } -- # } From 20d83599d548530120ac1bfaefc1dedb553309fb Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Thu, 10 Mar 2022 03:45:02 -0500 Subject: [PATCH 41/47] Clarify logic based on Plot object types --- src/MyPlot/InternalAPI.php | 751 +++++++++------------------ src/MyPlot/MyPlot.php | 104 +--- src/MyPlot/provider/DataProvider.php | 116 +++-- src/MyPlot/utils/AsyncVariants.php | 10 +- 4 files changed, 329 insertions(+), 652 deletions(-) diff --git a/src/MyPlot/InternalAPI.php b/src/MyPlot/InternalAPI.php index c9bfe2b2..9133d09c 100644 --- a/src/MyPlot/InternalAPI.php +++ b/src/MyPlot/InternalAPI.php @@ -28,16 +28,16 @@ use pocketmine\block\Block; use pocketmine\block\VanillaBlocks; use pocketmine\data\bedrock\BiomeIds; +use pocketmine\math\Axis; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; -use pocketmine\promise\PromiseResolver; use pocketmine\utils\TextFormat as TF; use pocketmine\world\biome\Biome; use pocketmine\world\biome\BiomeRegistry; +use pocketmine\world\format\Chunk; use pocketmine\world\Position; -use pocketmine\world\World; use SOFe\AwaitGenerator\Await; final class InternalAPI{ @@ -97,18 +97,21 @@ public function generatePlotsToSave(SinglePlot $plot) : \Generator{ $ev = new MyPlotSaveEvent($plot); $ev->call(); $plot = $ev->getPlot(); - $failed = false; - foreach((yield $this->dataProvider->getMergedPlots($plot)) as $merged){ - $savePlot = clone $plot; - $savePlot->X = $merged->X; - $savePlot->Z = $merged->Z; - $savePlot->levelName = $merged->levelName; - $saved = yield $this->dataProvider->savePlot($plot); - if(!$saved){ - $failed = true; + if($plot instanceof MergedPlot){ + $failed = false; + for($x = $plot->X; $x <= $plot->xWidth + $plot->X; ++$x){ + for($z = $plot->Z; $z <= $plot->zWidth + $plot->Z; ++$z){ + $newPlot = clone $plot; + $newPlot->X = $x; + $newPlot->Z = $z; + if(yield $this->dataProvider->savePlot($newPlot)){ + $failed = true; + } + } } + return $failed; } - return !$failed; + return yield $this->dataProvider->savePlot($plot); } /** @@ -133,7 +136,7 @@ public function getPlotsOfPlayer(string $username, ?string $levelName, ?callable * * @return \Generator> */ - public function generatePlotsOfPlayer(string $username, ?string $levelName) : \Generator { + public function generatePlotsOfPlayer(string $username, ?string $levelName) : \Generator{ return yield $this->dataProvider->getPlotsByOwner($username, $levelName); } @@ -182,32 +185,27 @@ public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) } /** - * @param string $worldName - * @param int $X - * @param int $Z + * @param BasePlot $plot * @param callable|null $onComplete - * @phpstan-param (callable(SinglePlot): void)|null $onComplete + * @phpstan-param (callable(SinglePlot|null): void)|null $onComplete * @param callable|null $onFail * @phpstan-param (callable(\Throwable): void)|null $catches */ - public function getPlot(string $worldName, int $X, int $Z, ?callable $onComplete = null, ?callable $onFail = null) : void { + public function getPlot(BasePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ Await::g2c( - $this->generatePlot($worldName, $X, $Z), + $this->generatePlot($plot), $onComplete, $onFail === null ? [] : [$onFail] ); } /** - * @param string $worldName - * @param int $X - * @param int $Z + * @param BasePlot $plot * - * @return \Generator + * @return \Generator */ - public function generatePlot(string $worldName, int $X, int $Z) : \Generator { - // TODO: if merged return MergedPlot object - return yield $this->dataProvider->getPlot($worldName, $X, $Z); + public function generatePlot(BasePlot $plot) : \Generator{ + return yield $this->dataProvider->getMergedPlot($plot); } /** @@ -234,62 +232,23 @@ public function generatePlotByPosition(Position $position) : \Generator{ $plotLevel = $this->getLevelSettings($levelName); $plot = $this->getPlotFast($x, $z, $plotLevel); - if($plot instanceof SinglePlot) - return yield $this->dataProvider->getMergeOrigin($plot); - - $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); - if(!$basePlot->isMerged()) - return null; - - // no plot found at current location yet, so search cardinal directions - $plotN = $basePlot->getSide(Facing::NORTH); - if($plotN->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotN); - - $plotS = $basePlot->getSide(Facing::SOUTH); - if($plotS->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotS); - - $plotE = $basePlot->getSide(Facing::EAST); - if($plotE->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotE); - - $plotW = $basePlot->getSide(Facing::WEST); - if($plotW->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotW); - + if($plot !== null) + return yield $this->generatePlot($plot); return null; } /** - * @param SinglePlot $plot - * @param bool $mergeOrigin - * @param callable|null $onComplete - * @phpstan-param (callable(Position): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches + * @param BasePlot $plot + * + * @return Position */ - public function getPlotPosition(SinglePlot $plot, bool $mergeOrigin, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generatePlotPosition($plot, $mergeOrigin), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - public function generatePlotPosition(BasePlot $plot, bool $mergeOrigin) : \Generator{ + public function getPlotPosition(BasePlot $plot) : Position{ $plotLevel = $this->getLevelSettings($plot->levelName); - $origin = yield $this->dataProvider->getMergeOrigin($plot); $plotSize = $plotLevel->plotSize; $roadWidth = $plotLevel->roadWidth; $totalSize = $plotSize + $roadWidth; - if($mergeOrigin){ - $x = $totalSize * $origin->X; - $z = $totalSize * $origin->Z; - }else{ - $x = $totalSize * $plot->X; - $z = $totalSize * $plot->Z; - } + $x = $totalSize * $plot->X; + $z = $totalSize * $plot->Z; $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); return new Position($x, $plotLevel->groundHeight, $z, $level); } @@ -305,7 +264,7 @@ public function isPositionBorderingPlot(Position $position, ?callable $onComplet Await::f2c( function() use ($position){ $plot = yield $this->generatePlotBorderingPosition($position); - return $plot instanceof SinglePlot; + return $plot instanceof BasePlot; }, $onComplete, $onFail === null ? [] : [$onFail] @@ -336,94 +295,44 @@ public function generatePlotBorderingPosition(Position $position) : \Generator{ $z = $pos->z; $levelName = $pos->getWorld()->getFolderName(); - if($this->getLevelSettings($levelName) === null) + $plotLevel = $this->getLevelSettings($levelName); + if($plotLevel === null) return null; - $plotLevel = $this->getLevelSettings($levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $totalSize = $plotSize + $roadWidth; - if($x >= 0){ - $X = (int) floor($x / $totalSize); - $difX = $x % $totalSize; - }else{ - $X = (int) ceil(($x - $plotSize + 1) / $totalSize); - $difX = abs(($x - $plotSize + 1) % $totalSize); - } - if($z >= 0){ - $Z = (int) floor($z / $totalSize); - $difZ = $z % $totalSize; - }else{ - $Z = (int) ceil(($z - $plotSize + 1) / $totalSize); - $difZ = abs(($z - $plotSize + 1) % $totalSize); - } - if(($difX > $plotSize - 1) or ($difZ > $plotSize - 1)){ - $basePlot = yield $this->dataProvider->getPlot($levelName, $x, $z); - if(!$basePlot->isMerged()) - return null; - - // no plot found at current location yet, so search cardinal directions - $plotN = $basePlot->getSide(Facing::NORTH); - if($plotN->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotN); - - $plotS = $basePlot->getSide(Facing::SOUTH); - if($plotS->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotS); - - $plotE = $basePlot->getSide(Facing::EAST); - if($plotE->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotE); - - $plotW = $basePlot->getSide(Facing::WEST); - if($plotW->isSame($basePlot)) - return yield $this->dataProvider->getMergeOrigin($plotW); - continue; + $plot = $this->getPlotFast($x, $z, $plotLevel); + if($plot === null){ + $plot = yield $this->generatePlot(new BasePlot($levelName, $x, $z)); + if(!$plot instanceof MergedPlot) // TODO: add more merge checks + continue; + return $plot; } - return yield $this->dataProvider->getPlot($levelName, $X, $Z); + return $plot; } return null; } - /** - * @param SinglePlot $plot - * @param callable|null $onComplete - * @phpstan-param (callable(AxisAlignedBB): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function getPlotBB(SinglePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generatePlotBB($plot), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - public function generatePlotBB(BasePlot $plot) : \Generator{ + public function getPlotBB(BasePlot $plot) : ?AxisAlignedBB{ $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize - 1; - $pos = yield $this->generatePlotPosition($plot, false); - $xMax = $pos->x + $plotSize; - $zMax = $pos->z + $plotSize; - foreach((yield $this->dataProvider->getMergedPlots($plot)) as $mergedPlot){ - $xplot = (yield $this->generatePlotPosition($mergedPlot, false))->x; - $zplot = (yield $this->generatePlotPosition($mergedPlot, false))->z; - $xMaxPlot = (int) ($xplot + $plotSize); - $zMaxPlot = (int) ($zplot + $plotSize); - if($pos->x > $xplot) $pos->x = $xplot; - if($pos->z > $zplot) $pos->z = $zplot; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + if($plotLevel === null) + return null; + + $plotSize = $plotLevel->plotSize; + $totalSize = $plotSize + $plotLevel->roadWidth; + $pos = $this->getPlotPosition($plot); + $xMax = $pos->x + $plotSize - 1; + $zMax = $pos->z + $plotSize - 1; + if($plot instanceof MergedPlot){ + $xMax = $pos->x + $totalSize * $plot->xWidth - 1; + $zMax = $pos->z + $totalSize * $plot->zWidth - 1; } return new AxisAlignedBB( - min($pos->x, $xMax), + $pos->x, $pos->getWorld()->getMinY(), - min($pos->z, $zMax), - max($pos->x, $xMax), + $pos->z, + $xMax, $pos->getWorld()->getMaxY(), - max($pos->z, $zMax) + $zMax ); } @@ -447,174 +356,89 @@ public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTi public function generateMergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTick) : \Generator{ if($this->getLevelSettings($plot->levelName) === null) return false; - /** @var SinglePlot[][] $toMerge */ - $toMerge = []; - /** @var SinglePlot[] $mergedPlots */ - $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); - $newPlot = $plot->getSide($direction); - $alreadyMerged = false; - foreach($mergedPlots as $mergedPlot){ - if($mergedPlot->isSame($newPlot)){ - $alreadyMerged = true; - } - } - if($alreadyMerged === false and $newPlot->isMerged()){ - $this->plugin->getLogger()->debug("Failed to merge due to plot origin mismatch"); - return false; - } - $toMerge[] = [$plot, $newPlot]; - - foreach($mergedPlots as $mergedPlot){ - $newPlot = $mergedPlot->getSide($direction); - $alreadyMerged = false; - foreach($mergedPlots as $mergedPlot2){ - if($mergedPlot2->isSame($newPlot)){ - $alreadyMerged = true; - } - } - if($alreadyMerged === false and $newPlot->isMerged()){ - $this->plugin->getLogger()->debug("Failed to merge due to plot origin mismatch"); - return false; - } - $toMerge[] = [$mergedPlot, $newPlot]; + + $plot = yield $this->generatePlot($plot); + + /** @var BasePlot[] $toMerge */ + $toMerge[] = $plot->getSide($direction); + if($plot instanceof MergedPlot){ + $toMerge[] = $plot->getSide( + Facing::rotateY($direction, Facing::isPositive($direction)), + Facing::axis($direction) === Axis::X ? $plot->xWidth : $plot->zWidth + ); } + /** @var BasePlot[][] $toFill */ $toFill = []; foreach($toMerge as $pair){ foreach($toMerge as $pair2){ - foreach(Facing::HORIZONTAL as $i){ - if($pair[1]->getSide($i)->isSame($pair2[1])){ - $toFill[] = [$pair[1], $pair2[1]]; - } + if($pair->getSide(Facing::rotateY($direction, !Facing::isPositive($direction)))->isSame($pair2)){ + $toFill[] = [$pair, $pair2]; + } + if($pair->getSide(Facing::opposite($direction))->isSame($pair2)){ + $toFill[] = [$pair, $pair2]; } } } - $ev = new MyPlotMergeEvent(yield $this->dataProvider->getMergeOrigin($plot), $toMerge); - $ev->call(); - if($ev->isCancelled()){ - return false; - } - foreach($toMerge as $pair){ - if($pair[1]->owner === ""){ - $this->plugin->getLogger()->debug("Failed to merge due to plot not claimed"); - return false; - }elseif($plot->owner !== $pair[1]->owner){ - $this->plugin->getLogger()->debug("Failed to merge due to owner mismatch"); + + /** @var SinglePlot[] $toMerge */ + $toMerge = yield AsyncVariants::array_map( + function(SinglePlot $plot) : \Generator{ + return yield $this->generatePlot($plot); + }, + $toMerge + ); + + foreach($toMerge as $newPlot){ + if($newPlot === null or + $newPlot instanceof MergedPlot or + $newPlot->levelName !== $plot->levelName or + $newPlot->owner !== $plot->owner + ) return false; - } } - // TODO: WorldStyler clearing + $ev = new MyPlotMergeEvent($plot, $toMerge); + $ev->call(); + if($ev->isCancelled()) + return false; - foreach($toMerge as $pair) - $this->plugin->getScheduler()->scheduleTask(new RoadFillTask($this->plugin, $pair[0], $pair[1], false, -1, $maxBlocksPerTick)); + // TODO: WorldStyler clearing foreach($toFill as $pair) - $this->plugin->getScheduler()->scheduleTask(new RoadFillTask($this->plugin, $pair[0], $pair[1], true, $direction, $maxBlocksPerTick)); + $this->plugin->getScheduler()->scheduleTask(new RoadFillTask($this->plugin, $this, $pair[0], $pair[1], $maxBlocksPerTick)); - return yield $this->dataProvider->mergePlots(yield $this->dataProvider->getMergeOrigin($plot), ...array_map(function(array $val) : SinglePlot{ - return $val[1]; - }, $toMerge)); + return yield $this->dataProvider->mergePlots($plot, ...$toMerge); } - /** - * @param Player $player - * @param SinglePlot $plot - * @param bool $center - * @param callable|null $onComplete - * @phpstan-param (callable(bool): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function teleportPlayerToPlot(Player $player, SinglePlot $plot, bool $center, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generatePlayerTeleport($player, $plot, $center), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - public function generatePlayerTeleport(Player $player, BasePlot $plot, bool $center) : \Generator{ + public function teleportPlayerToPlot(Player $player, BasePlot $plot, bool $center = false) : bool{ $ev = new MyPlotTeleportEvent($plot, $player, $center); $ev->call(); if($ev->isCancelled()) return false; - if($center){ - $pos = $plot instanceof MergedPlot ? yield $this->getMergeMid($plot) : yield $this->getPlotMid($plot); - return $player->teleport($pos); - } + $plotLevel = $this->getLevelSettings($plot->levelName); + $plotSize = $plotLevel->plotSize; + $totalWidth = $plotSize + $plotLevel->roadWidth; + $pos = $this->getPlotPosition($plot); + $pos->y += 1.5; - if($plot instanceof MergedPlot){ - $plotLevel = $this->getLevelSettings($plot->levelName); - - $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); - $minx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->x < (yield $this->generatePlotPosition($b, false))->x ? $a : $b; - }), false))->x; - $maxx = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->x > (yield $this->generatePlotPosition($b, false))->x ? $a : $b; - }), false))->x + $plotLevel->plotSize; - $minz = (yield $this->generatePlotPosition(yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->z < (yield $this->generatePlotPosition($b, false))->z ? $a : $b; - }), false))->z; - - $pos = new Position($minx, $plotLevel->groundHeight, $minz, $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)); - $pos->x = floor(($minx + $maxx) / 2); - $pos->y += 1.5; + if($center and $plot instanceof MergedPlot){ + $pos->x += $pos->x + ($totalWidth * $plot->xWidth) / 2; + $pos->z += $pos->z + ($totalWidth * $plot->zWidth) / 2; + }elseif($center){ + $pos->x += $plotSize / 2; + $pos->z += $plotSize / 2; + }elseif($plot instanceof MergedPlot){ + $pos->x += $pos->x + ($totalWidth * $plot->xWidth) / 2; + $pos->z -= 1; + }else{ + $pos->x += $plotSize / 2; $pos->z -= 1; - return $player->teleport($pos); } - - $plotLevel = $this->getLevelSettings($plot->levelName); - $pos = yield $this->generatePlotPosition($plot, true); - $pos->x += floor($plotLevel->plotSize / 2); - $pos->y += 1.5; - $pos->z -= 1; return $player->teleport($pos); } - private function getPlotMid(BasePlot $plot) : \Generator{ - if($this->getLevelSettings($plot->levelName) === null) - return null; - - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $pos = yield $this->generatePlotPosition($plot, false); - return new Position($pos->x + ($plotSize / 2), $pos->y + 1, $pos->z + ($plotSize / 2), $pos->getWorld()); - } - - private function getMergeMid(SinglePlot $plot) : \Generator{ - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $mergedPlots = yield $this->dataProvider->getMergedPlots($plot); - $minx = (yield $this->generatePlotPosition( - yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->x < (yield $this->generatePlotPosition($b, false))->x ? $a : $b; - }), - false - ))->x; - $maxx = (yield $this->generatePlotPosition( - yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->x > (yield $this->generatePlotPosition($b, false))->x ? $a : $b; - }), - false - ))->x + $plotSize; - $minz = (yield $this->generatePlotPosition( - yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->z < (yield $this->generatePlotPosition($b, false))->z ? $a : $b; - }), - false - ))->z; - $maxz = (yield $this->generatePlotPosition( - yield AsyncVariants::array_reduce($mergedPlots, function(SinglePlot $a, SinglePlot $b){ - return (yield $this->generatePlotPosition($a, false))->z > (yield $this->generatePlotPosition($b, false))->z ? $a : $b; - }), - false - ))->z + $plotSize; - return new Position(($minx + $maxx) / 2, $plotLevel->groundHeight, ($minz + $maxz) / 2, $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)); - } - /** * @param SinglePlot $plot * @param string $claimer @@ -675,28 +499,11 @@ public function generateRenamePlot(SinglePlot $plot, string $newName) : \Generat return yield $this->generatePlotsToSave($ev->getPlot()); } - /** - * @param SinglePlot $plotFrom - * @param SinglePlot $plotTo - * @param WorldStyler $styler - * @param callable|null $onComplete - * @phpstan-param (callable(bool): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generateClonePlot($plotFrom, $plotTo), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - public function generateClonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : \Generator{ + public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : bool{ $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if(!$styler instanceof WorldStyler){ + if(!$styler instanceof WorldStyler) return false; - } + $ev = new MyPlotCloneEvent($plotFrom, $plotTo); $ev->call(); if($ev->isCancelled()) @@ -704,182 +511,130 @@ public function generateClonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : \G $plotFrom = $ev->getPlot(); $plotTo = $ev->getClonePlot(); - if($this->getLevelSettings($plotFrom->levelName) === null or $this->getLevelSettings($plotTo->levelName) === null){ + + if($this->getLevelSettings($plotFrom->levelName) === null or $this->getLevelSettings($plotTo->levelName) === null) + return false; + + $fromMerge = $plotFrom instanceof MergedPlot; + $toMerge = $plotTo instanceof MergedPlot; + if(($fromMerge and !$toMerge) or (!$toMerge and $fromMerge)) + return false; + if($fromMerge and $toMerge and ($plotFrom->xWidth !== $plotTo->xWidth or $plotFrom->zWidth !== $plotTo->zWidth)) return false; - } - $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); - $aabb = yield $this->generatePlotBB($plotTo); - foreach($world->getEntities() as $entity){ - if($aabb->isVectorInXZ($entity->getPosition())){ - if($entity instanceof Player){ - yield $this->generatePlayerTeleport($entity, $plotTo, false); - } - } - } - $plotLevel = $this->getLevelSettings($plotFrom->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plotFrom, true); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = $plotBeginPos->x + $plotSize; - $zMax = $plotBeginPos->z + $plotSize; - foreach(yield $this->dataProvider->getMergedPlots($plotFrom) as $mergedPlot){ - $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); - $xMaxPlot = $pos->x + $plotSize; - $zMaxPlot = $pos->z + $plotSize; - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; - } $selection = $styler->getSelection(99997) ?? new Selection(99997); - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); + + $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plotFrom->levelName); + $fromAABB = $this->getPlotBB($plotFrom); + + $vec1 = new Vector3($fromAABB->minX - 1, $fromAABB->minY, $fromAABB->minZ - 1); + $selection->setPosition(1, $vec1); + $selection->setPosition(2, new Vector3($fromAABB->maxX, $fromAABB->maxY, $fromAABB->maxZ)); $cuboid = Cuboid::fromSelection($selection); //$cuboid = $cuboid->async(); // do not use async because WorldStyler async is very broken right now - $cuboid->copy($level, $vec2, function(float $time, int $changed) : void{ + $cuboid->copy($world, $vec1, function(float $time, int $changed) : void{ $this->plugin->getLogger()->debug(TF::GREEN . 'Copied ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's to the MyPlot clipboard.'); }); - $plotLevel = $this->getLevelSettings($plotTo->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plotTo, true); - $level = $plotBeginPos->getWorld(); - $plotBeginPos = $plotBeginPos->subtract(1, 0, 1); - $plotBeginPos->y = 0; - $xMax = $plotBeginPos->x + $plotSize; - $zMax = $plotBeginPos->z + $plotSize; - foreach(yield $this->dataProvider->getMergedPlots($plotTo) as $mergedPlot){ - $pos = (yield $this->generatePlotPosition($mergedPlot, false))->subtract(1, 0, 1); - $xMaxPlot = $pos->x + $plotSize; - $zMaxPlot = $pos->z + $plotSize; - if($plotBeginPos->x > $pos->x) $plotBeginPos->x = $pos->x; - if($plotBeginPos->z > $pos->z) $plotBeginPos->z = $pos->z; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plotTo->levelName); + $toAABB = $this->getPlotBB($plotTo); + foreach($world->getEntities() as $entity){ + if($toAABB->isVectorInXZ($entity->getPosition())){ + if($entity instanceof Player){ + $this->teleportPlayerToPlot($entity, $plotTo, false); + }else{ + $entity->flagForDespawn(); + } + } } - $selection->setPosition(1, $plotBeginPos); - $vec2 = new Vector3($xMax + 1, $level->getMaxY() - 1, $zMax + 1); - $selection->setPosition(2, $vec2); + + $vec1 = new Vector3($toAABB->minX - 1, $toAABB->minY, $toAABB->minZ - 1); + $selection->setPosition(1, $vec1); + $selection->setPosition(2, new Vector3($toAABB->maxX, $toAABB->maxY, $toAABB->maxZ)); $commonShape = CommonShape::fromSelection($selection); //$commonShape = $commonShape->async(); // do not use async because WorldStyler async is very broken right now - $commonShape->paste($level, $vec2, true, function(float $time, int $changed) : void{ + $commonShape->paste($world, $vec1, true, function(float $time, int $changed) : void{ $this->plugin->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); }); $styler->removeSelection(99997); - foreach((yield $this->generatePlotChunks($plotTo)) as [$chunkX, $chunkZ, $chunk]){ - $level->setChunk($chunkX, $chunkZ, $chunk); + foreach($this->getPlotChunks($plotTo) as [$chunkX, $chunkZ, $chunk]){ + $world->setChunk($chunkX, $chunkZ, $chunk); } return true; } - /** - * @param SinglePlot $plot - * @param int $maxBlocksPerTick - * @param callable|null $onComplete - * @phpstan-param (callable(bool): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function clearPlot(BasePlot $plot, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generateClearPlot($plot, $maxBlocksPerTick), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - public function generateClearPlot(BasePlot $plot, int $maxBlocksPerTick) : \Generator{ + public function clearPlot(BasePlot $plot, int $maxBlocksPerTick) : bool{ $ev = new MyPlotClearEvent($plot, $maxBlocksPerTick); $ev->call(); - if($ev->isCancelled()){ + if($ev->isCancelled()) return false; - } $plot = $ev->getPlot(); - if($this->getLevelSettings($plot->levelName) === null){ - return false; - } $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null){ + $plotLevel = $this->getLevelSettings($plot->levelName); + if($plotLevel === null) return false; - } - foreach($level->getEntities() as $entity){ - if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition())){ - if(!$entity instanceof Player){ - $entity->flagForDespawn(); - }else{ - $this->generatePlayerTeleport($entity, $plot, false); - } - } - } + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if($this->plugin->getConfig()->get("FastClearing", false) === true && $styler instanceof WorldStyler){ - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plot, true); - $xMax = $plotBeginPos->x + $plotSize; - $zMax = $plotBeginPos->z + $plotSize; - foreach(yield $this->dataProvider->getMergedPlots($plot) as $mergedPlot){ - $xplot = (yield $this->generatePlotPosition($mergedPlot, false))->x; - $zplot = (yield $this->generatePlotPosition($mergedPlot, false))->z; - $xMaxPlot = (int) ($xplot + $plotSize); - $zMaxPlot = (int) ($zplot + $plotSize); - if($plotBeginPos->x > $xplot) $plotBeginPos->x = $xplot; - if($plotBeginPos->z > $zplot) $plotBeginPos->z = $zplot; - if($xMax < $xMaxPlot) $xMax = $xMaxPlot; - if($zMax < $zMaxPlot) $zMax = $zMaxPlot; + if($this->plugin->getConfig()->get("FastClearing", false) === true and $styler instanceof WorldStyler){ + $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($world === null) + return false; + + $aabb = $this->getPlotBB($plot); + foreach($world->getEntities() as $entity){ + if($aabb->isVectorInXZ($entity->getPosition())){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->teleportPlayerToPlot($entity, $plot, false); + } + } } - // Above ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight + 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, World::Y_MAX, $zMax)); + + // Above ground + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->maxY, $aabb->maxZ)); $cuboid = Cuboid::fromSelection($selection); //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), VanillaBlocks::AIR()->getFullId(), function(float $time, int $changed) : void{ + $cuboid->set($world, VanillaBlocks::AIR()->getFullId(), function(float $time, int $changed) : void{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); // Ground Surface $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = $plotLevel->groundHeight; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight, $zMax)); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight, $aabb->maxZ)); $cuboid = Cuboid::fromSelection($selection); //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFloorBlock->getFullId(), function(float $time, int $changed) : void{ + $cuboid->set($world, $plotLevel->plotFloorBlock->getFullId(), function(float $time, int $changed) : void{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); // Ground $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, $plotLevel->groundHeight - 1, $zMax)); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight - 1, $aabb->maxZ)); $cuboid = Cuboid::fromSelection($selection); //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $cuboid->set($world, $plotLevel->plotFillBlock->getFullId(), function(float $time, int $changed) : void{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); // Bottom of world $selection = $styler->getSelection(99998) ?? new Selection(99998); - $plotBeginPos->y = 0; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($xMax, 0, $zMax)); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->minY, $aabb->maxZ)); $cuboid = Cuboid::fromSelection($selection); //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ + $cuboid->set($world, $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); - foreach($this->plugin->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ - $plotBeginPos->getWorld()->setChunk($chunkX, $chunkZ, $chunk); + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ + $world->setChunk($chunkX, $chunkZ, $chunk); } $this->plugin->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this->plugin, $plot), 1); return true; @@ -888,76 +643,48 @@ public function generateClearPlot(BasePlot $plot, int $maxBlocksPerTick) : \Gene return true; } - /** - * @param SinglePlot $plot - * @param Block $plotFillBlock - * @param int $maxBlocksPerTick - * @param callable|null $onComplete - * @phpstan-param (callable(bool): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generateFillPlot($plot, $plotFillBlock, $maxBlocksPerTick), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - public function generateFillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick) : \Generator{ + public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick) : bool{ $ev = new MyPlotFillEvent($plot, $maxBlocksPerTick); $ev->call(); - if($ev->isCancelled()){ + if($ev->isCancelled()) return false; - } $plot = $ev->getPlot(); - if($this->getLevelSettings($plot->levelName) === null){ - return false; - } $maxBlocksPerTick = $ev->getMaxBlocksPerTick(); - foreach($this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName)->getEntities() as $entity){ - if((yield $this->generatePlotBB($plot))->isVectorInXZ($entity->getPosition()) && $entity->getPosition()->y <= $this->getLevelSettings($plot->levelName)->groundHeight){ - if(!$entity instanceof Player){ - $entity->flagForDespawn(); - }else{ - $this->generatePlayerTeleport($entity, $plot, false); - } - } - } - if($this->plugin->getConfig()->get("FastFilling", false) === true){ - $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); - if(!$styler instanceof WorldStyler){ + $plotLevel = $this->getLevelSettings($plot->levelName); + if($plotLevel === null) + return false; + + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if($this->plugin->getConfig()->get("FastFilling", false) === true and $styler instanceof WorldStyler){ + $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($world === null) return false; + + $aabb = $this->getPlotBB($plot); + $aabb->maxY = $this->getLevelSettings($plot->levelName)->groundHeight; + foreach($world->getEntities() as $entity){ + if($aabb->isVectorInside($entity->getPosition())){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->teleportPlayerToPlot($entity, $plot, false); + } + } } - $plotLevel = $this->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize - 1; - $plotBeginPos = yield $this->generatePlotPosition($plot, false); + // Ground $selection = $styler->getSelection(99998); - $plotBeginPos->y = 1; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, $plotLevel->groundHeight, $plotBeginPos->z + $plotSize)); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->maxY, $aabb->maxZ)); $cuboid = Cuboid::fromSelection($selection); //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $cuboid->set($world, $plotFillBlock->getFullId(), function(float $time, int $changed) : void{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); - // Bottom of world - $selection = $styler->getSelection(99998); - $plotBeginPos->y = 0; - $selection->setPosition(1, $plotBeginPos); - $selection->setPosition(2, new Vector3($plotBeginPos->x + $plotSize, 0, $plotBeginPos->z + $plotSize)); - $cuboid = Cuboid::fromSelection($selection); - //$cuboid = $cuboid->async(); - $cuboid->set($plotBeginPos->getWorld(), $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ - $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); - }); - $styler->removeSelection(99998); - foreach((yield $this->generatePlotChunks($plot)) as [$chunkX, $chunkZ, $chunk]){ - $plotBeginPos->getWorld()?->setChunk($chunkX, $chunkZ, $chunk); + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ + $world->setChunk($chunkX, $chunkZ, $chunk); } return true; } @@ -1014,7 +741,7 @@ public function generateResetPlot(SinglePlot $plot, int $maxBlocksPerTick) : \Ge if(!yield $this->generateDisposePlot($plot)){ return false; } - if(!yield $this->generateClearPlot($plot, $maxBlocksPerTick)){ + if(!$this->clearPlot($plot, $maxBlocksPerTick)){ yield $this->generatePlotsToSave($plot); return false; } @@ -1056,7 +783,7 @@ public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ } $failed = false; - foreach(yield $this->dataProvider->getMergedPlots($plot) as $merged){ + foreach(yield $this->dataProvider->getMergedPlot($plot) as $merged){ $merged->biome = $plot->biome; if(!yield $this->dataProvider->savePlot($merged)) $failed = true; @@ -1066,7 +793,7 @@ public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ if($level === null){ return false; } - foreach((yield $this->generatePlotChunks($plot)) as [$chunkX, $chunkZ, $chunk]){ + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ for($x = 0; $x < 16; ++$x){ for($z = 0; $z < 16; ++$z){ $pos = new Position(($chunkX << 4) + $x, $plotLevel->groundHeight, ($chunkZ << 4) + $z, $level); @@ -1279,45 +1006,33 @@ public function generateBuyPlot(SinglePlot $plot, Player $player) : \Generator{ } /** - * @param SinglePlot $plot - * @param callable|null $onComplete - * @phpstan-param (callable(array): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches + * @param BasePlot $plot + * + * @return array + * @phpstan-return array> */ - public function getPlotChunks(SinglePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generatePlotChunks($plot), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - public function generatePlotChunks(BasePlot $plot) : \Generator{ + public function getPlotChunks(BasePlot $plot) : array{ $plotLevel = $this->getLevelSettings($plot->levelName); - if($plotLevel === null){ + if($plotLevel === null) return []; - } + + $aabb = $this->getPlotBB($plot); + $xMin = $aabb->minX >> 4; + $zMin = $aabb->minZ >> 4; + $xMax = $aabb->maxX >> 4; + $zMax = $aabb->maxZ >> 4; + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null){ - return []; - } - $plotSize = $plotLevel->plotSize; $chunks = []; - foreach((yield $this->dataProvider->getMergedPlots($plot)) as $mergedPlot){ - $pos = yield $this->generatePlotPosition($mergedPlot, false); - $xMax = ($pos->x + $plotSize) >> 4; - $zMax = ($pos->z + $plotSize) >> 4; - for($x = $pos->x >> 4; $x <= $xMax; $x++){ - for($z = $pos->z >> 4; $z <= $zMax; $z++){ - $chunks[] = [$x, $z, $level->getChunk($x, $z)]; - } + for($x = $xMin; $x <= $xMax; ++$x){ + for($z = $zMin; $z <= $zMax; ++$z){ + $chunks[] = [$x, $z, $level->getChunk($x, $z)]; } } return $chunks; } - public function onDisable() : void { + public function onDisable() : void{ $this->dataProvider->close(); } } \ No newline at end of file diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 226f756b..10bdb9d8 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -246,14 +246,12 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : Promise{ * @param int $X * @param int $Z * - * @return Promise + * @return Promise */ public function getPlot(string $levelName, int $X, int $Z) : Promise{ $resolver = new PromiseResolver(); $this->internalAPI->getPlot( - $levelName, - $X, - $Z, + new BasePlot($levelName, $X, $Z), fn(?SinglePlot $plot) => $resolver->resolve($plot), fn(\Throwable $e) => $resolver->reject() ); @@ -283,23 +281,14 @@ public function getPlotByPosition(Position $position) : Promise{ /** * Get the beginning position of a plot * - * @api + * @param BasePlot $plot * - * @param SinglePlot $plot - * @param bool $mergeOrigin + * @return Position + * @api * - * @return Promise - * @phpstan-return Promise */ - public function getPlotPosition(SinglePlot $plot, bool $mergeOrigin = true) : Promise{ - $resolver = new PromiseResolver(); - $this->internalAPI->getPlotPosition( - $plot, - $mergeOrigin, - fn(Position $position) => $resolver->resolve($position), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function getPlotPosition(BasePlot $plot) : Position{ + return $this->internalAPI->getPlotPosition($plot); } /** @@ -345,21 +334,14 @@ public function getPlotBorderingPosition(Position $position) : Promise{ /** * Returns the AABB of the plot area * - * @api - * * @param SinglePlot $plot * - * @return Promise - * @phpstan-return Promise + * @return AxisAlignedBB + * @api + * */ - public function getPlotBB(SinglePlot $plot) : Promise{ - $resolver = new PromiseResolver(); - $this->internalAPI->getPlotBB( - $plot, - fn(AxisAlignedBB $bb) => $resolver->resolve($bb), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function getPlotBB(SinglePlot $plot) : AxisAlignedBB{ + return $this->internalAPI->getPlotBB($plot); } /** @@ -395,19 +377,10 @@ public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTi * @param SinglePlot $plot * @param bool $center * - * @return Promise - * @phpstan-return Promise + * @return bool */ - public function teleportPlayerToPlot(Player $player, BasePlot $plot, bool $center = false) : Promise { - $resolver = new PromiseResolver(); - $this->internalAPI->teleportPlayerToPlot( - $player, - $plot, - $center, - fn(bool $success) => $resolver->resolve($success), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function teleportPlayerToPlot(Player $player, BasePlot $plot, bool $center = false) : bool{ + return $this->internalAPI->teleportPlayerToPlot($player, $plot, $center); } /** @@ -464,40 +437,24 @@ public function renamePlot(SinglePlot $plot, string $newName = "") : Promise{ * @param SinglePlot $plotFrom * @param SinglePlot $plotTo * - * @return Promise - * @phpstan-return Promise + * @return bool */ - public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : Promise { - $resolver = new PromiseResolver(); - $this->internalAPI->clonePlot( - $plotFrom, - $plotTo, - fn(bool $success) => $resolver->resolve($success), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : bool{ + return $this->internalAPI->clonePlot($plotFrom, $plotTo); } /** * Reset all the blocks inside a plot * - * @api + * @param BasePlot $plot + * @param int $maxBlocksPerTick * - * @param SinglePlot $plot - * @param int $maxBlocksPerTick + * @return bool + * @api * - * @return Promise - * @phpstan-return Promise */ - public function clearPlot(BasePlot $plot, int $maxBlocksPerTick = 256) : Promise{ - $resolver = new PromiseResolver(); - $this->internalAPI->clearPlot( - $plot, - $maxBlocksPerTick, - fn(bool $success) => $resolver->resolve($success), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function clearPlot(BasePlot $plot, int $maxBlocksPerTick = 256) : bool{ + return $this->internalAPI->clearPlot($plot, $maxBlocksPerTick); } /** @@ -749,16 +706,11 @@ public function buyPlot(SinglePlot $plot, Player $player) : Promise{ * * @param SinglePlot $plot * - * @return Promise> + * @return array + * @phpstan-return array> */ - public function getPlotChunks(SinglePlot $plot) : Promise { - $resolver = new PromiseResolver(); - $this->internalAPI->getPlotChunks( - $plot, - fn(array $chunks) => $resolver->resolve($chunks), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function getPlotChunks(BasePlot $plot) : array{ + $this->internalAPI->getPlotChunks($plot); } /** diff --git a/src/MyPlot/provider/DataProvider.php b/src/MyPlot/provider/DataProvider.php index 62a90e05..ef98e96d 100644 --- a/src/MyPlot/provider/DataProvider.php +++ b/src/MyPlot/provider/DataProvider.php @@ -6,7 +6,6 @@ use MyPlot\plot\BasePlot; use MyPlot\plot\MergedPlot; use MyPlot\plot\SinglePlot; -use pocketmine\math\Facing; use poggit\libasynql\DataConnector; use poggit\libasynql\libasynql; @@ -105,11 +104,11 @@ public function deletePlot(BasePlot $plot) : \Generator{ * @param int $X * @param int $Z * - * @return \Generator + * @return \Generator */ public function getPlot(string $levelName, int $X, int $Z) : \Generator{ $plot = $this->getPlotFromCache($levelName, $X, $Z); - if($plot !== null){ + if($plot instanceof SinglePlot){ return $plot; } $row = yield $this->database->asyncSelect('myplot.get.plot.by-xz', [ @@ -117,6 +116,9 @@ public function getPlot(string $levelName, int $X, int $Z) : \Generator{ 'X' => $X, 'Z' => $Z ]); + if(count($row) < 1) + return null; + return new SinglePlot($levelName, $X, $Z, $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); } @@ -174,18 +176,40 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : \Generato } /** - * @param BasePlot $base - * @param BasePlot ...$plots + * @param SinglePlot $base + * @param BasePlot ...$plots * * @return \Generator */ - public function mergePlots(BasePlot $base, BasePlot ...$plots) : \Generator{ + public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ + $xClosestToZero = 0; + $zClosestToZero = 0; + foreach($plots as $plot){ + if(max(-abs($xClosestToZero), -abs($plot->X))) + $xClosestToZero = $plot->X; + if(max(-abs($zClosestToZero), -abs($plot->Z))) + $zClosestToZero = $plot->Z; + } + $ret = true; foreach($plots as $plot){ + if($xClosestToZero !== $base->X and $zClosestToZero !== $base->Z){ + $affectedRows = yield $this->database->asyncChange('myplot.remove.merge-entry', [ + 'level' => $plot->levelName, + 'originX' => $base->X, + 'originZ' => $base->Z, + 'mergedX' => $plot->X, + 'mergedZ' => $plot->Z + ]); + if($affectedRows < 1){ + MyPlot::getInstance()->getLogger()->debug("Failed to delete merge entry for $plot with base $base"); + $ret = false; + } + } [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.merge', [ - 'level' => $base->levelName, - 'originX' => $base->X, - 'originZ' => $base->Z, + 'level' => $plot->levelName, + 'originX' => $xClosestToZero, + 'originZ' => $zClosestToZero, 'mergedX' => $plot->X, 'mergedZ' => $plot->Z ]); @@ -199,59 +223,45 @@ public function mergePlots(BasePlot $base, BasePlot ...$plots) : \Generator{ /** * @param BasePlot $plot - * @param bool $adjacent * - * @return \Generator> + * @return \Generator */ - public function getMergedPlots(BasePlot $plot, bool $adjacent = false) : \Generator{ - $origin = yield $this->getMergeOrigin($plot); - $rows = $this->database->asyncSelect('myplot.get.merge-plots.by-origin', [ + public function getMergedPlot(BasePlot $plot) : \Generator{ + $rows = yield $this->database->asyncSelect('myplot.get.merge-plots.by-origin', [ 'level' => $plot->levelName, 'originX' => $plot->X, 'originZ' => $plot->Z ]); - $plots = [$origin]; + if(count($rows) < 1){ + $rows = yield $this->database->asyncSelect('myplot.get.merge-plots.by-merged', [ + 'level' => $plot->levelName, + 'mergedX' => $plot->X, + 'mergedZ' => $plot->Z + ]); + if(count($rows) < 1){ + return yield $this->getPlot($plot->levelName, $plot->X, $plot->Z); + } + } + $highestX = $highestZ = $lowestX = $lowestZ = 0; foreach($rows as $row){ - $helpers = explode(",", $row["helpers"]); - $denied = explode(",", $row["denied"]); - $pvp = is_numeric($row["pvp"]) ? (bool) $row["pvp"] : null; - $plots[] = new SinglePlot($row["level"], $row["X"], $row["Z"], $row["name"], $row["owner"], $helpers, $denied, $row["biome"], $pvp, $row["price"]); + $highestX = max($highestX, $row['X']); + $highestZ = max($highestZ, $row['Z']); + $lowestX = max($lowestX, $row['X']); + $lowestZ = max($lowestZ, $row['Z']); } - if($adjacent) - $plots = array_filter($plots, function(BasePlot $val) use ($plot) : bool{ - foreach(Facing::HORIZONTAL as $i){ - if($plot->getSide($i)->isSame($val)) - return true; - } - return false; - }); - return $plots; - } - - /** - * @param BasePlot $plot - * - * @return \Generator - */ - public function getMergeOrigin(BasePlot $plot) : \Generator{ - $row = yield $this->database->asyncSelect('myplot.get.merge-origin.by-merged', [ - 'level' => $plot->levelName, - 'mergedX' => $plot->X, - 'mergedZ' => $plot->Z - ]); return new MergedPlot( - $row['level'], - $row['X'], - $row['Z'], - $row['name'], - $row['owner'], - explode(",", $row['helpers']), - explode(",", $row['denied']), - $row['biome'], - $row['pvp'], - $row['price'], - $xWidth, - $zWidth + $rows[0]["level"], + $rows[0]["X"], + $rows[0]["Z"], + $rows[0]["name"], + $rows[0]["owner"], + explode(",", $rows[0]["helpers"]), + explode(",", $rows[0]["denied"]), + $rows[0]["biome"], + is_numeric($rows[0]["pvp"]) ? (bool) $rows[0]["pvp"] : null, + $rows[0]["price"] * ($highestX - $lowestX) * ($highestZ - $lowestZ), + $highestX - $lowestX, + $highestZ - $lowestZ ); } diff --git a/src/MyPlot/utils/AsyncVariants.php b/src/MyPlot/utils/AsyncVariants.php index a7c7306b..2a13951d 100644 --- a/src/MyPlot/utils/AsyncVariants.php +++ b/src/MyPlot/utils/AsyncVariants.php @@ -2,11 +2,11 @@ declare(strict_types=1); namespace jasonwynn10\MyPlot\utils; -class AsyncVariants { - public static function array_reduce(array $array, callable $callback, mixed $initial = null) : \Generator { - $result = $initial; - foreach($array as $value){ - $result = yield $callback($result, $value); +class AsyncVariants{ + public static function array_map(?callable $callback, array $array, array ...$arrays) : \Generator{ + $result = []; + foreach([$array, ...$arrays] as $key => $value){ + $result[$key] = $callback === null ? $value : yield $callback($value, $key); } return $result; } From b413bc4ca6aad344cd6a33c50bbcc4d8ea0912d9 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Thu, 10 Mar 2022 04:38:20 -0500 Subject: [PATCH 42/47] Implemented MergedPlot caching --- resources/mysql.sql | 21 ++++----- resources/sqlite.sql | 21 ++++----- src/MyPlot/InternalAPI.php | 33 ++++++-------- src/MyPlot/plot/MergedPlot.php | 68 ++++++++++++++++------------ src/MyPlot/plot/SinglePlot.php | 27 ++++++++--- src/MyPlot/provider/DataProvider.php | 65 ++++++++++++++++++-------- 6 files changed, 139 insertions(+), 96 deletions(-) diff --git a/resources/mysql.sql b/resources/mysql.sql index 5b20831b..1c826e32 100644 --- a/resources/mysql.sql +++ b/resources/mysql.sql @@ -79,7 +79,7 @@ WHERE level = :level -- # {all-plots -- # {by-owner -- # :owner string -SELECT * +SELECT level, X, Z FROM plotsV2 WHERE owner = :owner; -- # } @@ -88,7 +88,7 @@ WHERE owner = :owner; -- # {by-owner-and-level -- # :owner string -- # :level string -SELECT * +SELECT level, X, Z FROM plotsV2 WHERE owner = :owner AND level = :level; @@ -119,10 +119,10 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 - ON mergedPlotsV2.level = plotsV2.level - AND mergedX = X - AND mergedZ = Z + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level AND originX = :originX AND originZ = :originZ; @@ -144,10 +144,10 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 - ON mergedPlotsV2.level = plotsV2.level - AND mergedX = X - AND mergedZ = Z + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level AND originX = ( SELECT originX @@ -192,7 +192,6 @@ SET name = '', owner = '', helpers = '', denied = '', - biome = :biome, pvp = :pvp, price = :price WHERE level = :level diff --git a/resources/sqlite.sql b/resources/sqlite.sql index 7b13bc0d..b1ae18c1 100644 --- a/resources/sqlite.sql +++ b/resources/sqlite.sql @@ -74,7 +74,7 @@ WHERE level = :level -- # {all-plots -- # {by-owner -- # :owner string -SELECT * +SELECT level, X, Z FROM plotsV2 WHERE owner = :owner; -- # } @@ -83,7 +83,7 @@ WHERE owner = :owner; -- # {by-owner-and-level -- # :owner string -- # :level string -SELECT * +SELECT level, X, Z FROM plotsV2 WHERE owner = :owner AND level = :level; @@ -114,10 +114,10 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 - ON mergedPlotsV2.level = plotsV2.level - AND mergedX = X - AND mergedZ = Z + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level AND originX = :originX AND originZ = :originZ; @@ -139,10 +139,10 @@ SELECT plotsV2.level, pvp, price FROM plotsV2 - LEFT JOIN mergedPlotsV2 - ON mergedPlotsV2.level = plotsV2.level - AND mergedX = X - AND mergedZ = Z + LEFT JOIN mergedPlotsV2 + ON mergedPlotsV2.level = plotsV2.level + AND mergedX = X + AND mergedZ = Z WHERE mergedPlotsV2.level = :level AND originX = ( SELECT originX @@ -187,7 +187,6 @@ SET name = '', owner = '', helpers = '', denied = '', - biome = :biome, pvp = :pvp, price = :price WHERE level = :level diff --git a/src/MyPlot/InternalAPI.php b/src/MyPlot/InternalAPI.php index 9133d09c..98e55eb0 100644 --- a/src/MyPlot/InternalAPI.php +++ b/src/MyPlot/InternalAPI.php @@ -772,31 +772,24 @@ public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ if($ev->isCancelled()) return false; $plot = $ev->getPlot(); + $plotLevel = $this->getLevelSettings($plot->levelName); + if($plotLevel === null) + return false; + if(defined(BiomeIds::class . "::" . $plot->biome) and is_int(constant(BiomeIds::class . "::" . $plot->biome))){ $biome = constant(BiomeIds::class . "::" . $plot->biome); }else{ $biome = BiomeIds::PLAINS; } $biome = BiomeRegistry::getInstance()->getBiome($biome); - if($this->getLevelSettings($plot->levelName) === null){ - return false; - } - $failed = false; - foreach(yield $this->dataProvider->getMergedPlot($plot) as $merged){ - $merged->biome = $plot->biome; - if(!yield $this->dataProvider->savePlot($merged)) - $failed = true; - } - $plotLevel = $this->getLevelSettings($plot->levelName); $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null){ + if($level === null) return false; - } foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ - for($x = 0; $x < 16; ++$x){ - for($z = 0; $z < 16; ++$z){ - $pos = new Position(($chunkX << 4) + $x, $plotLevel->groundHeight, ($chunkZ << 4) + $z, $level); + for($x = 0; $x < Chunk::EDGE_LENGTH; ++$x){ + for($z = 0; $z < Chunk::EDGE_LENGTH; ++$z){ + $pos = new Position(($chunkX << Chunk::COORD_MASK) + $x, $plotLevel->groundHeight, ($chunkZ << Chunk::COORD_MASK) + $z, $level); $chunkPlot = $this->getPlotFast($pos->x, $pos->z, $plotLevel); if($chunkPlot instanceof SinglePlot and $chunkPlot->isSame($plot)){ $chunk->setBiomeId($x, $z, $biome->getId()); @@ -805,7 +798,7 @@ public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ } $level->setChunk($chunkX, $chunkZ, $chunk); } - return !$failed; + return yield $this->generatePlotsToSave($plot); } /** @@ -1017,10 +1010,10 @@ public function getPlotChunks(BasePlot $plot) : array{ return []; $aabb = $this->getPlotBB($plot); - $xMin = $aabb->minX >> 4; - $zMin = $aabb->minZ >> 4; - $xMax = $aabb->maxX >> 4; - $zMax = $aabb->maxZ >> 4; + $xMin = $aabb->minX >> Chunk::COORD_MASK; + $zMin = $aabb->minZ >> Chunk::COORD_MASK; + $xMax = $aabb->maxX >> Chunk::COORD_MASK; + $zMax = $aabb->maxZ >> Chunk::COORD_MASK; $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); $chunks = []; diff --git a/src/MyPlot/plot/MergedPlot.php b/src/MyPlot/plot/MergedPlot.php index ac303393..1ff7df12 100644 --- a/src/MyPlot/plot/MergedPlot.php +++ b/src/MyPlot/plot/MergedPlot.php @@ -9,29 +9,41 @@ class MergedPlot extends SinglePlot{ - public int $xWidth; - public int $zWidth; - public function __construct( string $levelName, - int $X, - int $Z, + int $X, // Must always be lowest X coordinate in merge array + int $Z, // Must always be lowest Z coordinate in merge array + public int $xWidth, + public int $zWidth, string $name = "", string $owner = "", array $helpers = [], array $denied = [], string $biome = "PLAINS", ?bool $pvp = null, - float $price = -1, - int $xWidth = 0, - int $zWidth = 0, + int $price = -1 ){ - parent::__construct($levelName, $X, $Z, $name, $owner, $helpers, $denied, $biome, $pvp, $price); - if($xWidth === 0 and $zWidth === 0){ + if($xWidth <= 0 and $zWidth <= 0){ throw new \InvalidArgumentException("Plot merge width must be greater than 0"); } - $this->xWidth = $xWidth; - $this->zWidth = $zWidth; + parent::__construct($levelName, $X, $Z, $name, $owner, $helpers, $denied, $biome, $pvp, $price); + } + + public static function fromSingle(SinglePlot $plot, int $xWidth, int $zWidth) : MergedPlot{ + return new MergedPlot( + $plot->levelName, + $plot->X, + $plot->Z, + $xWidth, + $zWidth, + $plot->name, + $plot->owner, + $plot->helpers, + $plot->denied, + $plot->biome, + $plot->pvp, + $plot->price + ); } /** @@ -49,30 +61,30 @@ public function isSame(BasePlot $plot) : bool { return ( new AxisAlignedBB( - min($this->X, $this->X + $this->xWidth), + $this->X, 0, - min($this->Z, $this->Z + $this->zWidth), - max($this->X, $this->X + $this->xWidth), + $this->Z, + $this->X + $this->xWidth, 1, - max($this->Z, $this->Z + $this->zWidth) + $this->Z + $this->zWidth ) )->isVectorInXZ(new Vector3($plot->X, 0, $plot->Z)); } - public function getSide(int $side, int $step = 1) : BasePlot { - if(Facing::axis($side) === Axis::X) { - if(Facing::isPositive($side) and $this->xWidth > 0) { - return parent::getSide($side, $step); - }elseif(!Facing::isPositive($side) and $this->xWidth < 0) { - return parent::getSide($side, $step); + public function getSide(int $side, int $step = 1) : BasePlot{ + $axis = Facing::axis($side); + $isPositive = Facing::isPositive($side); + if($axis === Axis::X){ + if($isPositive){ + return parent::getSide($side, $step + $this->xWidth); } - }elseif(Facing::axis($side) === Axis::Z){ - if(Facing::isPositive($side)and $this->zWidth > 0) { - return parent::getSide($side, $step); - }elseif(!Facing::isPositive($side) and $this->xWidth < 0) { - return parent::getSide($side, $step); + return parent::getSide($side, $step); + }elseif($axis === Axis::Z){ + if($isPositive){ + return parent::getSide($side, $step + $this->zWidth); } + return parent::getSide($side, $step); } - return parent::getSide($side, $step); + throw new \InvalidArgumentException("Invalid Axis " . $axis); } } \ No newline at end of file diff --git a/src/MyPlot/plot/SinglePlot.php b/src/MyPlot/plot/SinglePlot.php index 397f22ca..e664ac83 100644 --- a/src/MyPlot/plot/SinglePlot.php +++ b/src/MyPlot/plot/SinglePlot.php @@ -5,15 +5,13 @@ use MyPlot\MyPlot; class SinglePlot extends BasePlot { - public string $biome = "PLAINS"; public bool $pvp = true; - public int $price = 0; - public function __construct(public string $levelName, public int $X, public int $Z, public string $name = "", public string $owner = "", public array $helpers = [], public array $denied = [], string $biome = "PLAINS", ?bool $pvp = null, float $price = -1) { + public function __construct(public string $levelName, public int $X, public int $Z, public string $name = "", public string $owner = "", public array $helpers = [], public array $denied = [], public string $biome = "PLAINS", ?bool $pvp = null, public int $price = -1){ parent::__construct($levelName, $X, $Z); $this->biome = strtoupper($biome); $settings = MyPlot::getInstance()->getLevelSettings($levelName); - if(!isset($pvp)) { + if(!isset($pvp)){ $this->pvp = !$settings->restrictPVP; }else{ $this->pvp = $pvp; @@ -24,14 +22,29 @@ public function __construct(public string $levelName, public int $X, public int $this->price = 0; } + public static function fromBase(BasePlot $plot, string $name, string $owner, array $helpers, array $denied, string $biome, ?bool $pvp, int $price) : SinglePlot{ + return new SinglePlot( + $plot->levelName, + $plot->X, + $plot->Z, + $name, + $owner, + $helpers, + $denied, + $biome, + $pvp, + $price + ); + } + /** - * @api - * * @param string $username * * @return bool + * @api + * */ - public function isHelper(string $username) : bool { + public function isHelper(string $username) : bool{ return in_array($username, $this->helpers, true); } diff --git a/src/MyPlot/provider/DataProvider.php b/src/MyPlot/provider/DataProvider.php index ef98e96d..1aaddf9c 100644 --- a/src/MyPlot/provider/DataProvider.php +++ b/src/MyPlot/provider/DataProvider.php @@ -26,6 +26,21 @@ public function __construct(private MyPlot $plugin) { private function cachePlot(BasePlot $plot) : void{ if($this->cacheSize > 0){ + if($plot instanceof MergedPlot){ + for($x = $plot->X; $x <= $plot->xWidth + $plot->X; ++$x){ + for($z = $plot->Z; $z <= $plot->zWidth + $plot->Z; ++$z){ + $key = $plot->levelName . ';' . $x . ';' . $z; + if(isset($this->cache[$key])){ + unset($this->cache[$key]); + }elseif($this->cacheSize <= count($this->cache)){ + array_shift($this->cache); + } + $this->cache = array_merge([$key => clone $plot], $this->cache); + $this->plugin->getLogger()->debug("Plot $x;$z has been cached"); + } + } + return; + } $key = $plot->levelName . ';' . $plot->X . ';' . $plot->Z; if(isset($this->cache[$key])){ unset($this->cache[$key]); @@ -79,23 +94,28 @@ public function savePlot(SinglePlot $plot) : \Generator{ * @return \Generator */ public function deletePlot(BasePlot $plot) : \Generator{ - if($plot instanceof MergedPlot) { + if($plot instanceof MergedPlot){ + $plotLevel = $this->plugin->getLevelSettings($plot->levelName); + $changedRows = yield $this->database->asyncChange('myplot.remove.merge.by-xz', [ 'level' => $plot->levelName, 'X' => $plot->X, 'Z' => $plot->Z, + 'pvp' => !$plotLevel->restrictPVP, + 'price' => $plotLevel->claimPrice, ]); + $this->cachePlot(new MergedPlot($plot->levelName, $plot->X, $plot->Z, $plot->xWidth, $plot->zWidth, pvp: !$plotLevel->restrictPVP, price: $plotLevel->claimPrice)); }else{ $changedRows = yield $this->database->asyncChange('myplot.remove.plot.by-xz', [ 'level' => $plot->levelName, 'X' => $plot->X, 'Z' => $plot->Z, ]); + $this->cachePlot(new BasePlot($plot->levelName, $plot->X, $plot->Z)); } if($changedRows < 1){ return false; } - $this->cachePlot(new BasePlot($plot->levelName, $plot->X, $plot->Z)); return true; } @@ -141,7 +161,7 @@ public function getPlotsByOwner(string $owner, string $levelName = "") : \Genera } $plots = []; foreach($rows as $row){ - $plots[] = new SinglePlot($row['level'], $row['X'], $row['Z'], $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + $plots[] = yield $this->getMergedPlot(new BasePlot($row['level'], $row['X'], $row['Z'])); } return $plots; } @@ -182,18 +202,18 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : \Generato * @return \Generator */ public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ - $xClosestToZero = 0; - $zClosestToZero = 0; + $minX = 0; + $minZ = 0; foreach($plots as $plot){ - if(max(-abs($xClosestToZero), -abs($plot->X))) - $xClosestToZero = $plot->X; - if(max(-abs($zClosestToZero), -abs($plot->Z))) - $zClosestToZero = $plot->Z; + if(min($minX, $plot->X)) + $minX = $plot->X; + if(min($minZ, $plot->Z)) + $minZ = $plot->Z; } $ret = true; foreach($plots as $plot){ - if($xClosestToZero !== $base->X and $zClosestToZero !== $base->Z){ + if($minX !== $base->X and $minZ !== $base->Z){ $affectedRows = yield $this->database->asyncChange('myplot.remove.merge-entry', [ 'level' => $plot->levelName, 'originX' => $base->X, @@ -208,8 +228,8 @@ public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ } [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.merge', [ 'level' => $plot->levelName, - 'originX' => $xClosestToZero, - 'originZ' => $zClosestToZero, + 'originX' => $minX, + 'originZ' => $minZ, 'mergedX' => $plot->X, 'mergedZ' => $plot->Z ]); @@ -224,9 +244,13 @@ public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ /** * @param BasePlot $plot * - * @return \Generator + * @return \Generator */ public function getMergedPlot(BasePlot $plot) : \Generator{ + $plot = $this->getPlotFromCache($plot->levelName, $plot->X, $plot->Z); + if($plot instanceof MergedPlot) + return $plot; + $rows = yield $this->database->asyncSelect('myplot.get.merge-plots.by-origin', [ 'level' => $plot->levelName, 'originX' => $plot->X, @@ -246,23 +270,26 @@ public function getMergedPlot(BasePlot $plot) : \Generator{ foreach($rows as $row){ $highestX = max($highestX, $row['X']); $highestZ = max($highestZ, $row['Z']); - $lowestX = max($lowestX, $row['X']); - $lowestZ = max($lowestZ, $row['Z']); + $lowestX = min($lowestX, $row['X']); + $lowestZ = min($lowestZ, $row['Z']); } - return new MergedPlot( + + $plot = new MergedPlot( $rows[0]["level"], $rows[0]["X"], $rows[0]["Z"], + $highestX - $lowestX, + $highestZ - $lowestZ, $rows[0]["name"], $rows[0]["owner"], explode(",", $rows[0]["helpers"]), explode(",", $rows[0]["denied"]), $rows[0]["biome"], is_numeric($rows[0]["pvp"]) ? (bool) $rows[0]["pvp"] : null, - $rows[0]["price"] * ($highestX - $lowestX) * ($highestZ - $lowestZ), - $highestX - $lowestX, - $highestZ - $lowestZ + $rows[0]["price"] * ($highestX - $lowestX) * ($highestZ - $lowestZ) ); + $this->cachePlot($plot); + return $plot; } public function close() : void{ From 967f9ed3f9c8575217ddc7ca7c3fe6e5f01f047f Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Thu, 10 Mar 2022 04:39:24 -0500 Subject: [PATCH 43/47] Increase Default Cache --- resources/config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/config.yml b/resources/config.yml index 7623816e..b5651480 100644 --- a/resources/config.yml +++ b/resources/config.yml @@ -64,7 +64,7 @@ UseEconomy: false # Amount of plots to be cached. # Increasing this number will improve performance, but also increase memory usage. -PlotCacheSize: 256 +PlotCacheSize: 2048 # When a player enters a plot, a popup with basic info will be shown ShowPlotPopup: true From 34f04d5f6e7be2dfecaaaef65170537ce6fe6f65 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Wed, 6 Apr 2022 16:36:00 -0400 Subject: [PATCH 44/47] Refactor everything --- resources/config.yml | 14 +- resources/eng.ini | 4 +- resources/langtemplate.ini | 4 +- resources/mysql.sql | 22 +- resources/sqlite.sql | 14 +- src/MyPlot/Commands.php | 95 ++- src/MyPlot/EventListener.php | 301 +++++---- src/MyPlot/InternalAPI.php | 607 ++++++++++++++---- src/MyPlot/MyPlot.php | 153 +++-- src/MyPlot/MyPlotGenerator.php | 48 +- src/MyPlot/PlotLevelSettings.php | 54 +- src/MyPlot/events/MyPlotBlockEvent.php | 18 +- src/MyPlot/events/MyPlotBorderChangeEvent.php | 2 +- src/MyPlot/events/MyPlotClearEvent.php | 14 +- src/MyPlot/events/MyPlotCloneEvent.php | 18 +- src/MyPlot/events/MyPlotDenyEvent.php | 57 -- src/MyPlot/events/MyPlotDisposeEvent.php | 12 +- src/MyPlot/events/MyPlotFillEvent.php | 14 +- src/MyPlot/events/MyPlotGenerationEvent.php | 20 +- src/MyPlot/events/MyPlotMergeEvent.php | 39 +- .../events/MyPlotPlayerEnterPlotEvent.php | 14 +- .../events/MyPlotPlayerLeavePlotEvent.php | 12 +- src/MyPlot/events/MyPlotPlotEvent.php | 12 +- src/MyPlot/events/MyPlotPvpEvent.php | 12 +- src/MyPlot/events/MyPlotResetEvent.php | 17 +- src/MyPlot/events/MyPlotSaveEvent.php | 26 +- src/MyPlot/events/MyPlotSettingEvent.php | 19 +- src/MyPlot/events/MyPlotTeleportEvent.php | 10 +- src/MyPlot/forms/ComplexMyPlotForm.php | 28 - src/MyPlot/forms/MainForm.php | 112 ++-- src/MyPlot/forms/MyPlotForm.php | 8 +- src/MyPlot/forms/SimpleMyPlotForm.php | 28 - src/MyPlot/forms/subforms/AddHelperForm.php | 54 +- src/MyPlot/forms/subforms/BiomeForm.php | 41 +- src/MyPlot/forms/subforms/ClaimForm.php | 110 +--- src/MyPlot/forms/subforms/CloneForm.php | 115 +--- src/MyPlot/forms/subforms/DenyPlayerForm.php | 52 +- src/MyPlot/forms/subforms/FillForm.php | 35 +- src/MyPlot/forms/subforms/GenerateForm.php | 132 ++-- src/MyPlot/forms/subforms/GiveForm.php | 40 +- src/MyPlot/forms/subforms/HomeForm.php | 33 +- src/MyPlot/forms/subforms/InfoForm.php | 102 ++- src/MyPlot/forms/subforms/KickForm.php | 53 +- src/MyPlot/forms/subforms/NameForm.php | 39 +- src/MyPlot/forms/subforms/OwnerForm.php | 41 +- .../forms/subforms/RemoveHelperForm.php | 44 +- .../forms/subforms/UndenyPlayerForm.php | 44 +- src/MyPlot/forms/subforms/WarpForm.php | 70 +- src/MyPlot/plot/BasePlot.php | 16 +- src/MyPlot/plot/MergedPlot.php | 18 +- src/MyPlot/plot/SinglePlot.php | 26 +- src/MyPlot/provider/DataProvider.php | 83 ++- .../InternalBedrockEconomyProvider.php | 75 +++ .../provider/InternalCapitalProvider.php | 6 +- .../provider/InternalEconomySProvider.php | 14 +- src/MyPlot/subcommand/AddHelperSubCommand.php | 24 +- src/MyPlot/subcommand/AutoSubCommand.php | 14 +- src/MyPlot/subcommand/BiomeSubCommand.php | 27 +- src/MyPlot/subcommand/BuySubCommand.php | 27 +- src/MyPlot/subcommand/ClaimSubCommand.php | 65 +- src/MyPlot/subcommand/ClearSubCommand.php | 26 +- src/MyPlot/subcommand/CloneSubCommand.php | 31 +- .../subcommand/DenyPlayerSubCommand.php | 36 +- src/MyPlot/subcommand/DisposeSubCommand.php | 28 +- src/MyPlot/subcommand/FillSubCommand.php | 28 +- src/MyPlot/subcommand/GenerateSubCommand.php | 45 +- src/MyPlot/subcommand/GiveSubCommand.php | 29 +- src/MyPlot/subcommand/HelpSubCommand.php | 24 +- src/MyPlot/subcommand/HomeSubCommand.php | 27 +- src/MyPlot/subcommand/HomesSubCommand.php | 24 +- src/MyPlot/subcommand/InfoSubCommand.php | 26 +- src/MyPlot/subcommand/KickSubCommand.php | 29 +- src/MyPlot/subcommand/ListSubCommand.php | 50 +- src/MyPlot/subcommand/MergeSubCommand.php | 26 +- src/MyPlot/subcommand/MiddleSubCommand.php | 26 +- src/MyPlot/subcommand/NameSubCommand.php | 27 +- src/MyPlot/subcommand/PvpSubCommand.php | 12 +- .../subcommand/RemoveHelperSubCommand.php | 28 +- src/MyPlot/subcommand/ResetSubCommand.php | 28 +- src/MyPlot/subcommand/SellSubCommand.php | 26 +- src/MyPlot/subcommand/SetOwnerSubCommand.php | 26 +- src/MyPlot/subcommand/SubCommand.php | 19 +- src/MyPlot/subcommand/UnDenySubCommand.php | 28 +- src/MyPlot/subcommand/WarpSubCommand.php | 14 +- src/MyPlot/task/BorderCorrectionTask.php | 78 +-- src/MyPlot/task/ClearBorderTask.php | 133 ++-- src/MyPlot/task/ClearPlotTask.php | 121 ++-- src/MyPlot/task/CornerCorrectionTask.php | 92 ++- src/MyPlot/task/FillPlotTask.php | 117 ++-- src/MyPlot/task/RoadFillTask.php | 221 ++++--- src/MyPlot/utils/AsyncVariants.php | 2 +- src/MyPlot/utils/Utils.php | 24 + 92 files changed, 2523 insertions(+), 2136 deletions(-) delete mode 100644 src/MyPlot/events/MyPlotDenyEvent.php delete mode 100644 src/MyPlot/forms/ComplexMyPlotForm.php delete mode 100644 src/MyPlot/forms/SimpleMyPlotForm.php create mode 100644 src/MyPlot/provider/InternalBedrockEconomyProvider.php create mode 100644 src/MyPlot/utils/Utils.php diff --git a/resources/config.yml b/resources/config.yml index b5651480..db635f29 100644 --- a/resources/config.yml +++ b/resources/config.yml @@ -37,7 +37,7 @@ Custom Messages: false UI Forms: true # The data provider where plot data is stored. -database: +Database: # The database type. "sqlite" and "mysql" are supported. type: sqlite @@ -64,7 +64,7 @@ UseEconomy: false # Amount of plots to be cached. # Increasing this number will improve performance, but also increase memory usage. -PlotCacheSize: 2048 +PlotCacheSize: 2500 # When a player enters a plot, a popup with basic info will be shown ShowPlotPopup: true @@ -129,12 +129,12 @@ DefaultWorld: RoadWidth: 7 # The block that the road is made of (Default is Oak Planks) - RoadBlock: '5:0' + RoadBlock: oak planks # The block that plot walls are made of (Default is Stone Slabs) - WallBlock: '44:0' + WallBlock: stone slab # The block used as the plot floor (Default is Grass) - PlotFloorBlock: '2:0' + PlotFloorBlock: grass # The block that fills the rest of the plot (Default is Dirt) - PlotFillBlock: '3:0' + PlotFillBlock: dirt # The block at the bottom (Default is Bedrock) - BottomBlock: '7:0' + BottomBlock: bedrock diff --git a/resources/eng.ini b/resources/eng.ini index 491acc77..8ed76f6a 100644 --- a/resources/eng.ini +++ b/resources/eng.ini @@ -14,6 +14,7 @@ command.name=plot command.alias=p command.desc=Claim and manage your plots command.usage=/p [help] +command.usable=You cannot use this command right now command.unknown=Unknown command. Try /p help for a list of commands subcommand.usage=Usage: {%0} @@ -282,8 +283,7 @@ clone.wrongid="The plot id should be in the format X;Z" clone.nomoney=You do not have enough money to clone this plot clone.success=Plot {%0} has been successfully cloned to plot {%1} clone.form=Clone -clone.formlabel1=Origin Plot Location -clone.formlabel2=Clone Plot Location +clone.formcoordslabel=Clone Plot Location clone.formxcoord=Plot X Coordinate clone.formzcoord=Plot Z Coordinate clone.formworld=Plot World Name diff --git a/resources/langtemplate.ini b/resources/langtemplate.ini index 5312c264..2f78159b 100644 --- a/resources/langtemplate.ini +++ b/resources/langtemplate.ini @@ -14,6 +14,7 @@ command.name=plot command.alias=p command.desc= command.usage=/p [help] +command.usable= command.unknown= subcommand.usage= @@ -269,8 +270,7 @@ clone.wrongid= clone.nomoney= clone.success= clone.form= -clone.formlabel1= -clone.formlabel2= +clone.formcoordslabel= clone.formxcoord= clone.formzcoord= clone.formworld= diff --git a/resources/mysql.sql b/resources/mysql.sql index 1c826e32..215e52c9 100644 --- a/resources/mysql.sql +++ b/resources/mysql.sql @@ -29,6 +29,15 @@ CREATE TABLE IF NOT EXISTS mergedPlotsV2 ); -- # } -- # } +-- # {test +-- # {table +-- # :tableName string +SELECT COUNT(*) AS tables +FROM information_schema.tables +WHERE table_schema = DATABASE() + AND table_name = :tableName; +-- # } +-- # } -- # {add -- # {plot -- # :level string @@ -40,9 +49,8 @@ CREATE TABLE IF NOT EXISTS mergedPlotsV2 -- # :denied string -- # :biome string -- # :pvp bool false --- # :price int -INSERT -INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) +-- # :price float +INSERT INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) VALUES (:level, :X, :Z, :name, :owner, :helpers, :denied, :biome, :pvp, :price) ON DUPLICATE KEY UPDATE name = VALUES(:name), owner = VALUES(:owner), @@ -58,8 +66,7 @@ ON DUPLICATE KEY UPDATE name = VALUES(:name), -- # :originZ int -- # :mergedX int -- # :mergedZ int -INSERT IGNORE -INTO mergedPlotsV2 (`level`, `originX`, `originZ`, `mergedX`, `mergedZ`) +INSERT IGNORE INTO mergedPlotsV2 (`level`, `originX`, `originZ`, `mergedX`, `mergedZ`) VALUES (:level, :originX, :originZ, :mergedX, :mergedZ); -- # } -- # } @@ -123,7 +130,7 @@ FROM plotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedX = X AND mergedZ = Z -WHERE mergedPlotsV2.level = :level +WHERE mergedplotsV2.level = :level AND originX = :originX AND originZ = :originZ; -- # } @@ -184,9 +191,8 @@ WHERE level = :level -- # :level string -- # :x int -- # :z int --- # :biome string -- # :pvp bool false --- # :price int +-- # :price float UPDATE plotsV2 SET name = '', owner = '', diff --git a/resources/sqlite.sql b/resources/sqlite.sql index b1ae18c1..6ba8e32f 100644 --- a/resources/sqlite.sql +++ b/resources/sqlite.sql @@ -29,6 +29,15 @@ CREATE TABLE IF NOT EXISTS mergedPlotsV2 ); -- # } -- # } +-- # {test +-- # {table +-- # :tableName string +SELECT COUNT(name) AS tables +FROM sqlite_master +WHERE type = 'table' + AND name = :tableName; +-- # } +-- # } -- # {add -- # {plot -- # :level string @@ -40,7 +49,7 @@ CREATE TABLE IF NOT EXISTS mergedPlotsV2 -- # :denied string -- # :biome string -- # :pvp bool false --- # :price int +-- # :price float INSERT OR REPLACE INTO plotsV2 (level, X, Z, name, owner, helpers, denied, biome, pvp, price) @@ -179,9 +188,8 @@ WHERE level = :level -- # :level string -- # :X int -- # :Z int --- # :biome string -- # :pvp bool false --- # :price int +-- # :price float UPDATE plotsV2 SET name = '', owner = '', diff --git a/src/MyPlot/Commands.php b/src/MyPlot/Commands.php index 36cb5875..d408568e 100644 --- a/src/MyPlot/Commands.php +++ b/src/MyPlot/Commands.php @@ -51,9 +51,10 @@ class Commands extends Command implements PluginOwned{ /** @var MyPlotSubCommand[] $aliasSubCommands */ private array $aliasSubCommands = []; - public function __construct(private MyPlot $owningPlugin, private InternalAPI $internalAPI){ + public function __construct(MyPlot $owningPlugin, private InternalAPI $internalAPI){ parent::__construct($owningPlugin->getLanguage()->get("command.name"), $owningPlugin->getLanguage()->get("command.desc"), $owningPlugin->getLanguage()->get("command.usage"), [$owningPlugin->getLanguage()->get("command.alias")]); $this->setPermission("myplot.command"); + $this->owningPlugin = $owningPlugin; $this->loadSubCommand(new HelpSubCommand($owningPlugin, $internalAPI, "help", $this)); $this->loadSubCommand(new ClaimSubCommand($owningPlugin, $internalAPI, "claim")); $this->loadSubCommand(new GenerateSubCommand($owningPlugin, $internalAPI, "generate")); @@ -100,42 +101,68 @@ public function __construct(private MyPlot $owningPlugin, private InternalAPI $i $usage = $subCommand->getUsage(); $commandString = explode(" ", $usage)[0]; - preg_match_all('/(\s?[<\[]?\s*)([a-zA-Z0-9|]+)\s*:?\s*(string|int|x y z|float|mixed|target|message|text|json|command|boolean|bool)?\s*[>\]]?\s?/iu', $usage, $matches, PREG_PATTERN_ORDER, strlen($commandString)); - $argumentCount = count($matches[0])-1; - for($argNumber = 1; $argNumber <= $argumentCount; ++$argNumber) { - $optional = $matches[1][$argNumber] === '['; + preg_match_all('/\h*([<\[])?\h*([\w|]+)\h*:?\h*([\w\h]+)?\h*[>\]]?\h*/iu', $usage, $matches, PREG_PATTERN_ORDER, strlen($commandString)); // https://regex101.com/r/1REoJG/22 + $argumentCount = count($matches[0]) - 1; + for($argNumber = 1; $argNumber <= $argumentCount; ++$argNumber){ + if(!isset($matches[1][$argNumber])){ + $paramName = strtolower($matches[2][$argNumber]); + $paramName = $paramName === 'bool' ? 'Boolean' : $paramName; + + $softEnums = $autofill->getSoftEnums(); + if(isset($softEnums[$paramName])){ + $enum = $softEnums[$paramName]; + }else{ + $autofill->addSoftEnum($enum = new CommandEnum($paramName, [$paramName]), false); + } + $overloads[$tree][$argNumber] = CommandParameter::enum($paramName, $enum, CommandParameter::FLAG_FORCE_COLLAPSE_ENUM, false); // collapse and assume required because no optional identifier exists in usage message + continue; + } + $optional = str_contains($matches[1][$argNumber], '['); $paramName = strtolower($matches[2][$argNumber]); - if(stripos($paramName, "|") === false) { - $paramType = match (strtolower($matches[3][$argNumber])) { - default => AvailableCommandsPacket::ARG_TYPE_STRING, - "int" => AvailableCommandsPacket::ARG_TYPE_INT, - "x y z" => AvailableCommandsPacket::ARG_TYPE_POSITION, - "float" => AvailableCommandsPacket::ARG_TYPE_FLOAT, - "target" => AvailableCommandsPacket::ARG_TYPE_TARGET, - "message" => AvailableCommandsPacket::ARG_TYPE_MESSAGE, - "json" => AvailableCommandsPacket::ARG_TYPE_JSON, - "command" => AvailableCommandsPacket::ARG_TYPE_COMMAND, - "boolean", "bool", "mixed" => AvailableCommandsPacket::ARG_TYPE_VALUE, - "text" => AvailableCommandsPacket::ARG_TYPE_RAWTEXT, - }; - $parameter = CommandParameter::standard($paramName, $paramType, 0, $optional); - }else{ + $paramType = strtolower($matches[3][$argNumber] ?? ''); + if(in_array($paramType, array_keys(array_merge($autofill->getSoftEnums(), $autofill->getHardcodedEnums())), true)){ + $paramType = $paramType === 'bool' ? 'Boolean' : $paramType; + $enum = $autofill->getSoftEnums()[$paramType] ?? $autofill->getHardcodedEnums()[$paramType]; + $overloads[$tree][$argNumber] = CommandParameter::enum($paramName, $enum, 0, $optional); + }elseif(str_contains($paramName, "|")){ + ++$enumCount; $enumValues = explode("|", $paramName); - $parameter = CommandParameter::enum($paramName, new CommandEnum($this->getName()." Enum#".$enumCount, $enumValues), CommandParameter::FLAG_FORCE_COLLAPSE_ENUM, $optional); + $autofill->addSoftEnum($enum = new CommandEnum($subCommandName . " Enum#" . $enumCount, $enumValues), false); + $overloads[$tree][$argNumber] = CommandParameter::enum($paramName, $enum, CommandParameter::FLAG_FORCE_COLLAPSE_ENUM, $optional); + }elseif(str_contains($paramName, "/")){ + ++$enumCount; + $enumValues = explode("/", $paramName); + $autofill->addSoftEnum($enum = new CommandEnum($subCommandName . " Enum#" . $enumCount, $enumValues), false); + $overloads[$tree][$argNumber] = CommandParameter::enum($paramName, $enum, CommandParameter::FLAG_FORCE_COLLAPSE_ENUM, $optional); + }else{ + $paramType = match ($paramType) { // ordered by constant value + 'int' => AvailableCommandsPacket::ARG_TYPE_INT, + 'float' => AvailableCommandsPacket::ARG_TYPE_FLOAT, + 'mixed' => AvailableCommandsPacket::ARG_TYPE_VALUE, + 'player', 'target' => AvailableCommandsPacket::ARG_TYPE_TARGET, + 'string' => AvailableCommandsPacket::ARG_TYPE_STRING, + 'x y z' => AvailableCommandsPacket::ARG_TYPE_POSITION, + 'message' => AvailableCommandsPacket::ARG_TYPE_MESSAGE, + default => AvailableCommandsPacket::ARG_TYPE_RAWTEXT, + 'json' => AvailableCommandsPacket::ARG_TYPE_JSON, + 'command' => AvailableCommandsPacket::ARG_TYPE_COMMAND, + }; + $overloads[$tree][$argNumber] = CommandParameter::standard($paramName, $paramType, 0, $optional); } - $overloads[$tree][$argNumber] = $parameter; } $tree++; } - $autofill->addManualOverride($this->getName(), new CommandData($this->getName(), $this->getDescription(), 0, 1, new CommandEnum(ucfirst($this->getName()) . "Aliases", array_merge([$this->getName()], $this->getAliases())), $overloads)); - $plugin->getLogger()->debug("Command Autofill Enabled"); + $data = $autofill->generateGenericCommandData($this->getName(), $this->getAliases(), $this->getDescription(), $this->getUsage()); + $data->overloads = $overloads; + $autofill->addManualOverride('myplot:' . $this->getName(), $data); + $owningPlugin->getLogger()->debug("Command Autofill Enabled"); } } /** * @return MyPlotSubCommand[] */ - public function getCommands() : array { + public function getCommands() : array{ return $this->subCommands; } @@ -162,25 +189,25 @@ public function execute(CommandSender $sender, string $commandLabel, array $args if(!isset($args[0])){ $args[0] = "help"; if($sender instanceof Player and $this->owningPlugin->getConfig()->get("UI Forms", true) === true and class_exists('cosmicpe\\form\\PaginatedForm')){ - $sender->sendForm(new MainForm(1, $sender, $this->internalAPI)); + $sender->sendForm(new MainForm(1, $sender, $this->owningPlugin, $this->internalAPI)); return true; } } $subCommand = strtolower((string) array_shift($args)); - if(isset($this->subCommands[$subCommand])) { + if(isset($this->subCommands[$subCommand])){ $command = $this->subCommands[$subCommand]; - }elseif(isset($this->aliasSubCommands[$subCommand])) { + }elseif(isset($this->aliasSubCommands[$subCommand])){ $command = $this->aliasSubCommands[$subCommand]; }else{ $sender->sendMessage(TextFormat::RED . $this->owningPlugin->getLanguage()->get("command.unknown")); return true; } - if($command->canUse($sender)) { - if(!$command->execute($sender, $args)) { - $sender->sendMessage($this->owningPlugin->getLanguage()->translateString("subcommand.usage", [$command->getUsage()])); - } - }else{ - $sender->sendMessage(TextFormat::RED . $this->owningPlugin->getLanguage()->get("command.unknown")); + if(!$command->canUse($sender)){ + $sender->sendMessage(TextFormat::RED . $this->owningPlugin->getLanguage()->get("command.usable")); + return true; + } + if(!$command->execute($sender, $args)){ + $sender->sendMessage($this->owningPlugin->getLanguage()->translateString("subcommand.usage", [$command->getUsage()])); } return true; } diff --git a/src/MyPlot/EventListener.php b/src/MyPlot/EventListener.php index f4d8ad1e..9602ff74 100644 --- a/src/MyPlot/EventListener.php +++ b/src/MyPlot/EventListener.php @@ -7,6 +7,8 @@ use MyPlot\events\MyPlotPlayerEnterPlotEvent; use MyPlot\events\MyPlotPlayerLeavePlotEvent; use MyPlot\events\MyPlotPvpEvent; +use MyPlot\plot\BasePlot; +use MyPlot\plot\SinglePlot; use pocketmine\block\Liquid; use pocketmine\block\Sapling; use pocketmine\block\utils\TreeType; @@ -30,34 +32,33 @@ use pocketmine\world\World; final class EventListener implements Listener{ - public function __construct(private MyPlot $plugin, private InternalAPI $api){ } + public function __construct(private MyPlot $plugin, private InternalAPI $internalAPI){ } /** - * @ignoreCancelled false * @priority LOWEST * * @param WorldLoadEvent $event */ public function onLevelLoad(WorldLoadEvent $event) : void{ - if(file_exists($this->plugin->getDataFolder()."worlds".DIRECTORY_SEPARATOR.$event->getWorld()->getFolderName().".yml")) { + if(file_exists($this->plugin->getDataFolder() . "worlds" . DIRECTORY_SEPARATOR . $event->getWorld()->getFolderName() . ".yml")){ $this->plugin->getLogger()->debug("MyPlot level " . $event->getWorld()->getFolderName() . " loaded!"); $settings = $event->getWorld()->getProvider()->getWorldData()->getGeneratorOptions(); $settings = json_decode($settings, true); - if($settings === false) { + if($settings === false){ return; } $levelName = $event->getWorld()->getFolderName(); - $default = array_filter((array) $this->plugin->getConfig()->get("DefaultWorld", []), function($key) : bool { + $default = array_filter((array) $this->plugin->getConfig()->get("DefaultWorld", []), function($key) : bool{ return !in_array($key, ["PlotSize", "GroundHeight", "RoadWidth", "RoadBlock", "WallBlock", "PlotFloorBlock", "PlotFillBlock", "BottomBlock"], true); }, ARRAY_FILTER_USE_KEY); - $config = new Config($this->plugin->getDataFolder()."worlds".DIRECTORY_SEPARATOR.$levelName.".yml", Config::YAML, $default); - foreach(array_keys($default) as $key) { - $settings[$key] = $config->get((string)$key); + $config = new Config($this->plugin->getDataFolder() . "worlds" . DIRECTORY_SEPARATOR . $levelName . ".yml", Config::YAML, $default); + foreach(array_keys($default) as $key){ + $settings[$key] = $config->get((string) $key); } - $this->api->addLevelSettings($levelName, new PlotLevelSettings($levelName, $settings)); + $this->internalAPI->addLevelSettings($levelName, new PlotLevelSettings($levelName, $settings)); - if($this->plugin->getConfig()->get('AllowFireTicking', false) === false) { - $ref = new \ReflectionClass($event->getWorld()); + if($this->plugin->getConfig()->get('AllowFireTicking', false) === false){ + $ref = new \ReflectionClass(World::class); $prop = $ref->getProperty('randomTickBlocks'); $prop->setAccessible(true); $randomTickBlocks = $prop->getValue($event->getWorld()); @@ -68,76 +69,83 @@ public function onLevelLoad(WorldLoadEvent $event) : void{ } /** - * @ignoreCancelled false * @priority MONITOR * * @param WorldUnloadEvent $event */ - public function onLevelUnload(WorldUnloadEvent $event) : void { - if($event->isCancelled()) { - return; - } + public function onLevelUnload(WorldUnloadEvent $event) : void{ $levelName = $event->getWorld()->getFolderName(); - if($this->api->unloadLevelSettings($levelName)) { + if($this->internalAPI->unloadLevelSettings($levelName)){ $this->plugin->getLogger()->debug("Level " . $event->getWorld()->getFolderName() . " unloaded!"); } } /** - * @ignoreCancelled false + * @handleCancelled true * @priority LOWEST * * @param BlockPlaceEvent $event */ - public function onBlockPlace(BlockPlaceEvent $event) : void { + public function onBlockPlace(BlockPlaceEvent $event) : void{ $this->onEventOnBlock($event); } /** - * @ignoreCancelled false + * @handleCancelled true * @priority LOWEST * * @param BlockBreakEvent $event */ - public function onBlockBreak(BlockBreakEvent $event) : void { + public function onBlockBreak(BlockBreakEvent $event) : void{ $this->onEventOnBlock($event); } /** - * @ignoreCancelled false + * @handleCancelled true * @priority LOWEST * * @param PlayerInteractEvent $event */ - public function onPlayerInteract(PlayerInteractEvent $event) : void { + public function onPlayerInteract(PlayerInteractEvent $event) : void{ $this->onEventOnBlock($event); } /** - * @ignoreCancelled false + * @handleCancelled true * @priority LOWEST * * @param SignChangeEvent $event */ - public function onSignChange(SignChangeEvent $event) : void { + public function onSignChange(SignChangeEvent $event) : void{ $this->onEventOnBlock($event); } - private function onEventOnBlock(BlockPlaceEvent|SignChangeEvent|PlayerInteractEvent|BlockBreakEvent $event) : void { + private function onEventOnBlock(BlockPlaceEvent|SignChangeEvent|PlayerInteractEvent|BlockBreakEvent $event) : void{ $levelName = $event->getBlock()->getPosition()->getWorld()->getFolderName(); - if($this->api->getLevelSettings($levelName) === null) { + $plotLevel = $this->internalAPI->getLevelSettings($levelName); + if($plotLevel === null) return; - } - $plot = $this->plugin->getPlotByPosition($event->getBlock()->getPosition()); - if($plot !== null) { + + $pos = $event->getBlock()->getPosition(); + $x = $pos->x; + $z = $pos->z; + $plot = $this->internalAPI->getPlotFast($x, $z, $plotLevel); + + if($plot !== null){ $ev = new MyPlotBlockEvent($plot, $event->getBlock(), $event->getPlayer(), $event); - if($event->isCancelled()) { + if($event->isCancelled()) $ev->cancel(); - } + $ev->call(); $ev->isCancelled() ? $event->cancel() : $event->uncancel(); + $plot = $this->internalAPI->getPlotFromCache($plot, true); + if(!$plot instanceof SinglePlot){ + $event->cancel(); + $this->plugin->getLogger()->debug("Cancelled block change event at $x,$pos->y,$z in [$levelName]"); + return; + } $username = $event->getPlayer()->getName(); - if($plot->owner == $username or $plot->isHelper($username) or $plot->isHelper("*") or $event->getPlayer()->hasPermission("myplot.admin.build.plot")) { + if($plot->owner == $username or $plot->isHelper($username) or $plot->isHelper("*") or $event->getPlayer()->hasPermission("myplot.admin.build.plot")){ if(!($event instanceof PlayerInteractEvent and $event->getBlock() instanceof Sapling)) return; /* @@ -146,28 +154,35 @@ private function onEventOnBlock(BlockPlaceEvent|SignChangeEvent|PlayerInteractEv */ $block = $event->getBlock(); $maxLengthLeaves = $block->getIdInfo()->getVariant() === TreeType::SPRUCE()->getMagicNumber() ? 3 : 2; - $beginPos = $this->plugin->getPlotPosition($plot); + $beginPos = $this->internalAPI->getPlotPosition($plot); $endPos = clone $beginPos; $beginPos->x += $maxLengthLeaves; $beginPos->z += $maxLengthLeaves; - $plotSize = $this->api->getLevelSettings($levelName)->plotSize; + $plotSize = $plotLevel->plotSize; $endPos->x += $plotSize - $maxLengthLeaves; $endPos->z += $plotSize - $maxLengthLeaves; - if($block->getPosition()->x >= $beginPos->x and $block->getPosition()->z >= $beginPos->z and $block->getPosition()->x < $endPos->x and $block->getPosition()->z < $endPos->z) { + if($block->getPosition()->x >= $beginPos->x and $block->getPosition()->z >= $beginPos->z and $block->getPosition()->x < $endPos->x and $block->getPosition()->z < $endPos->z) return; - } } }elseif($event->getPlayer()->hasPermission("myplot.admin.build.road")) return; - elseif($this->plugin->isPositionBorderingPlot($event->getBlock()->getPosition()) and $this->api->getLevelSettings($levelName)->editBorderBlocks) { - $plot = $this->plugin->getPlotBorderingPosition($event->getBlock()->getPosition()); - if($plot instanceof Plot) { + elseif($plotLevel->editBorderBlocks){ + $plot = $this->internalAPI->getPlotBorderingPosition($event->getBlock()->getPosition()); + if($plot !== null){ + $plot = $this->internalAPI->getPlotFromCache($plot, true); + if(!$plot instanceof SinglePlot){ + $event->cancel(); + $this->plugin->getLogger()->debug("Cancelled block change event at $x,$pos->y,$z in [$levelName]"); + return; + } + $ev = new MyPlotBorderChangeEvent($plot, $event->getBlock(), $event->getPlayer(), $event); - if($event->isCancelled()) { + if($event->isCancelled()) $ev->cancel(); - } + $ev->call(); $ev->isCancelled() ? $event->cancel() : $event->uncancel(); + $username = $event->getPlayer()->getName(); if($plot->owner == $username or $plot->isHelper($username) or $plot->isHelper("*") or $event->getPlayer()->hasPermission("myplot.admin.build.plot")) if(!($event instanceof PlayerInteractEvent and $event->getBlock() instanceof Sapling)) @@ -175,35 +190,36 @@ private function onEventOnBlock(BlockPlaceEvent|SignChangeEvent|PlayerInteractEv } } $event->cancel(); - $this->plugin->getLogger()->debug("Block placement/break/interaction of {$event->getBlock()->getName()} was cancelled at ".$event->getBlock()->getPosition()->__toString()); + $this->plugin->getLogger()->debug("Block placement/break/interaction of {$event->getBlock()->getName()} was cancelled at " . $event->getBlock()->getPosition()->__toString()); } /** - * @ignoreCancelled false * @priority LOWEST * * @param EntityExplodeEvent $event */ - public function onExplosion(EntityExplodeEvent $event) : void { - if($event->isCancelled()) { - return; - } + public function onExplosion(EntityExplodeEvent $event) : void{ $levelName = $event->getEntity()->getWorld()->getFolderName(); - if($this->api->getLevelSettings($levelName) === null) + $plotLevel = $this->internalAPI->getLevelSettings($levelName); + if($plotLevel === null) return; - $plot = $this->plugin->getPlotByPosition($event->getPosition()); - if($plot === null) { + + $pos = $event->getPosition(); + $x = $pos->x; + $z = $pos->z; + + $plot = $this->internalAPI->getPlotFast($x, $z, $plotLevel); + if($plot === null){ $event->cancel(); return; } - $beginPos = $this->plugin->getPlotPosition($plot); + $beginPos = $this->internalAPI->getPlotPosition($plot); $endPos = clone $beginPos; - $levelSettings = $this->api->getLevelSettings($levelName); - $plotSize = $levelSettings->plotSize; + $plotSize = $plotLevel->plotSize; $endPos->x += $plotSize; $endPos->z += $plotSize; - $blocks = array_filter($event->getBlockList(), function($block) use ($beginPos, $endPos) : bool { - if($block->getPosition()->x >= $beginPos->x and $block->getPosition()->z >= $beginPos->z and $block->getPosition()->x < $endPos->x and $block->getPosition()->z < $endPos->z) { + $blocks = array_filter($event->getBlockList(), function($block) use ($beginPos, $endPos) : bool{ + if($block->getPosition()->x >= $beginPos->x and $block->getPosition()->z >= $beginPos->z and $block->getPosition()->x < $endPos->x and $block->getPosition()->z < $endPos->z){ return true; } return false; @@ -212,174 +228,197 @@ public function onExplosion(EntityExplodeEvent $event) : void { } /** - * @ignoreCancelled false * @priority LOWEST * * @param EntityMotionEvent $event */ - public function onEntityMotion(EntityMotionEvent $event) : void { - if($event->isCancelled()) { - return; - } + public function onEntityMotion(EntityMotionEvent $event) : void{ $level = $event->getEntity()->getWorld(); if(!$level instanceof World) return; $levelName = $level->getFolderName(); - if($this->api->getLevelSettings($levelName) === null) + if($this->internalAPI->getLevelSettings($levelName) === null) return; - $settings = $this->api->getLevelSettings($levelName); - if($settings->restrictEntityMovement and !($event->getEntity() instanceof Player)) { + $settings = $this->internalAPI->getLevelSettings($levelName); + if($settings->restrictEntityMovement and !($event->getEntity() instanceof Player)){ $event->cancel(); $this->plugin->getLogger()->debug("Cancelled entity motion on " . $levelName); } } /** - * @ignoreCancelled false * @priority LOWEST * * @param BlockSpreadEvent $event */ - public function onBlockSpread(BlockSpreadEvent $event) : void { - if($event->isCancelled()) { - return; - } + public function onBlockSpread(BlockSpreadEvent $event) : void{ $levelName = $event->getBlock()->getPosition()->getWorld()->getFolderName(); - if($this->api->getLevelSettings($levelName) === null) + $plotLevel = $this->internalAPI->getLevelSettings($levelName); + if($plotLevel === null) return; - $settings = $this->api->getLevelSettings($levelName); - $newBlockInPlot = ($plotA = $this->plugin->getPlotByPosition($event->getBlock()->getPosition())) instanceof Plot; - $sourceBlockInPlot = ($plotB = $this->plugin->getPlotByPosition($event->getSource()->getPosition())) instanceof Plot; + $pos = $event->getBlock()->getPosition(); + $x = $pos->x; + $z = $pos->z; + $newBlockInPlot = ($plotA = $this->internalAPI->getPlotFast($x, $z, $plotLevel)) !== null; - $spreadIsSamePlot = (($newBlockInPlot and $sourceBlockInPlot)) && $plotA->isSame($plotB); + $pos = $event->getSource()->getPosition(); + $x = $pos->x; + $z = $pos->z; + $sourceBlockInPlot = ($plotB = $this->internalAPI->getPlotFast($x, $z, $plotLevel)) !== null; - if($event->getSource() instanceof Liquid) { - if(!$settings->updatePlotLiquids and ($sourceBlockInPlot or $this->plugin->isPositionBorderingPlot($event->getSource()->getPosition()))) { - $event->cancel(); - $this->plugin->getLogger()->debug("Cancelled {$event->getSource()->getName()} spread on [$levelName]"); - }elseif($settings->updatePlotLiquids and ($sourceBlockInPlot or $this->plugin->isPositionBorderingPlot($event->getSource()->getPosition())) and (!$newBlockInPlot or !$this->plugin->isPositionBorderingPlot($event->getBlock()->getPosition()) or !$spreadIsSamePlot)) { - $event->cancel(); - $this->plugin->getLogger()->debug("Cancelled {$event->getSource()->getName()} spread on [$levelName]"); - } - }elseif(!$settings->allowOutsidePlotSpread and (!$newBlockInPlot or !$spreadIsSamePlot)) { + $spreadIsSamePlot = (($newBlockInPlot and $sourceBlockInPlot)) and $plotA->isSame($plotB); + + if($event->getSource() instanceof Liquid and (!$plotLevel->updatePlotLiquids or !$spreadIsSamePlot)){ + $event->cancel(); + $this->plugin->getLogger()->debug("Cancelled {$event->getSource()->getName()} spread on [$levelName]"); + }elseif(!$plotLevel->allowOutsidePlotSpread and (!$newBlockInPlot or !$spreadIsSamePlot)){ $event->cancel(); //$this->plugin->getLogger()->debug("Cancelled block spread of {$event->getSource()->getName()} on ".$levelName); } } /** - * @ignoreCancelled false + * @handleCancelled true * @priority LOWEST * * @param PlayerMoveEvent $event */ - public function onPlayerMove(PlayerMoveEvent $event) : void { + public function onPlayerMove(PlayerMoveEvent $event) : void{ $this->onEventOnMove($event->getPlayer(), $event); } /** - * @ignoreCancelled false + * @handleCancelled true * @priority LOWEST * * @param EntityTeleportEvent $event */ - public function onPlayerTeleport(EntityTeleportEvent $event) : void { + public function onPlayerTeleport(EntityTeleportEvent $event) : void{ $entity = $event->getEntity(); - if ($entity instanceof Player) { + if($entity instanceof Player){ $this->onEventOnMove($entity, $event); } } - private function onEventOnMove(Player $player, EntityTeleportEvent|PlayerMoveEvent $event) : void { + private function onEventOnMove(Player $player, EntityTeleportEvent|PlayerMoveEvent $event) : void{ $levelName = $player->getWorld()->getFolderName(); - if ($this->api->getLevelSettings($levelName) === null) + $plotLevel = $this->internalAPI->getLevelSettings($levelName); + if($plotLevel === null) return; - $plot = $this->plugin->getPlotByPosition($event->getTo()); - $plotFrom = $this->plugin->getPlotByPosition($event->getFrom()); - if($plot !== null and ($plotFrom === null or !$plot->isSame($plotFrom))) { - if(str_contains((string) $plot, "-0")) { + + $pos = $event->getTo(); + $x = $pos->x; + $z = $pos->z; + $plot = $this->internalAPI->getPlotFast($x, $z, $plotLevel); + + $pos = $event->getFrom(); + $x = $pos->x; + $z = $pos->z; + $plotFrom = $this->internalAPI->getPlotFast($x, $z, $plotLevel); + + if($plotFrom !== null and ($plot === null or !$plot->isSame($plotFrom))){ + if(str_contains((string) $plotFrom, "-0")) return; - } + + $ev = new MyPlotPlayerLeavePlotEvent($plotFrom, $player); + $event->isCancelled() ? $ev->cancel() : $ev->uncancel(); + $ev->call(); + $ev->isCancelled() ? $event->cancel() : $event->uncancel(); + } + + if($plot !== null) + $plot = $this->internalAPI->getPlotFromCache($plot, true); + + if($plot instanceof BasePlot and ($plotFrom === null or !$plot->isSame($plotFrom))){ + if(str_contains((string) $plot, "-0")) + return; + $plot = SinglePlot::fromBase($plot); + $ev = new MyPlotPlayerEnterPlotEvent($plot, $player); $event->isCancelled() ? $ev->cancel() : $ev->uncancel(); + $username = $ev->getPlayer()->getName(); - if($plot->owner !== $username and ($plot->isDenied($username) or $plot->isDenied("*")) and !$ev->getPlayer()->hasPermission("myplot.admin.denyplayer.bypass")) { + if($plot->owner !== $username and + ($plot->isDenied($username) or $plot->isDenied("*")) and + !$ev->getPlayer()->hasPermission("myplot.admin.denyplayer.bypass") + ) $ev->cancel(); - } + $ev->call(); $ev->isCancelled() ? $event->cancel() : $event->uncancel(); - if($event->isCancelled()) { + if($event->isCancelled()){ + $this->internalAPI->teleportPlayerToPlot($player, $plot); return; } - if(!(bool) $this->plugin->getConfig()->get("ShowPlotPopup", true)) + + if($this->plugin->getConfig()->get("ShowPlotPopup", true) === false) return; + $popup = $this->plugin->getLanguage()->translateString("popup", [TextFormat::GREEN . $plot]); $price = TextFormat::GREEN . $plot->price; - if($plot->owner !== "") { + if($plot->owner !== ""){ $owner = TextFormat::GREEN . $plot->owner; - if($plot->price > 0 and $plot->owner !== $player->getName()) { - $ownerPopup = $this->plugin->getLanguage()->translateString("popup.forsale", [$owner.TextFormat::WHITE, $price.TextFormat::WHITE]); + if($plot->price > 0 and $plot->owner !== $player->getName()){ + $ownerPopup = $this->plugin->getLanguage()->translateString("popup.forsale", [$owner . TextFormat::WHITE, $price . TextFormat::WHITE]); }else{ - $ownerPopup = $this->plugin->getLanguage()->translateString("popup.owner", [$owner.TextFormat::WHITE]); + $ownerPopup = $this->plugin->getLanguage()->translateString("popup.owner", [$owner . TextFormat::WHITE]); } }else{ - $ownerPopup = $this->plugin->getLanguage()->translateString("popup.available", [$price.TextFormat::WHITE]); + $ownerPopup = $this->plugin->getLanguage()->translateString("popup.available", [$price . TextFormat::WHITE]); } $paddingSize = (int) floor((strlen($popup) - strlen($ownerPopup)) / 2); $paddingPopup = str_repeat(" ", max(0, -$paddingSize)); $paddingOwnerPopup = str_repeat(" ", max(0, $paddingSize)); $popup = TextFormat::WHITE . $paddingPopup . $popup . "\n" . TextFormat::WHITE . $paddingOwnerPopup . $ownerPopup; $ev->getPlayer()->sendTip($popup); - }elseif($plotFrom !== null and ($plot === null or !$plot->isSame($plotFrom))) { - if(str_contains((string) $plotFrom, "-0")) { - return; - } - $ev = new MyPlotPlayerLeavePlotEvent($plotFrom, $player); - $event->isCancelled() ? $ev->cancel() : $ev->uncancel(); - $ev->call(); - $ev->isCancelled() ? $event->cancel() : $event->uncancel(); - }elseif($plotFrom !== null and $plot !== null and ($plot->isDenied($player->getName()) or $plot->isDenied("*")) and $plot->owner !== $player->getName() and !$player->hasPermission("myplot.admin.denyplayer.bypass")) { - $this->plugin->teleportPlayerToPlot($player, $plot); } } /** - * @ignoreCancelled false * @priority LOWEST * * @param EntityDamageByEntityEvent $event */ - public function onEntityDamage(EntityDamageByEntityEvent $event) : void { + public function onEntityDamage(EntityDamageByEntityEvent $event) : void{ $damaged = $event->getEntity(); $damager = $event->getDamager(); - if($damaged instanceof Player and $damager instanceof Player and !$event->isCancelled()) { + if($damaged instanceof Player and $damager instanceof Player){ $levelName = $damaged->getWorld()->getFolderName(); - if($this->api->getLevelSettings($levelName) === null) { + $plotLevel = $this->internalAPI->getLevelSettings($levelName); + if($plotLevel === null) return; - } - $settings = $this->api->getLevelSettings($levelName); - $plot = $this->plugin->getPlotByPosition($damaged->getPosition()); - if($plot !== null) { + + $pos = $damaged->getPosition(); + $x = $pos->x; + $z = $pos->z; + $plot = $this->internalAPI->getPlotFast($x, $z, $plotLevel); + if($plot !== null){ + $plot = $this->internalAPI->getPlotFromCache($plot); + if(!$plot instanceof SinglePlot){ + if($plotLevel->restrictPVP and !$damager->hasPermission("myplot.admin.pvp.bypass")) + $event->cancel(); + $this->plugin->getLogger()->debug("Cancelled player damage on [$levelName] due to plot not cached"); + return; + } + $ev = new MyPlotPvpEvent($plot, $damager, $damaged, $event); - if(!$plot->pvp and !$damager->hasPermission("myplot.admin.pvp.bypass")) { + if(!$plot->pvp and !$damager->hasPermission("myplot.admin.pvp.bypass")){ $ev->cancel(); - $this->plugin->getLogger()->debug("Cancelled pvp event in plot ".$plot->X.";".$plot->Z." on level '" . $levelName . "'"); + $this->plugin->getLogger()->debug("Cancelled pvp event in plot " . $plot->X . ";" . $plot->Z . " on level '" . $levelName . "'"); } $ev->call(); $ev->isCancelled() ? $event->cancel() : $event->uncancel(); - if($event->isCancelled()) { + if($event->isCancelled()){ $ev->getAttacker()->sendMessage(TextFormat::RED . $this->plugin->getLanguage()->translateString("pvp.disabled")); // generic message- we dont know if by config or plot } return; } - if($damager->hasPermission("myplot.admin.pvp.bypass")) { - return; - } - if($settings->restrictPVP) { + + if($plotLevel->restrictPVP and !$damager->hasPermission("myplot.admin.pvp.bypass")){ $event->cancel(); - $damager->sendMessage(TextFormat::RED.$this->plugin->getLanguage()->translateString("pvp.world")); - $this->plugin->getLogger()->debug("Cancelled pvp event on ".$levelName); + $damager->sendMessage(TextFormat::RED . $this->plugin->getLanguage()->translateString("pvp.world")); + $this->plugin->getLogger()->debug("Cancelled pvp event on " . $levelName); } } } diff --git a/src/MyPlot/InternalAPI.php b/src/MyPlot/InternalAPI.php index 98e55eb0..ef5cdf75 100644 --- a/src/MyPlot/InternalAPI.php +++ b/src/MyPlot/InternalAPI.php @@ -21,7 +21,6 @@ use MyPlot\plot\SinglePlot; use MyPlot\provider\DataProvider; use MyPlot\provider\InternalEconomyProvider; -use MyPlot\task\ClearBorderTask; use MyPlot\task\ClearPlotTask; use MyPlot\task\FillPlotTask; use MyPlot\task\RoadFillTask; @@ -44,10 +43,11 @@ final class InternalAPI{ /** @var PlotLevelSettings[] $levels */ private array $levels = []; private DataProvider $dataProvider; + private array $populatingCache = []; public function __construct(private MyPlot $plugin, private ?InternalEconomyProvider $economyProvider){ $plugin->getLogger()->debug(TF::BOLD . "Loading Data Provider settings"); - $this->dataProvider = new DataProvider($plugin); + $this->dataProvider = new DataProvider($plugin, $this); } public function getEconomyProvider() : ?InternalEconomyProvider{ @@ -99,19 +99,19 @@ public function generatePlotsToSave(SinglePlot $plot) : \Generator{ $plot = $ev->getPlot(); if($plot instanceof MergedPlot){ $failed = false; - for($x = $plot->X; $x <= $plot->xWidth + $plot->X; ++$x){ - for($z = $plot->Z; $z <= $plot->zWidth + $plot->Z; ++$z){ + for($x = $plot->X; $x < $plot->xWidth + $plot->X; ++$x){ + for($z = $plot->Z; $z < $plot->zWidth + $plot->Z; ++$z){ $newPlot = clone $plot; $newPlot->X = $x; $newPlot->Z = $z; - if(yield $this->dataProvider->savePlot($newPlot)){ + if(yield from $this->dataProvider->savePlot($newPlot)){ $failed = true; } } } return $failed; } - return yield $this->dataProvider->savePlot($plot); + return yield from $this->dataProvider->savePlot($plot); } /** @@ -137,7 +137,7 @@ public function getPlotsOfPlayer(string $username, ?string $levelName, ?callable * @return \Generator> */ public function generatePlotsOfPlayer(string $username, ?string $levelName) : \Generator{ - return yield $this->dataProvider->getPlotsByOwner($username, $levelName); + return yield from $this->dataProvider->getPlotsByOwner($username, $levelName ?? ''); } /** @@ -157,7 +157,31 @@ public function getNextFreePlot(string $levelName, int $limitXZ, ?callable $onCo } public function generateNextFreePlot(string $levelName, int $limitXZ) : \Generator{ - return yield $this->dataProvider->getNextFreePlot($levelName, $limitXZ); + return yield from $this->dataProvider->getNextFreePlot($levelName, $limitXZ); + } + + /** + * @param BasePlot $plot + * @param callable|null $onComplete + * @phpstan-param (callable(SinglePlot|null): void)|null $onComplete + * @param callable|null $onFail + * @phpstan-param (callable(\Throwable): void)|null $catches + */ + public function getPlot(BasePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ + Await::g2c( + $this->generatePlot($plot), + $onComplete, + $onFail === null ? [] : [$onFail] + ); + } + + /** + * @param BasePlot $plot + * + * @return \Generator + */ + public function generatePlot(BasePlot $plot) : \Generator{ + return yield from $this->dataProvider->getMergedPlot($plot); } public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?BasePlot{ @@ -184,28 +208,23 @@ public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) return new BasePlot($plotLevel->name, $x, $z); } - /** - * @param BasePlot $plot - * @param callable|null $onComplete - * @phpstan-param (callable(SinglePlot|null): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function getPlot(BasePlot $plot, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generatePlot($plot), - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - /** - * @param BasePlot $plot - * - * @return \Generator - */ - public function generatePlot(BasePlot $plot) : \Generator{ - return yield $this->dataProvider->getMergedPlot($plot); + public function getPlotFromCache(BasePlot $plot, bool $orderCachePopulation = true) : BasePlot{ + $cachedPlot = $this->dataProvider->getPlotFromCache($plot->levelName, $plot->X, $plot->Z); + if(!$cachedPlot instanceof SinglePlot and $orderCachePopulation and !in_array("{$plot->levelName}:{$plot->X}:{$plot->Z}", $this->populatingCache, true)){ + $index = count($this->populatingCache); + $this->populatingCache[] = "{$plot->levelName}:{$plot->X}:{$plot->Z}"; + Await::g2c( + $this->generatePlot($plot), + function(?BasePlot $cachedPlot) use ($index) : void{ + unset($this->populatingCache[$index]); + }, + function(\Throwable $e) use ($plot, $index) : void{ + $this->plugin->getLogger()->debug("Plot {$plot->X};{$plot->Z} could not be generated"); + unset($this->populatingCache[$index]); + } + ); + } + return $cachedPlot; } /** @@ -227,13 +246,13 @@ public function generatePlotByPosition(Position $position) : \Generator{ $x = $position->x; $z = $position->z; $levelName = $position->getWorld()->getFolderName(); - if($this->getLevelSettings($levelName) === null) - return null; $plotLevel = $this->getLevelSettings($levelName); + if($plotLevel === null) + return null; $plot = $this->getPlotFast($x, $z, $plotLevel); if($plot !== null) - return yield $this->generatePlot($plot); + return yield from $this->generatePlot($plot); return null; } @@ -253,40 +272,11 @@ public function getPlotPosition(BasePlot $plot) : Position{ return new Position($x, $plotLevel->groundHeight, $z, $level); } - /** - * @param Position $position - * @param callable|null $onComplete - * @phpstan-param (callable(bool): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function isPositionBorderingPlot(Position $position, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::f2c( - function() use ($position){ - $plot = yield $this->generatePlotBorderingPosition($position); - return $plot instanceof BasePlot; - }, - $onComplete, - $onFail === null ? [] : [$onFail] - ); - } - - /** - * @param Position $position - * @param callable|null $onComplete - * @phpstan-param (callable(BasePlot): void)|null $onComplete - * @param callable|null $onFail - * @phpstan-param (callable(\Throwable): void)|null $catches - */ - public function getPlotBorderingPosition(Position $position, ?callable $onComplete = null, ?callable $onFail = null) : void{ - Await::g2c( - $this->generatePlotBorderingPosition($position), - $onComplete, - $onFail === null ? [] : [$onFail] - ); + public function isPositionBorderingPlot(Position $position) : bool{ + return $this->getPlotBorderingPosition($position) instanceof BasePlot; } - public function generatePlotBorderingPosition(Position $position) : \Generator{ + public function getPlotBorderingPosition(Position $position) : ?BasePlot{ if(!$position->isValid()) return null; foreach(Facing::HORIZONTAL as $i){ @@ -299,14 +289,8 @@ public function generatePlotBorderingPosition(Position $position) : \Generator{ if($plotLevel === null) return null; - $plot = $this->getPlotFast($x, $z, $plotLevel); - if($plot === null){ - $plot = yield $this->generatePlot(new BasePlot($levelName, $x, $z)); - if(!$plot instanceof MergedPlot) // TODO: add more merge checks - continue; - return $plot; - } - return $plot; + return $this->getPlotFast($x, $z, $plotLevel); + // TODO: checks for merged plots } return null; } @@ -354,10 +338,11 @@ public function mergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTi } public function generateMergePlots(SinglePlot $plot, int $direction, int $maxBlocksPerTick) : \Generator{ - if($this->getLevelSettings($plot->levelName) === null) + $plotLevel = $this->getLevelSettings($plot->levelName); + if($plotLevel === null) return false; - $plot = yield $this->generatePlot($plot); + $plot = yield from $this->generatePlot($plot); /** @var BasePlot[] $toMerge */ $toMerge[] = $plot->getSide($direction); @@ -368,23 +353,10 @@ public function generateMergePlots(SinglePlot $plot, int $direction, int $maxBlo ); } - /** @var BasePlot[][] $toFill */ - $toFill = []; - foreach($toMerge as $pair){ - foreach($toMerge as $pair2){ - if($pair->getSide(Facing::rotateY($direction, !Facing::isPositive($direction)))->isSame($pair2)){ - $toFill[] = [$pair, $pair2]; - } - if($pair->getSide(Facing::opposite($direction))->isSame($pair2)){ - $toFill[] = [$pair, $pair2]; - } - } - } - /** @var SinglePlot[] $toMerge */ $toMerge = yield AsyncVariants::array_map( function(SinglePlot $plot) : \Generator{ - return yield $this->generatePlot($plot); + return yield from $this->generatePlot($plot); }, $toMerge ); @@ -398,17 +370,351 @@ function(SinglePlot $plot) : \Generator{ return false; } - $ev = new MyPlotMergeEvent($plot, $toMerge); + if(!$plot instanceof MergedPlot){ + $plot = MergedPlot::fromSingle( + $plot, + Facing::axis($direction) === Axis::X ? count($toMerge) : 1, + Facing::axis($direction) === Axis::Z ? count($toMerge) : 1 + ); + } + + $ev = new MyPlotMergeEvent($plot, $direction, $toMerge); $ev->call(); if($ev->isCancelled()) return false; - // TODO: WorldStyler clearing + $styler = $this->plugin->getServer()->getPluginManager()->getPlugin("WorldStyler"); + if($this->plugin->getConfig()->get("FastClearing", false) === true and $styler instanceof WorldStyler) { + $world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($world === null) + return false; + + $plotSize = $plotLevel->plotSize; + $totalSize = $plotSize + $plotLevel->roadWidth; + + $aabb = $this->getPlotBB($plot); + + $aabbExpanded = $aabb->expandedCopy(1, 0, 1); // expanded to include plot borders + foreach($world->getEntities() as $entity){ + if($aabbExpanded->isVectorInXZ($entity->getPosition())){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->teleportPlayerToPlot($entity, $plot, false); + } + } + } + + $aabb = match ($direction) { + Facing::NORTH => new AxisAlignedBB( + $aabb->minX, + $aabb->minY, + $aabb->minZ - $plotLevel->roadWidth, + $aabb->maxX, + $aabb->maxY, + $aabb->minZ + ), + Facing::EAST => new AxisAlignedBB( + $aabb->maxX + ($totalSize * ($plot->xWidth - 1)), + $aabb->minY, + $aabb->minZ, + $aabb->maxX + ($totalSize * ($plot->xWidth - 1)) + $plotLevel->roadWidth, + $aabb->maxY, + $aabb->maxZ + ), + Facing::SOUTH => new AxisAlignedBB( + $aabb->minX, + $aabb->minY, + $aabb->maxZ + ($totalSize * ($plot->zWidth - 1)), + $aabb->maxX, + $aabb->maxY, + $aabb->maxZ + ($totalSize * ($plot->zWidth - 1)) + $plotLevel->roadWidth + ), + Facing::WEST => new AxisAlignedBB( + $aabb->minX - $plotLevel->roadWidth, + $aabb->minY, + $aabb->minZ, + $aabb->minX, + $aabb->maxY, + $aabb->maxZ + ), + default => throw new \InvalidArgumentException("Invalid direction $direction") + }; + + // above ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->maxY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 2, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, VanillaBlocks::AIR()->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + if(Facing::axis($direction) === Axis::X) { + // min border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // max border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + }elseif(Facing::axis($direction) === Axis::Z){ + // min border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // max border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + } - foreach($toFill as $pair) - $this->plugin->getScheduler()->scheduleTask(new RoadFillTask($this->plugin, $this, $pair[0], $pair[1], $maxBlocksPerTick)); + // ground height + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->plotFloorBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); - return yield $this->dataProvider->mergePlots($plot, ...$toMerge); + // below ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight - 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // bottom block + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->minY, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + $i = 0; + foreach($toMerge as $newPlot) { + $newPlot = MergedPlot::fromSingle( + SinglePlot::fromBase($newPlot), + Facing::axis($direction) === Axis::X ? $i : 1, + Facing::axis($direction) === Axis::Z ? $i : 1 + ); + $direction = Facing::rotateY($direction, true); + + $aabb = $this->getPlotBB($newPlot); + + $aabbExpanded = $aabb->expandedCopy(1, 0, 1); // expanded to include plot borders + foreach($world->getEntities() as $entity){ + if($aabbExpanded->isVectorInXZ($entity->getPosition())){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->teleportPlayerToPlot($entity, $newPlot, false); + } + } + } + + $aabb = match ($direction) { + Facing::NORTH => new AxisAlignedBB( + $aabb->minX, + $aabb->minY, + $aabb->minZ - $plotLevel->roadWidth, + $aabb->maxX, + $aabb->maxY, + $aabb->minZ + ), + Facing::EAST => new AxisAlignedBB( + $aabb->maxX + ($totalSize * ($newPlot->xWidth - 1)), + $aabb->minY, + $aabb->minZ, + $aabb->maxX + ($totalSize * ($newPlot->xWidth - 1)) + $plotLevel->roadWidth, + $aabb->maxY, + $aabb->maxZ + ), + Facing::SOUTH => new AxisAlignedBB( + $aabb->minX, + $aabb->minY, + $aabb->maxZ + ($totalSize * ($newPlot->zWidth - 1)), + $aabb->maxX, + $aabb->maxY, + $aabb->maxZ + ($totalSize * ($newPlot->zWidth - 1)) + $plotLevel->roadWidth + ), + Facing::WEST => new AxisAlignedBB( + $aabb->minX - $plotLevel->roadWidth, + $aabb->minY, + $aabb->minZ, + $aabb->minX, + $aabb->maxY, + $aabb->maxZ + ), + default => throw new \InvalidArgumentException("Invalid direction $direction") + }; + + // above ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->maxY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 2, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, VanillaBlocks::AIR()->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + if(Facing::isPositive($direction)) { + if(Facing::axis($direction) === Axis::X) { + // max border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + }elseif(Facing::axis($direction) === Axis::Z){ + // max border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + } + }else{ + if(Facing::axis($direction) === Axis::X) { + // min border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + }elseif(Facing::axis($direction) === Axis::Z){ + // min border + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + } + } + + // ground height + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->plotFloorBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // below ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight - 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->plotFillBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // bottom block + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->minY, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->bottomBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + ++$i; + } + + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ + if($chunk === null) + continue; + foreach($chunk->getTiles() as $tile) + if($aabb->isVectorInXZ($tile->getPosition())) + $tile->close(); + $world->setChunk($chunkX, $chunkZ, $chunk); + } + + return yield from $this->dataProvider->mergePlots($plot, ...$toMerge); + } + + $this->plugin->getScheduler()->scheduleTask(new RoadFillTask($this->plugin, $plot, $direction, RoadFillTask::BOTH_BORDERS, $maxBlocksPerTick)); + + for($i = 0; $i < count($toMerge) - 1; ++$i){ + $this->plugin->getScheduler()->scheduleTask(new RoadFillTask( + $this->plugin, + MergedPlot::fromSingle( + SinglePlot::fromBase($toMerge[$i]), + Facing::axis($direction) === Axis::X ? $i : 1, + Facing::axis($direction) === Axis::Z ? $i : 1 + ), + Facing::rotateY($direction, true), + Facing::isPositive($direction) ? RoadFillTask::HIGH_BORDER : RoadFillTask::LOW_BORDER, + $maxBlocksPerTick + )); + } + + return yield from $this->dataProvider->mergePlots($plot, ...$toMerge); } public function teleportPlayerToPlot(Player $player, BasePlot $plot, bool $center = false) : bool{ @@ -469,7 +775,7 @@ public function generateClaimPlot(SinglePlot $plot, string $claimer, string $plo if($ev->isCancelled()){ return false; } - return yield $this->generatePlotsToSave($ev->getPlot()); + return yield from $this->generatePlotsToSave($ev->getPlot()); // TODO: figure out why cache is not updated } /** @@ -496,7 +802,7 @@ public function generateRenamePlot(SinglePlot $plot, string $newName) : \Generat if($ev->isCancelled()){ return false; } - return yield $this->generatePlotsToSave($ev->getPlot()); + return yield from $this->generatePlotsToSave($ev->getPlot()); } public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : bool{ @@ -557,6 +863,7 @@ public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : bool{ $this->plugin->getLogger()->debug(TF::GREEN . 'Pasted ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's from the MyPlot clipboard.'); }); $styler->removeSelection(99997); + foreach($this->getPlotChunks($plotTo) as [$chunkX, $chunkZ, $chunk]){ $world->setChunk($chunkX, $chunkZ, $chunk); } @@ -581,7 +888,7 @@ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick) : bool{ if($world === null) return false; - $aabb = $this->getPlotBB($plot); + $aabb = $this->getPlotBB($plot)->expand(1, 0, 1); // expanded to include plot borders foreach($world->getEntities() as $entity){ if($aabb->isVectorInXZ($entity->getPosition())){ if(!$entity instanceof Player){ @@ -592,9 +899,8 @@ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick) : bool{ } } - $selection = $styler->getSelection(99998) ?? new Selection(99998); - // Above ground + $selection = $styler->getSelection(99998) ?? new Selection(99998); $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->minZ)); $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->maxY, $aabb->maxZ)); $cuboid = Cuboid::fromSelection($selection); @@ -603,6 +909,7 @@ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick) : bool{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); + // Ground Surface $selection = $styler->getSelection(99998) ?? new Selection(99998); $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight, $aabb->minZ)); @@ -613,6 +920,7 @@ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick) : bool{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); + // Ground $selection = $styler->getSelection(99998) ?? new Selection(99998); $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY + 1, $aabb->minZ)); @@ -623,6 +931,7 @@ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick) : bool{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); + // Bottom of world $selection = $styler->getSelection(99998) ?? new Selection(99998); $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); @@ -633,10 +942,59 @@ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick) : bool{ $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); + + // Border +X + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // Border +Z + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $plotLevel->groundHeight + 1, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // Border -X + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->minX, $aabb->minY, $aabb->maxZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + + // Border -Z + $selection = $styler->getSelection(99998) ?? new Selection(99998); + $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY, $aabb->minZ)); + $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->minY, $aabb->minZ)); + $cuboid = Cuboid::fromSelection($selection); + //$cuboid = $cuboid->async(); + $cuboid->set($world, $plotLevel->wallBlock->getFullId(), function(float $time, int $changed) : void{ + $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); + }); + $styler->removeSelection(99998); + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ + if($chunk === null) + continue; + foreach($chunk->getTiles() as $tile) + if($aabb->isVectorInXZ($tile->getPosition())) + $tile->close(); $world->setChunk($chunkX, $chunkZ, $chunk); } - $this->plugin->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this->plugin, $plot), 1); return true; } $this->plugin->getScheduler()->scheduleTask(new ClearPlotTask($this->plugin, $plot, $maxBlocksPerTick)); @@ -674,7 +1032,7 @@ public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPer } // Ground - $selection = $styler->getSelection(99998); + $selection = $styler->getSelection(99998) ?? new Selection(99998); $selection->setPosition(1, new Vector3($aabb->minX, $aabb->minY + 1, $aabb->minZ)); $selection->setPosition(2, new Vector3($aabb->maxX, $aabb->maxY, $aabb->maxZ)); $cuboid = Cuboid::fromSelection($selection); @@ -683,6 +1041,7 @@ public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPer $this->plugin->getLogger()->debug('Set ' . number_format($changed) . ' blocks in ' . number_format($time, 10) . 's'); }); $styler->removeSelection(99998); + foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ $world->setChunk($chunkX, $chunkZ, $chunk); } @@ -713,7 +1072,7 @@ public function generateDisposePlot(BasePlot $plot) : \Generator{ if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - return yield $this->dataProvider->deletePlot($plot); + return yield from $this->dataProvider->deletePlot($plot); } /** @@ -738,11 +1097,11 @@ public function generateResetPlot(SinglePlot $plot, int $maxBlocksPerTick) : \Ge if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - if(!yield $this->generateDisposePlot($plot)){ + if(!yield from $this->generateDisposePlot($plot)){ return false; } if(!$this->clearPlot($plot, $maxBlocksPerTick)){ - yield $this->generatePlotsToSave($plot); + yield from $this->generatePlotsToSave($plot); return false; } return true; @@ -772,8 +1131,11 @@ public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - $plotLevel = $this->getLevelSettings($plot->levelName); - if($plotLevel === null) + if($this->getLevelSettings($plot->levelName) === null) + return false; + + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + if($level === null) return false; if(defined(BiomeIds::class . "::" . $plot->biome) and is_int(constant(BiomeIds::class . "::" . $plot->biome))){ @@ -783,22 +1145,21 @@ public function generatePlotBiome(SinglePlot $plot, Biome $biome) : \Generator{ } $biome = BiomeRegistry::getInstance()->getBiome($biome); - $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); - if($level === null) - return false; + $aabb = $this->getPlotBB($plot); foreach($this->getPlotChunks($plot) as [$chunkX, $chunkZ, $chunk]){ + if($chunk === null) + continue; + for($x = 0; $x < Chunk::EDGE_LENGTH; ++$x){ for($z = 0; $z < Chunk::EDGE_LENGTH; ++$z){ - $pos = new Position(($chunkX << Chunk::COORD_MASK) + $x, $plotLevel->groundHeight, ($chunkZ << Chunk::COORD_MASK) + $z, $level); - $chunkPlot = $this->getPlotFast($pos->x, $pos->z, $plotLevel); - if($chunkPlot instanceof SinglePlot and $chunkPlot->isSame($plot)){ + if($aabb->isVectorInXZ(new Vector3(($chunkX << Chunk::COORD_MASK) + $x, 0, ($chunkZ << Chunk::COORD_MASK) + $z))){ $chunk->setBiomeId($x, $z, $biome->getId()); } } } $level->setChunk($chunkX, $chunkZ, $chunk); } - return yield $this->generatePlotsToSave($plot); + return yield from $this->generatePlotsToSave($plot); } /** @@ -825,7 +1186,7 @@ public function generatePlotPvp(SinglePlot $plot, bool $pvp) : \Generator{ if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - return yield $this->dataProvider->savePlot($plot); + return yield from $this->dataProvider->savePlot($plot); } /** @@ -852,7 +1213,7 @@ public function generateAddPlotHelper(SinglePlot $plot, string $player) : \Gener if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - return yield $this->dataProvider->savePlot($plot); + return yield from $this->dataProvider->savePlot($plot); } /** @@ -879,7 +1240,7 @@ public function generateRemovePlotHelper(SinglePlot $plot, string $player) : \Ge if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - return yield $this->dataProvider->savePlot($plot); + return yield from $this->dataProvider->savePlot($plot); } /** @@ -906,7 +1267,7 @@ public function generateAddPlotDenied(SinglePlot $plot, string $player) : \Gener if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - return yield $this->dataProvider->savePlot($plot); + return yield from $this->dataProvider->savePlot($plot); } /** @@ -933,7 +1294,7 @@ public function generateRemovePlotDenied(SinglePlot $plot, string $player) : \Ge if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - return yield $this->dataProvider->savePlot($plot); + return yield from $this->dataProvider->savePlot($plot); } /** @@ -964,7 +1325,7 @@ public function generateSellPlot(SinglePlot $plot, int $price) : \Generator{ if($ev->isCancelled()) return false; $plot = $ev->getPlot(); - return yield $this->dataProvider->savePlot($plot); + return yield from $this->dataProvider->savePlot($plot); } /** @@ -987,15 +1348,15 @@ public function generateBuyPlot(SinglePlot $plot, Player $player) : \Generator{ if($this->economyProvider === null){ return false; } - if(!yield $this->economyProvider->reduceMoney($player, $plot->price)){ + if(!yield from $this->economyProvider->reduceMoney($player, $plot->price)){ return false; } - if(!yield $this->economyProvider->addMoney($this->plugin->getServer()->getOfflinePlayer($plot->owner), $plot->price)){ - yield $this->economyProvider->addMoney($player, $plot->price); + if(!yield from $this->economyProvider->addMoney($this->plugin->getServer()->getOfflinePlayer($plot->owner), $plot->price)){ + yield from $this->economyProvider->addMoney($player, $plot->price); return false; } - return yield $this->generateClaimPlot($plot, $player->getName(), ''); + return yield from $this->generateClaimPlot($plot, $player->getName(), ''); } /** diff --git a/src/MyPlot/MyPlot.php b/src/MyPlot/MyPlot.php index 10bdb9d8..df0e3f0f 100644 --- a/src/MyPlot/MyPlot.php +++ b/src/MyPlot/MyPlot.php @@ -2,14 +2,15 @@ declare(strict_types=1); namespace MyPlot; +use cooldogedev\BedrockEconomy\api\BedrockEconomyAPI; +use cooldogedev\BedrockEconomy\BedrockEconomy; use MyPlot\events\MyPlotGenerationEvent; use MyPlot\plot\BasePlot; use MyPlot\plot\SinglePlot; use MyPlot\provider\EconomyWrapper; +use MyPlot\provider\InternalBedrockEconomyProvider; use MyPlot\provider\InternalCapitalProvider; -use MyPlot\provider\InternalEconomyProvider; use MyPlot\provider\InternalEconomySProvider; -use onebone\economyapi\EconomyAPI; use pocketmine\block\Block; use pocketmine\lang\Language; use pocketmine\math\AxisAlignedBB; @@ -35,7 +36,7 @@ final class MyPlot extends PluginBase{ private static MyPlot $instance; private Language $language; private InternalAPI $internalAPI; - private ?EconomyWrapper $economyProvider; + private ?EconomyWrapper $economyProvider = null; public static function getInstance() : self{ return self::$instance; @@ -48,7 +49,7 @@ public static function getInstance() : self{ * * @return Language */ - public function getLanguage() : Language { + public function getLanguage() : Language{ return $this->language; } @@ -59,16 +60,16 @@ public function getLanguage() : Language { * * @return Language */ - public function getFallBackLang() : Language { + public function getFallBackLang() : Language{ return new Language(Language::FALLBACK_LANGUAGE, $this->getFile() . "resources/"); } /** - * Returns the EconomyProvider that is being used + * Returns the EconomyWrapper instance which is used to access the economy provider * - * @return InternalEconomyProvider|null * @api * + * @return EconomyWrapper|null */ public function getEconomyProvider() : ?EconomyWrapper{ return $this->economyProvider; @@ -77,10 +78,9 @@ public function getEconomyProvider() : ?EconomyWrapper{ /** * Allows setting the economy provider to a custom provider or to null to disable economy mode * - * @param bool $enable - * * @api * + * @param bool $enable */ public function toggleEconomy(bool $enable) : void{ if(!$enable){ @@ -114,7 +114,7 @@ public function getAllLevelSettings() : array{ * * @return PlotLevelSettings|null */ - public function getLevelSettings(string $levelName) : ?PlotLevelSettings { + public function getLevelSettings(string $levelName) : ?PlotLevelSettings{ return $this->internalAPI->getLevelSettings($levelName); } @@ -128,7 +128,7 @@ public function getLevelSettings(string $levelName) : ?PlotLevelSettings { * * @return void */ - public function addLevelSettings(string $levelName, PlotLevelSettings $settings) : void { + public function addLevelSettings(string $levelName, PlotLevelSettings $settings) : void{ $this->internalAPI->addLevelSettings($levelName, $settings); } @@ -141,7 +141,7 @@ public function addLevelSettings(string $levelName, PlotLevelSettings $settings) * * @return bool */ - public function unloadLevelSettings(string $levelName) : bool { + public function unloadLevelSettings(string $levelName) : bool{ return $this->internalAPI->unloadLevelSettings($levelName); } @@ -150,27 +150,27 @@ public function unloadLevelSettings(string $levelName) : bool { * * @api * - * @param string $levelName - * @param string $generator + * @param string $levelName + * @param string $generator * @param mixed[] $settings * * @return bool */ - public function generateLevel(string $levelName, string $generator = MyPlotGenerator::NAME, array $settings = []) : bool { + public function generateLevel(string $levelName, string $generator = MyPlotGenerator::NAME, array $settings = []) : bool{ $ev = new MyPlotGenerationEvent($levelName, $generator, $settings); $ev->call(); - if($ev->isCancelled() or $this->getServer()->getWorldManager()->isWorldGenerated($levelName)) { + if($ev->isCancelled() or $this->getServer()->getWorldManager()->isWorldGenerated($levelName)){ return false; } $generator = GeneratorManager::getInstance()->getGenerator($generator); - if(count($settings) === 0) { + if(count($settings) === 0){ $this->getConfig()->reload(); $settings = $this->getConfig()->get("DefaultWorld", []); } - $default = array_filter((array) $this->getConfig()->get("DefaultWorld", []), function($key) : bool { + $default = array_filter((array) $this->getConfig()->get("DefaultWorld", []), function($key) : bool{ return !in_array($key, ["PlotSize", "GroundHeight", "RoadWidth", "RoadBlock", "WallBlock", "PlotFloorBlock", "PlotFillBlock", "BottomBlock"], true); }, ARRAY_FILTER_USE_KEY); - new Config($this->getDataFolder()."worlds".DIRECTORY_SEPARATOR.$levelName.".yml", Config::YAML, $default); + new Config($this->getDataFolder() . "worlds" . DIRECTORY_SEPARATOR . $levelName . ".yml", Config::YAML, $default); $return = $this->getServer()->getWorldManager()->generateWorld($levelName, WorldCreationOptions::create()->setGeneratorClass($generator->getGeneratorClass())->setGeneratorOptions(json_encode($settings)), true); $level = $this->getServer()->getWorldManager()->getWorldByName($levelName); $level?->setSpawnLocation(new Vector3(0, $this->getConfig()->getNested("DefaultWorld.GroundHeight", 64) + 1, 0)); @@ -258,6 +258,17 @@ public function getPlot(string $levelName, int $X, int $Z) : Promise{ return $resolver->getPromise(); } + /** + * @param float &$x + * @param float &$z + * @param PlotLevelSettings $plotLevel + * + * @return BasePlot|null + */ + public function getPlotFast(float &$x, float &$z, PlotLevelSettings $plotLevel) : ?BasePlot{ + return $this->internalAPI->getPlotFast($x, $z, $plotLevel); + } + /** * Finds the plot at a certain position or null if there is no plot at that position * @@ -281,11 +292,11 @@ public function getPlotByPosition(Position $position) : Promise{ /** * Get the beginning position of a plot * + * @api + * * @param BasePlot $plot * * @return Position - * @api - * */ public function getPlotPosition(BasePlot $plot) : Position{ return $this->internalAPI->getPlotPosition($plot); @@ -298,17 +309,10 @@ public function getPlotPosition(BasePlot $plot) : Position{ * * @param Position $position * - * @return Promise - * @phpstan-return Promise + * @return bool */ - public function isPositionBorderingPlot(Position $position) : Promise{ - $resolver = new PromiseResolver(); - $this->internalAPI->isPositionBorderingPlot( - $position, - fn(bool $bordering) => $resolver->resolve($bordering), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function isPositionBorderingPlot(Position $position) : bool{ + return $this->internalAPI->isPositionBorderingPlot($position); } /** @@ -318,29 +322,22 @@ public function isPositionBorderingPlot(Position $position) : Promise{ * * @param Position $position * - * @return Promise - * @phpstan-return Promise + * @return BasePlot|null */ - public function getPlotBorderingPosition(Position $position) : Promise{ - $resolver = new PromiseResolver(); - $this->internalAPI->getPlotBorderingPosition( - $position, - fn(SinglePlot $plot) => $resolver->resolve($plot), - fn(\Throwable $e) => $resolver->reject() - ); - return $resolver->getPromise(); + public function getPlotBorderingPosition(Position $position) : ?BasePlot{ + return $this->internalAPI->getPlotBorderingPosition($position); } /** * Returns the AABB of the plot area * - * @param SinglePlot $plot - * - * @return AxisAlignedBB * @api * + * @param BasePlot $plot + * + * @return AxisAlignedBB */ - public function getPlotBB(SinglePlot $plot) : AxisAlignedBB{ + public function getPlotBB(BasePlot $plot) : AxisAlignedBB{ return $this->internalAPI->getPlotBB($plot); } @@ -446,12 +443,12 @@ public function clonePlot(SinglePlot $plotFrom, SinglePlot $plotTo) : bool{ /** * Reset all the blocks inside a plot * + * @api + * * @param BasePlot $plot * @param int $maxBlocksPerTick * * @return bool - * @api - * */ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick = 256) : bool{ return $this->internalAPI->clearPlot($plot, $maxBlocksPerTick); @@ -466,19 +463,14 @@ public function clearPlot(BasePlot $plot, int $maxBlocksPerTick = 256) : bool{ * @param Block $plotFillBlock * @param int $maxBlocksPerTick * - * @return Promise - * @phpstan-return Promise + * @return bool */ - public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick = 256) : Promise{ - $resolver = new PromiseResolver(); - $this->internalAPI->fillPlot( + public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPerTick = 256) : bool{ + return $this->internalAPI->fillPlot( $plot, $plotFillBlock, - $maxBlocksPerTick, - fn(bool $success) => $resolver->resolve($success), - fn(\Throwable $e) => $resolver->reject() + $maxBlocksPerTick ); - return $resolver->getPromise(); } /** @@ -491,7 +483,7 @@ public function fillPlot(BasePlot $plot, Block $plotFillBlock, int $maxBlocksPer * @return Promise * @phpstan-return Promise */ - public function disposePlot(SinglePlot $plot) : Promise { + public function disposePlot(SinglePlot $plot) : Promise{ $resolver = new PromiseResolver(); $this->internalAPI->disposePlot( $plot, @@ -512,7 +504,7 @@ public function disposePlot(SinglePlot $plot) : Promise { * @return Promise * @phpstan-return Promise */ - public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promise { + public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promise{ $resolver = new PromiseResolver(); $this->internalAPI->resetPlot( $plot, @@ -534,7 +526,7 @@ public function resetPlot(SinglePlot $plot, int $maxBlocksPerTick = 256) : Promi * @return Promise * @phpstan-return Promise */ - public function setPlotBiome(SinglePlot $plot, Biome $biome) : Promise { + public function setPlotBiome(SinglePlot $plot, Biome $biome) : Promise{ $resolver = new PromiseResolver(); $this->internalAPI->setPlotBiome( $plot, @@ -710,7 +702,7 @@ public function buyPlot(SinglePlot $plot, Player $player) : Promise{ * @phpstan-return array> */ public function getPlotChunks(BasePlot $plot) : array{ - $this->internalAPI->getPlotChunks($plot); + return $this->internalAPI->getPlotChunks($plot); } /** @@ -722,19 +714,19 @@ public function getPlotChunks(BasePlot $plot) : array{ * * @return int */ - public function getMaxPlotsOfPlayer(Player $player) : int { + public function getMaxPlotsOfPlayer(Player $player) : int{ if($player->hasPermission("myplot.claimplots.unlimited")) return PHP_INT_MAX; $perms = array_map(fn(PermissionAttachmentInfo $attachment) => $attachment->getValue(), $player->getEffectivePermissions()); // outputs permission string => value $perms = array_merge(PermissionManager::getInstance()->getPermission(DefaultPermissions::ROOT_USER)->getChildren(), $perms); - $perms = array_filter($perms, function(string $name) : bool { + $perms = array_filter($perms, function(string $name) : bool{ return (str_starts_with($name, "myplot.claimplots.")); }, ARRAY_FILTER_USE_KEY); if(count($perms) === 0) return 0; krsort($perms, SORT_FLAG_CASE | SORT_NATURAL); /** - * @var string $name + * @var string $name * @var Permission $perm */ foreach($perms as $name => $perm){ @@ -750,19 +742,24 @@ public function getMaxPlotsOfPlayer(Player $player) : int { private function checkEconomy() : InternalEconomySProvider{ $this->getLogger()->debug(TF::BOLD . "Loading economy settings"); - $this->economyProvider = $economyProvider = null; + $economyProvider = null; if(($plugin = $this->getServer()->getPluginManager()->getPlugin("EconomyAPI")) !== null){ if($plugin instanceof EconomyAPI){ $economyProvider = new InternalEconomySProvider($plugin); - $this->economyProvider = new EconomyWrapper($economyProvider); $this->getLogger()->info("Economy set to EconomyAPI"); }else $this->getLogger()->debug("Invalid instance of EconomyAPI"); } + if(($plugin = $this->getServer()->getPluginManager()->getPlugin("BedrockEconomy")) !== null){ + if($plugin instanceof BedrockEconomy){ + $economyProvider = new InternalBedrockEconomyProvider(BedrockEconomyAPI::getInstance()); + $this->getLogger()->info("Economy set to BedrockEconomy"); + }else + $this->getLogger()->debug("Invalid instance of BedrockEconomy"); + } if(($plugin = $this->getServer()->getPluginManager()->getPlugin("Capital")) !== null){ if($plugin instanceof Capital){ $economyProvider = new InternalCapitalProvider(); - $this->economyProvider = new EconomyWrapper($economyProvider); $this->getLogger()->info("Economy set to Capital"); }else $this->getLogger()->debug("Invalid instance of Capital"); @@ -771,6 +768,8 @@ private function checkEconomy() : InternalEconomySProvider{ $this->getLogger()->warning("No supported economy plugin found!"); $this->getConfig()->set("UseEconomy", false); //$this->getConfig()->save(); + }else{ + $this->economyProvider = new EconomyWrapper($economyProvider); } return $economyProvider; } @@ -788,22 +787,22 @@ public function onLoad() : void{ $this->getLogger()->debug(TF::BOLD . "Loading Languages"); /** @var string $lang */ $lang = $this->getConfig()->get("Language", Language::FALLBACK_LANGUAGE); - if($this->getConfig()->get("Custom Messages", false) === true) { - if(!file_exists($this->getDataFolder()."lang.ini")) { + if($this->getConfig()->get("Custom Messages", false) === true){ + if(!file_exists($this->getDataFolder() . "lang.ini")){ /** @var string|resource $resource */ - $resource = $this->getResource($lang.".ini") ?? file_get_contents($this->getFile()."resources/".Language::FALLBACK_LANGUAGE.".ini"); - file_put_contents($this->getDataFolder()."lang.ini", $resource); - if(is_resource($resource)) { + $resource = $this->getResource($lang . ".ini") ?? file_get_contents($this->getFile() . "resources/" . Language::FALLBACK_LANGUAGE . ".ini"); + file_put_contents($this->getDataFolder() . "lang.ini", $resource); + if(is_resource($resource)){ fclose($resource); } - $this->saveResource(Language::FALLBACK_LANGUAGE.".ini", true); + $this->saveResource(Language::FALLBACK_LANGUAGE . ".ini", true); $this->getLogger()->debug("Custom Language ini created"); } $this->language = new Language("lang", $this->getDataFolder()); }else{ - if(file_exists($this->getDataFolder()."lang.ini")) { - unlink($this->getDataFolder()."lang.ini"); - unlink($this->getDataFolder().Language::FALLBACK_LANGUAGE.".ini"); + if(file_exists($this->getDataFolder() . "lang.ini")){ + unlink($this->getDataFolder() . "lang.ini"); + unlink($this->getDataFolder() . Language::FALLBACK_LANGUAGE . ".ini"); $this->getLogger()->debug("Custom Language ini deleted"); } $this->language = new Language($lang, $this->getFile() . "resources/"); @@ -824,12 +823,12 @@ public function onLoad() : void{ $this->getServer()->getCommandMap()->register("myplot", new Commands($this, $this->internalAPI)); } - public function onEnable() : void { + public function onEnable() : void{ $this->getLogger()->debug(TF::BOLD . "Loading Events"); $this->getServer()->getPluginManager()->registerEvents(new EventListener($this, $this->internalAPI), $this); } - public function onDisable() : void { + public function onDisable() : void{ $this->internalAPI->onDisable(); } } \ No newline at end of file diff --git a/src/MyPlot/MyPlotGenerator.php b/src/MyPlot/MyPlotGenerator.php index acdab337..fa7be64f 100644 --- a/src/MyPlot/MyPlotGenerator.php +++ b/src/MyPlot/MyPlotGenerator.php @@ -9,7 +9,7 @@ use pocketmine\world\format\Chunk; use pocketmine\world\generator\Generator; -class MyPlotGenerator extends Generator { +class MyPlotGenerator extends Generator{ protected Block $roadBlock; protected Block $bottomBlock; protected Block $plotFillBlock; @@ -29,9 +29,9 @@ class MyPlotGenerator extends Generator { * @param int $seed * @param string $preset */ - public function __construct(int $seed, string $preset) { + public function __construct(int $seed, string $preset){ $settings = json_decode($preset, true); - if($settings === false or is_null($settings)) { + if($settings === false or is_null($settings)){ $settings = []; } $this->roadBlock = PlotLevelSettings::parseBlock($settings, "RoadBlock", VanillaBlocks::OAK_PLANKS()); @@ -54,7 +54,7 @@ public function __construct(int $seed, string $preset) { ])); } - public function generateChunk(ChunkManager $world, int $chunkX, int $chunkZ) : void { + public function generateChunk(ChunkManager $world, int $chunkX, int $chunkZ) : void{ $shape = $this->getShape($chunkX << 4, $chunkZ << 4); $chunk = $world->getChunk($chunkX, $chunkZ); $bottomBlockId = $this->bottomBlock->getFullId(); @@ -63,17 +63,17 @@ public function generateChunk(ChunkManager $world, int $chunkX, int $chunkZ) : v $roadBlockId = $this->roadBlock->getFullId(); $wallBlockId = $this->wallBlock->getFullId(); $groundHeight = $this->groundHeight; - for($Z = 0; $Z < 16; ++$Z) { - for($X = 0; $X < 16; ++$X) { + for($Z = 0; $Z < 16; ++$Z){ + for($X = 0; $X < 16; ++$X){ $chunk->setBiomeId($X, $Z, BiomeIds::PLAINS); $chunk->setFullBlock($X, 0, $Z, $bottomBlockId); - for($y = 1; $y < $groundHeight; ++$y) { + for($y = 1; $y < $groundHeight; ++$y){ $chunk->setFullBlock($X, $y, $Z, $plotFillBlockId); } $type = $shape[($Z << 4) | $X]; - if($type === self::PLOT) { + if($type === self::PLOT){ $chunk->setFullBlock($X, $groundHeight, $Z, $plotFloorBlockId); - }elseif($type === self::ROAD) { + }elseif($type === self::ROAD){ $chunk->setFullBlock($X, $groundHeight, $Z, $roadBlockId); }else{ $chunk->setFullBlock($X, $groundHeight, $Z, $roadBlockId); @@ -92,47 +92,47 @@ public function generateChunk(ChunkManager $world, int $chunkX, int $chunkZ) : v * * @return \SplFixedArray */ - public function getShape(int $x, int $z) : \SplFixedArray { + public function getShape(int $x, int $z) : \SplFixedArray{ $totalSize = $this->plotSize + $this->roadWidth; - if($x >= 0) { + if($x >= 0){ $X = $x % $totalSize; }else{ $X = $totalSize - abs($x % $totalSize); } - if($z >= 0) { + if($z >= 0){ $Z = $z % $totalSize; }else{ $Z = $totalSize - abs($z % $totalSize); } $startX = $X; $shape = new \SplFixedArray(256); - for($z = 0; $z < 16; $z++, $Z++) { - if($Z === $totalSize) { + for($z = 0; $z < 16; $z++, $Z++){ + if($Z === $totalSize){ $Z = 0; } - if($Z < $this->plotSize) { + if($Z < $this->plotSize){ $typeZ = self::PLOT; - }elseif($Z === $this->plotSize or $Z === ($totalSize - 1)) { + }elseif($Z === $this->plotSize or $Z === ($totalSize - 1)){ $typeZ = self::WALL; }else{ $typeZ = self::ROAD; } - for($x = 0, $X = $startX; $x < 16; $x++, $X++) { - if($X === $totalSize) { + for($x = 0, $X = $startX; $x < 16; $x++, $X++){ + if($X === $totalSize){ $X = 0; } - if($X < $this->plotSize) { + if($X < $this->plotSize){ $typeX = self::PLOT; - }elseif($X === $this->plotSize or $X === ($totalSize - 1)) { + }elseif($X === $this->plotSize or $X === ($totalSize - 1)){ $typeX = self::WALL; }else{ $typeX = self::ROAD; } - if($typeX === $typeZ) { + if($typeX === $typeZ){ $type = $typeX; - }elseif($typeX === self::PLOT) { + }elseif($typeX === self::PLOT){ $type = $typeZ; - }elseif($typeZ === self::PLOT) { + }elseif($typeZ === self::PLOT){ $type = $typeX; }else{ $type = self::ROAD; @@ -143,5 +143,5 @@ public function getShape(int $x, int $z) : \SplFixedArray { return $shape; } - public function populateChunk(ChunkManager $world, int $chunkX, int $chunkZ) : void {} + public function populateChunk(ChunkManager $world, int $chunkX, int $chunkZ) : void{ } } \ No newline at end of file diff --git a/src/MyPlot/PlotLevelSettings.php b/src/MyPlot/PlotLevelSettings.php index f6fa631e..72e3178a 100644 --- a/src/MyPlot/PlotLevelSettings.php +++ b/src/MyPlot/PlotLevelSettings.php @@ -3,11 +3,11 @@ namespace MyPlot; use pocketmine\block\Block; -use pocketmine\block\BlockFactory; use pocketmine\block\VanillaBlocks; +use pocketmine\item\ItemBlock; +use pocketmine\item\StringToItemParser; -class PlotLevelSettings -{ +class PlotLevelSettings{ public string $name; public Block $roadBlock; public Block $bottomBlock; @@ -22,22 +22,22 @@ class PlotLevelSettings public int $disposePrice = 0; public int $resetPrice = 0; public int $clonePrice = 0; + public int $fillPrice = 0; public bool $restrictEntityMovement = true; public bool $restrictPVP = false; public bool $updatePlotLiquids = false; public bool $allowOutsidePlotSpread = false; - public bool $displayDoneNametags = false; public bool $editBorderBlocks = true; /** * PlotLevelSettings constructor. * - * @param string $name + * @param string $name * @param mixed[] $settings */ - public function __construct(string $name, array $settings = []) { + public function __construct(string $name, array $settings = []){ $this->name = $name; - if(count($settings) > 0) { + if(count($settings) > 0){ $this->roadBlock = self::parseBlock($settings, "RoadBlock", VanillaBlocks::OAK_PLANKS()); $this->wallBlock = self::parseBlock($settings, "WallBlock", VanillaBlocks::STONE_SLAB()); $this->plotFloorBlock = self::parseBlock($settings, "PlotFloorBlock", VanillaBlocks::GRASS()); @@ -60,40 +60,26 @@ public function __construct(string $name, array $settings = []) { } /** - * @param string[] $array + * @param string[] $array * @param string|int $key - * @param Block $default + * @param Block $default * * @return Block */ - public static function parseBlock(array $array, string|int $key, Block $default) : Block { - if(isset($array[$key])) { - $id = $array[$key]; - if(is_numeric($id)) { - $block = BlockFactory::getInstance()->get((int) $id); - }else{ - $split = explode(":", $id); - if(count($split) === 2 and is_numeric($split[0]) and is_numeric($split[1])) { - $block = BlockFactory::getInstance()->get((int) $split[0], (int) $split[1]); - }else{ - $block = $default; - } - } - }else{ - $block = $default; - } - return $block; + public static function parseBlock(array $array, string|int $key, Block $default) : Block{ + $item = StringToItemParser::getInstance()->parse($array[$key]); + return $item instanceof ItemBlock ? $item->getBlock() : $default; } /** - * @param string[] $array + * @param string[] $array * @param string|int $key - * @param int $default + * @param int $default * * @return int */ - public static function parseNumber(array $array, string|int $key, int $default) : int { - if(isset($array[$key]) and is_numeric($array[$key])) { + public static function parseNumber(array $array, string|int $key, int $default) : int{ + if(isset($array[$key]) and is_numeric($array[$key])){ return (int) $array[$key]; }else{ return $default; @@ -101,14 +87,14 @@ public static function parseNumber(array $array, string|int $key, int $default) } /** - * @param mixed[] $array + * @param mixed[] $array * @param string|int $key - * @param bool $default + * @param bool $default * * @return bool */ - public static function parseBool(array $array, string|int $key, bool $default) : bool { - if(isset($array[$key]) and is_bool($array[$key])) { + public static function parseBool(array $array, string|int $key, bool $default) : bool{ + if(isset($array[$key]) and is_bool($array[$key])){ return $array[$key]; }else{ return $default; diff --git a/src/MyPlot/events/MyPlotBlockEvent.php b/src/MyPlot/events/MyPlotBlockEvent.php index 3f77ea55..2c69cc41 100644 --- a/src/MyPlot/events/MyPlotBlockEvent.php +++ b/src/MyPlot/events/MyPlotBlockEvent.php @@ -2,7 +2,7 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\block\Block; use pocketmine\event\block\BlockBreakEvent; use pocketmine\event\block\BlockPlaceEvent; @@ -13,7 +13,7 @@ use pocketmine\event\player\PlayerInteractEvent; use pocketmine\player\Player; -class MyPlotBlockEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotBlockEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; private Block $block; @@ -24,30 +24,30 @@ class MyPlotBlockEvent extends MyPlotPlotEvent implements Cancellable { /** * MyPlotBlockEvent constructor. * - * @param Plot $plot - * @param Block $block - * @param Player $player + * @param BasePlot $plot + * @param Block $block + * @param Player $player * @param BlockPlaceEvent|BlockBreakEvent|PlayerInteractEvent|SignChangeEvent $event */ - public function __construct(Plot $plot, Block $block, Player $player, Event $event) { + public function __construct(BasePlot $plot, Block $block, Player $player, Event $event){ $this->block = $block; $this->player = $player; $this->event = $event; parent::__construct($plot); } - public function getBlock() : Block { + public function getBlock() : Block{ return $this->block; } /** * @return BlockPlaceEvent|BlockBreakEvent|PlayerInteractEvent|SignChangeEvent */ - public function getEvent() : Event { + public function getEvent() : Event{ return $this->event; } - public function getPlayer() : Player { + public function getPlayer() : Player{ return $this->player; } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotBorderChangeEvent.php b/src/MyPlot/events/MyPlotBorderChangeEvent.php index cf387f78..b3c9cdff 100644 --- a/src/MyPlot/events/MyPlotBorderChangeEvent.php +++ b/src/MyPlot/events/MyPlotBorderChangeEvent.php @@ -4,6 +4,6 @@ namespace MyPlot\events; -class MyPlotBorderChangeEvent extends MyPlotBlockEvent { +class MyPlotBorderChangeEvent extends MyPlotBlockEvent{ } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotClearEvent.php b/src/MyPlot/events/MyPlotClearEvent.php index 8ea187a4..8c1fe6e9 100644 --- a/src/MyPlot/events/MyPlotClearEvent.php +++ b/src/MyPlot/events/MyPlotClearEvent.php @@ -2,11 +2,11 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -class MyPlotClearEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotClearEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; private int $maxBlocksPerTick; @@ -14,19 +14,19 @@ class MyPlotClearEvent extends MyPlotPlotEvent implements Cancellable { /** * MyPlotClearEvent constructor. * - * @param Plot $plot - * @param int $maxBlocksPerTick + * @param BasePlot $plot + * @param int $maxBlocksPerTick */ - public function __construct(Plot $plot, int $maxBlocksPerTick = 256) { + public function __construct(BasePlot $plot, int $maxBlocksPerTick = 256){ $this->maxBlocksPerTick = $maxBlocksPerTick; parent::__construct($plot); } - public function getMaxBlocksPerTick() : int { + public function getMaxBlocksPerTick() : int{ return $this->maxBlocksPerTick; } - public function setMaxBlocksPerTick(int $maxBlocksPerTick) : self { + public function setMaxBlocksPerTick(int $maxBlocksPerTick) : self{ $this->maxBlocksPerTick = $maxBlocksPerTick; return $this; } diff --git a/src/MyPlot/events/MyPlotCloneEvent.php b/src/MyPlot/events/MyPlotCloneEvent.php index 91eb0e0c..01c724e6 100644 --- a/src/MyPlot/events/MyPlotCloneEvent.php +++ b/src/MyPlot/events/MyPlotCloneEvent.php @@ -2,31 +2,25 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -class MyPlotCloneEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotCloneEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; - protected Plot $clonePlot; + protected BasePlot $clonePlot; - /** - * MyPlotCloneEvent constructor. - * - * @param Plot $originPlot - * @param Plot $clonePlot - */ - public function __construct(Plot $originPlot, Plot $clonePlot) { + public function __construct(BasePlot $originPlot, BasePlot $clonePlot){ $this->clonePlot = $clonePlot; parent::__construct($originPlot); } - public function setClonePlot(Plot $clonePlot) : void { + public function setClonePlot(BasePlot $clonePlot) : void{ $this->clonePlot = $clonePlot; } - public function getClonePlot() : Plot { + public function getClonePlot() : BasePlot{ return $this->clonePlot; } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotDenyEvent.php b/src/MyPlot/events/MyPlotDenyEvent.php deleted file mode 100644 index 6a88361d..00000000 --- a/src/MyPlot/events/MyPlotDenyEvent.php +++ /dev/null @@ -1,57 +0,0 @@ -type = $type; - $this->player = $player; - parent::__construct($plot); - } - - public function getType() : int { - return $this->type; - } - - public function setType(int $type) : self { - $this->type = $type; - return $this; - } - - public function getDenied() : string { - return $this->player; - } - - /** - * @param IPlayer|string $player - * - * @return self - */ - public function setDenied(IPlayer|string $player) : self { - if($player instanceof IPlayer) { - $this->player = $player->getName(); - }else { - $this->player = $player; - } - return $this; - } -} \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotDisposeEvent.php b/src/MyPlot/events/MyPlotDisposeEvent.php index 04a5d56d..5c86cfcf 100644 --- a/src/MyPlot/events/MyPlotDisposeEvent.php +++ b/src/MyPlot/events/MyPlotDisposeEvent.php @@ -2,19 +2,9 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -class MyPlotDisposeEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotDisposeEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; - - /** - * MyPlotClearEvent constructor. - * - * @param Plot $plot - */ - public function __construct(Plot $plot) { - parent::__construct($plot); - } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotFillEvent.php b/src/MyPlot/events/MyPlotFillEvent.php index fdeb9fb7..ce7f27f9 100644 --- a/src/MyPlot/events/MyPlotFillEvent.php +++ b/src/MyPlot/events/MyPlotFillEvent.php @@ -2,11 +2,11 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -class MyPlotFillEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotFillEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; /** @var int $maxBlocksPerTick */ @@ -15,10 +15,10 @@ class MyPlotFillEvent extends MyPlotPlotEvent implements Cancellable { /** * MyPlotFillEvent constructor. * - * @param Plot $plot - * @param int $maxBlocksPerTick + * @param BasePlot $plot + * @param int $maxBlocksPerTick */ - public function __construct(Plot $plot, int $maxBlocksPerTick = 256) { + public function __construct(BasePlot $plot, int $maxBlocksPerTick = 256){ $this->maxBlocksPerTick = $maxBlocksPerTick; parent::__construct($plot); } @@ -26,7 +26,7 @@ public function __construct(Plot $plot, int $maxBlocksPerTick = 256) { /** * @return int */ - public function getMaxBlocksPerTick() : int { + public function getMaxBlocksPerTick() : int{ return $this->maxBlocksPerTick; } @@ -35,7 +35,7 @@ public function getMaxBlocksPerTick() : int { * * @return self */ - public function setMaxBlocksPerTick(int $maxBlocksPerTick) : self { + public function setMaxBlocksPerTick(int $maxBlocksPerTick) : self{ $this->maxBlocksPerTick = $maxBlocksPerTick; return $this; } diff --git a/src/MyPlot/events/MyPlotGenerationEvent.php b/src/MyPlot/events/MyPlotGenerationEvent.php index 958d12bc..627b3527 100644 --- a/src/MyPlot/events/MyPlotGenerationEvent.php +++ b/src/MyPlot/events/MyPlotGenerationEvent.php @@ -6,7 +6,7 @@ use pocketmine\event\CancellableTrait; use pocketmine\event\Event; -class MyPlotGenerationEvent extends Event implements Cancellable { +class MyPlotGenerationEvent extends Event implements Cancellable{ use CancellableTrait; private string $levelName; @@ -17,30 +17,30 @@ class MyPlotGenerationEvent extends Event implements Cancellable { /** * MyPlotGenerationEvent constructor. * - * @param string $levelName - * @param string $generator + * @param string $levelName + * @param string $generator * @param string[] $settings */ - public function __construct(string $levelName, string $generator = "myplot", array $settings = []) { + public function __construct(string $levelName, string $generator = "myplot", array $settings = []){ $this->levelName = $levelName; $this->generator = $generator; $this->settings = $settings; } - public function getLevelName() : string { + public function getLevelName() : string{ return $this->levelName; } - public function setLevelName(string $levelName) : self { + public function setLevelName(string $levelName) : self{ $this->levelName = $levelName; return $this; } - public function getGenerator() : string { + public function getGenerator() : string{ return $this->generator; } - public function setGenerator(string $generator) : self { + public function setGenerator(string $generator) : self{ $this->generator = $generator; return $this; } @@ -48,7 +48,7 @@ public function setGenerator(string $generator) : self { /** * @return string[] */ - public function getSettings() : array { + public function getSettings() : array{ return $this->settings; } @@ -58,7 +58,7 @@ public function getSettings() : array { * @return self * @throws \JsonException */ - public function setSettings(array $settings) : self { + public function setSettings(array $settings) : self{ $this->settings = $settings; $this->settings["preset"] = json_encode($settings, JSON_THROW_ON_ERROR); return $this; diff --git a/src/MyPlot/events/MyPlotMergeEvent.php b/src/MyPlot/events/MyPlotMergeEvent.php index 7411ff9e..4cd821db 100644 --- a/src/MyPlot/events/MyPlotMergeEvent.php +++ b/src/MyPlot/events/MyPlotMergeEvent.php @@ -2,33 +2,38 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; +use MyPlot\plot\MergedPlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -class MyPlotMergeEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotMergeEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; - /** @var Plot[][] $toMerge */ - private array $toMerge; + /** @var BasePlot[] $toMerge */ + private array $toMerge; + private int $direction; - /** - * MyPlotMergeEvent constructor. - * @param Plot $plot - * @param Plot[][] $toMerge - */ - public function __construct(Plot $plot, array $toMerge) { - $this->toMerge = $toMerge; + /** + * MyPlotMergeEvent constructor. + * + * @param MergedPlot $plot + * @param int $direction + * @param BasePlot[] $toMerge + */ + public function __construct(MergedPlot $plot, int $direction, array $toMerge){ parent::__construct($plot); + $this->direction = $direction; + $this->toMerge = $toMerge; } - /** - * @return Plot[][] - */ - public function getToMergePairs() : array { - return $this->toMerge; - } + /** + * @return BasePlot[] + */ + public function getToMergePairs() : array{ + return $this->toMerge; + } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotPlayerEnterPlotEvent.php b/src/MyPlot/events/MyPlotPlayerEnterPlotEvent.php index a1ae4af4..9a17d66d 100644 --- a/src/MyPlot/events/MyPlotPlayerEnterPlotEvent.php +++ b/src/MyPlot/events/MyPlotPlayerEnterPlotEvent.php @@ -2,12 +2,12 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; use pocketmine\player\Player; -class MyPlotPlayerEnterPlotEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotPlayerEnterPlotEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; private Player $player; @@ -15,19 +15,19 @@ class MyPlotPlayerEnterPlotEvent extends MyPlotPlotEvent implements Cancellable /** * MyPlotPlayerEnterPlotEvent constructor. * - * @param Plot $plot - * @param Player $player + * @param BasePlot $plot + * @param Player $player */ - public function __construct(Plot $plot, Player $player) { + public function __construct(BasePlot $plot, Player $player){ $this->player = $player; parent::__construct($plot); } - public function getPlayer() : Player { + public function getPlayer() : Player{ return $this->player; } - public function setPlayer(Player $player) : self { + public function setPlayer(Player $player) : self{ $this->player = $player; return $this; } diff --git a/src/MyPlot/events/MyPlotPlayerLeavePlotEvent.php b/src/MyPlot/events/MyPlotPlayerLeavePlotEvent.php index b2afdeb7..eb5b5125 100644 --- a/src/MyPlot/events/MyPlotPlayerLeavePlotEvent.php +++ b/src/MyPlot/events/MyPlotPlayerLeavePlotEvent.php @@ -2,12 +2,12 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; use pocketmine\player\Player; -class MyPlotPlayerLeavePlotEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotPlayerLeavePlotEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; private Player $player; @@ -15,15 +15,15 @@ class MyPlotPlayerLeavePlotEvent extends MyPlotPlotEvent implements Cancellable /** * MyPlotPlayerLeavePlotEvent constructor. * - * @param Plot $plot - * @param Player $player + * @param BasePlot $plot + * @param Player $player */ - public function __construct(Plot $plot, Player $player) { + public function __construct(BasePlot $plot, Player $player){ $this->player = $player; parent::__construct($plot); } - public function getPlayer() : Player { + public function getPlayer() : Player{ return $this->player; } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotPlotEvent.php b/src/MyPlot/events/MyPlotPlotEvent.php index abb7a585..4b766845 100644 --- a/src/MyPlot/events/MyPlotPlotEvent.php +++ b/src/MyPlot/events/MyPlotPlotEvent.php @@ -2,21 +2,21 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\event\Event; -class MyPlotPlotEvent extends Event { - protected Plot $plot; +class MyPlotPlotEvent extends Event{ + protected BasePlot $plot; - public function __construct(Plot $plot) { + public function __construct(BasePlot $plot){ $this->plot = $plot; } - public function getPlot() : Plot { + public function getPlot() : BasePlot{ return $this->plot; } - public function setPlot(Plot $plot) : self { + public function setPlot(BasePlot $plot) : self{ $this->plot = $plot; return $this; } diff --git a/src/MyPlot/events/MyPlotPvpEvent.php b/src/MyPlot/events/MyPlotPvpEvent.php index 01c70373..85dfc755 100644 --- a/src/MyPlot/events/MyPlotPvpEvent.php +++ b/src/MyPlot/events/MyPlotPvpEvent.php @@ -2,35 +2,35 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; use pocketmine\event\entity\EntityDamageByEntityEvent; use pocketmine\player\Player; -class MyPlotPvpEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotPvpEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; private Player $attacker; private Player $damaged; private ?EntityDamageByEntityEvent $event; - public function __construct(Plot $plot, Player $attacker, Player $damaged, ?EntityDamageByEntityEvent $event = null) { + public function __construct(BasePlot $plot, Player $attacker, Player $damaged, ?EntityDamageByEntityEvent $event = null){ $this->attacker = $attacker; $this->damaged = $damaged; $this->event = $event; parent::__construct($plot); } - public function getAttacker() : Player { + public function getAttacker() : Player{ return $this->attacker; } - public function getDamaged() : Player { + public function getDamaged() : Player{ return $this->damaged; } - public function getEvent() : ?EntityDamageByEntityEvent { + public function getEvent() : ?EntityDamageByEntityEvent{ return $this->event; } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotResetEvent.php b/src/MyPlot/events/MyPlotResetEvent.php index 86ab7cef..90139456 100644 --- a/src/MyPlot/events/MyPlotResetEvent.php +++ b/src/MyPlot/events/MyPlotResetEvent.php @@ -2,19 +2,22 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; +use MyPlot\plot\SinglePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -class MyPlotResetEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotResetEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; + public function __construct(SinglePlot $plot){ + parent::__construct($plot); + } + /** - * MyPlotClearEvent constructor. - * - * @param Plot $plot + * @return SinglePlot */ - public function __construct(Plot $plot) { - parent::__construct($plot); + public function getPlot() : BasePlot{ + return parent::getPlot(); } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotSaveEvent.php b/src/MyPlot/events/MyPlotSaveEvent.php index d4a0e9e8..46a82fb9 100644 --- a/src/MyPlot/events/MyPlotSaveEvent.php +++ b/src/MyPlot/events/MyPlotSaveEvent.php @@ -2,26 +2,18 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; -use pocketmine\event\Cancellable; -use pocketmine\event\CancellableTrait; +use MyPlot\plot\BasePlot; +use MyPlot\plot\SinglePlot; -class MyPlotSaveEvent extends MyPlotPlotEvent implements Cancellable { - use CancellableTrait; - - public const SQLITE3 = 0; - public const MySQL = 1; - public const JSON = 2; - public const YAML = 3; - public const OTHER = -1; - private int $type; - - public function __construct(int $type, Plot $plot) { - $this->type = $type; +class MyPlotSaveEvent extends MyPlotPlotEvent{ + public function __construct(SinglePlot $plot){ parent::__construct($plot); } - public function getSaveType() : int { - return $this->type; + /** + * @return SinglePlot + */ + public function getPlot() : BasePlot{ + return parent::getPlot(); } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotSettingEvent.php b/src/MyPlot/events/MyPlotSettingEvent.php index b2116784..55f937c4 100644 --- a/src/MyPlot/events/MyPlotSettingEvent.php +++ b/src/MyPlot/events/MyPlotSettingEvent.php @@ -2,26 +2,29 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; +use MyPlot\plot\SinglePlot; use pocketmine\event\Cancellable; use pocketmine\event\CancellableTrait; -class MyPlotSettingEvent extends MyPlotPlotEvent implements Cancellable { +class MyPlotSettingEvent extends MyPlotPlotEvent implements Cancellable{ use CancellableTrait; - private Plot $oldPlot; + private SinglePlot $oldPlot; - public function __construct(Plot $oldPlot, Plot $newPlot) { + public function __construct(SinglePlot $oldPlot, SinglePlot $newPlot){ $this->oldPlot = $oldPlot; parent::__construct($newPlot); } - public function getOldPlot() : Plot { + public function getOldPlot() : SinglePlot{ return $this->oldPlot; } - public function setOldPlot(Plot $oldPlot) : self { - $this->oldPlot = $oldPlot; - return $this; + /** + * @return SinglePlot + */ + public function getPlot() : BasePlot{ + return parent::getPlot(); } } \ No newline at end of file diff --git a/src/MyPlot/events/MyPlotTeleportEvent.php b/src/MyPlot/events/MyPlotTeleportEvent.php index ed4b548c..c5c17bfa 100644 --- a/src/MyPlot/events/MyPlotTeleportEvent.php +++ b/src/MyPlot/events/MyPlotTeleportEvent.php @@ -2,22 +2,22 @@ declare(strict_types=1); namespace MyPlot\events; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; use pocketmine\player\Player; -class MyPlotTeleportEvent extends MyPlotPlayerEnterPlotEvent { +class MyPlotTeleportEvent extends MyPlotPlayerEnterPlotEvent{ private bool $center; - public function __construct(Plot $plot, Player $player, bool $center = false) { + public function __construct(BasePlot $plot, Player $player, bool $center = false){ $this->center = $center; parent::__construct($plot, $player); } - public function toCenter() : bool { + public function toCenter() : bool{ return $this->center; } - public function setToCenter(bool $center) : self { + public function setToCenter(bool $center) : self{ $this->center = $center; return $this; } diff --git a/src/MyPlot/forms/ComplexMyPlotForm.php b/src/MyPlot/forms/ComplexMyPlotForm.php deleted file mode 100644 index b7e77b25..00000000 --- a/src/MyPlot/forms/ComplexMyPlotForm.php +++ /dev/null @@ -1,28 +0,0 @@ -getServer()->dispatchCommand($player, MyPlot::getInstance()->getLanguage()->get("command.name"), true); - } - ); - } - - public function setPlot(?Plot $plot) : void { - $this->plot = $plot; - } - - public function getPlot() : ?Plot { - return $this->plot; - } -} \ No newline at end of file diff --git a/src/MyPlot/forms/MainForm.php b/src/MyPlot/forms/MainForm.php index 47ca1743..ad1dfb40 100644 --- a/src/MyPlot/forms/MainForm.php +++ b/src/MyPlot/forms/MainForm.php @@ -1,55 +1,89 @@ setPlot($plugin->getPlotByPosition($player->getPosition())); - - $elements = []; - foreach($subCommands as $command) { - if(!$command->canUse($player) or $command->getForm($player) === null) - continue; - $name = (new \ReflectionClass($command))->getShortName(); - $name = preg_replace('/([a-z])([A-Z])/s','$1 $2', $name); - if($name === null) - continue; - $length = strlen($name) - strlen("Sub Command"); - $name = substr($name, 0, $length); - $elements[] = new MenuOption(TextFormat::DARK_RED.ucfirst($name)); - $this->link[] = $command; + private array $formNames; + + public function __construct(int $current_page, private Player $player, private MyPlot $owningPlugin, private InternalAPI $internalAPI){ + $owningPlugin = MyPlot::getInstance(); + /** @var Commands $mainCommand */ + $mainCommand = $owningPlugin->getCommand($owningPlugin->getLanguage()->get("command.name")); + foreach($mainCommand->getCommands() as $subCommand){ + if($subCommand->getFormClass() !== null and $subCommand->canUse($player)){ + $name = (new \ReflectionClass($subCommand))->getShortName(); + $name = preg_replace('/([a-z])([A-Z])/s', '$1 $2', $name); + $length = strlen($name) - strlen("SubCommand"); // TODO: validate + $name = substr($name, 0, $length); + $this->formNames[TextFormat::DARK_RED . ucfirst($name)] = $subCommand->getFormClass(); + } } parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", ["Main"]), - "", - $elements, - function(Player $player, int $selectedOption) : void { - $form = $this->link[$selectedOption]->getForm($player); - if($form === null) - return; - $form->setPlot($this->plot); - $player->sendForm($form); - }, - function(Player $player) : void {} + TextFormat::BLACK . MyPlot::getInstance()->getLanguage()->translateString("form.header", ["Main"]), + '', + $current_page ); } + + protected function getPreviousButton() : Button{ + return new Button("<- Go back"); + } + + protected function getNextButton() : Button{ + return new Button("Next Page ->"); + } + + protected function getPages() : int{ + // Returns the maximum number of pages. + // This will alter the visibility of previous and next buttons. + // For example: + // * If we are on page 7 of 7, the "next" button wont be visible + // * If we are on page 6 of 7, the "next" and "previous" button WILL be visible + // * If we are on page 1 of 7, the "previous" button won't be visible + return (int) ceil(count($this->formNames) / self::ENTRIES_PER_PAGE); + } + + protected function populatePage() : void{ + // populate this page with buttons + /** + * @var string $formName + * @var MyPlotForm $formClass + */ + foreach($this->formNames as $formName => $formClass){ + $this->addButton( + new Button($formName), // TODO: icons + \Closure::fromCallable(function() use ($formClass){ + Await::f2c( + function() use ($formClass){ + $plot = yield from $this->internalAPI->generatePlotByPosition($this->player->getPosition()); + $this->player->sendForm(new $formClass($this->owningPlugin, $this->player, $plot)); + } + ); + }) + ); + } + } + + protected function sendPreviousPage(Player $player) : void{ + $player->sendForm(new self($this->current_page - 1, $this->player, $this->owningPlugin, $this->internalAPI)); + } + + protected function sendNextPage(Player $player) : void{ + $player->sendForm(new self($this->current_page + 1, $this->player, $this->owningPlugin, $this->internalAPI)); + } } \ No newline at end of file diff --git a/src/MyPlot/forms/MyPlotForm.php b/src/MyPlot/forms/MyPlotForm.php index c942c662..d64f2932 100644 --- a/src/MyPlot/forms/MyPlotForm.php +++ b/src/MyPlot/forms/MyPlotForm.php @@ -2,9 +2,11 @@ declare(strict_types=1); namespace MyPlot\forms; -use MyPlot\Plot; +use MyPlot\MyPlot; +use MyPlot\plot\BasePlot; use pocketmine\form\Form; +use pocketmine\player\Player; -interface MyPlotForm extends Form { - public function setPlot(?Plot $plot) : void; +interface MyPlotForm extends Form{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot); } \ No newline at end of file diff --git a/src/MyPlot/forms/SimpleMyPlotForm.php b/src/MyPlot/forms/SimpleMyPlotForm.php deleted file mode 100644 index ba98e01c..00000000 --- a/src/MyPlot/forms/SimpleMyPlotForm.php +++ /dev/null @@ -1,28 +0,0 @@ -getServer()->dispatchCommand($player, MyPlot::getInstance()->getLanguage()->get("command.name"), true); - } - ); - } - - public function setPlot(?Plot $plot) : void { - $this->plot = $plot; - } - - public function getPlot() : ?Plot { - return $this->plot; - } -} \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/AddHelperForm.php b/src/MyPlot/forms/subforms/AddHelperForm.php index 47f37dc5..710ae6a1 100644 --- a/src/MyPlot/forms/subforms/AddHelperForm.php +++ b/src/MyPlot/forms/subforms/AddHelperForm.php @@ -1,46 +1,46 @@ helpers, true)) { + if(!in_array("*", $plot->helpers, true)){ $players = ["*"]; - $this->players = ["*"]; + $this->players['*'] = ["*"]; } - foreach($plugin->getServer()->getOnlinePlayers() as $player) { - $players[] = $player->getDisplayName(); - $this->players[] = $player->getName(); + foreach($plugin->getServer()->getOnlinePlayers() as $onlinePlayer){ + $players[] = $onlinePlayer->getDisplayName(); + $this->players[$onlinePlayer->getDisplayName()] = $onlinePlayer->getName(); } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("addhelper.form")]), - [ - new Dropdown( - "0", - $plugin->getLanguage()->get("addhelper.dropdown"), - array_map( - function(string $text) : string { - return TextFormat::DARK_BLUE.$text; - }, $players - ) + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("addhelper.form")])); + $this->addEntry( + new DropdownEntry( + $plugin->getLanguage()->get("addhelper.dropdown"), + ...array_map( + function(string $text) : string{ + return TextFormat::DARK_BLUE . $text; + }, + $players ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("addhelper.name").' "'.$this->players[$response->getInt("0")].'"', true); - } + ), + \Closure::fromCallable(fn(Player $player, DropdownEntry $entry) => $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("addhelper.name") . ' "' . $this->players[$entry->getValue()] . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/BiomeForm.php b/src/MyPlot/forms/subforms/BiomeForm.php index b6e07963..1d022d3a 100644 --- a/src/MyPlot/forms/subforms/BiomeForm.php +++ b/src/MyPlot/forms/subforms/BiomeForm.php @@ -1,38 +1,27 @@ getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("biome.form")])); - $elements = []; - $this->biomeNames = $biomes; - foreach($biomes as $biomeName) { - $elements[] = new MenuOption(TextFormat::DARK_RED.ucfirst(strtolower(str_replace("_", " ", $biomeName)))); // TODO: add images + $biomes = array_keys(BiomeSubCommand::BIOMES); + foreach($biomes as $biomeName){ + $this->addButton( + new Button(TextFormat::DARK_RED . ucfirst(strtolower(str_replace("_", " ", $biomeName)))), // TODO: add images + \Closure::fromCallable(fn(Player $player, int $entry) => $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("biome.name") . ' "' . $biomes[$entry] . '"', true)) + ); } - - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("biome.form")]), - "", - $elements, - function(Player $player, int $selectedOption) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("biome.name").' "'.$this->biomeNames[$selectedOption].'"', true); - } - ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/ClaimForm.php b/src/MyPlot/forms/subforms/ClaimForm.php index 52654f1c..86d5debf 100644 --- a/src/MyPlot/forms/subforms/ClaimForm.php +++ b/src/MyPlot/forms/subforms/ClaimForm.php @@ -1,93 +1,41 @@ setPlot($plot); - if($plot === null) { - $plot = new \stdClass(); - $plot->X = ""; - $plot->Z = ""; - $plot->levelName = $player->getWorld()->getFolderName(); - } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("claim.form")]), - [ - new Input( - "0", - $plugin->getLanguage()->get("claim.formxcoord"), - "2", - (string)$plot->X - ), - new Input( - "1", - $plugin->getLanguage()->get("claim.formzcoord"), - "2", - (string)$plot->Z - ), - new Input( - "2", - $plugin->getLanguage()->get("claim.formworld"), - "world", - $plot->levelName - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - if(is_numeric($response->getString("0")) and is_numeric($response->getString("1")) and $plugin->isLevelLoaded($response->getString("2"))) - $data = MyPlot::getInstance()->getProvider()->getPlot( - $response->getString("2") === '' ? $player->getWorld()->getFolderName() : $response->getString("2"), - (int)$response->getString("0"), - (int)$response->getString("1") - ); - elseif($response->getString("0") === '' or $response->getString("1") === '') { - $data = $this->plot; - }else { - throw new FormValidationException("Unexpected form data returned"); - } +class ClaimForm extends CustomForm implements MyPlotForm{ + public function __construct(Myplot $plugin, Player $player, ?BasePlot $plot){ + if($plot === null) + throw new \InvalidArgumentException("Plot must be a SinglePlot"); - if($data->owner != "") { - if($data->owner === $player->getName()) { - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("claim.yourplot")); - }else{ - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("claim.alreadyclaimed", [$data->owner])); - } - return; - } - $maxPlots = $plugin->getMaxPlotsOfPlayer($player); - $plotsOfPlayer = 0; - foreach($plugin->getPlotLevels() as $level => $settings) { - $level = $plugin->getServer()->getWorldManager()->getWorldByName((string)$level); - if($level !== null and $level->isLoaded()) { - $plotsOfPlayer += count($plugin->getPlotsOfPlayer($player->getName(), $level->getFolderName())); - } - } - if($plotsOfPlayer >= $maxPlots) { - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("claim.maxplots", [$maxPlots])); - return; - } - $economy = $plugin->getEconomyProvider(); - if($economy !== null and !$economy->reduceMoney($player, $data->price)) { - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("claim.nomoney")); - return; - } - if($plugin->claimPlot($data, $player->getName())) { - $player->sendMessage($plugin->getLanguage()->translateString("claim.success")); - }else{ - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("error")); - } - } + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("claim.form")])); + $this->addEntry( + new InputEntry( + $plugin->getLanguage()->get("claim.formxcoord"), + '2', + (string) $plot->X + ), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $plot->X = (int) $entry->getValue()) + ); + $this->addEntry( + new InputEntry( + $plugin->getLanguage()->get("claim.formzcoord"), + '2', + (string) $plot->Z + ), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $plot->Z = (int) $entry->getValue()) + ); + $this->addEntry( + new InputEntry($plugin->getLanguage()->get("claim.formname")), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . ' ' . $plugin->getLanguage()->get("claim.name") . ' ' . $plot->X . ';' . $plot->Z . ($entry->getValue() === '' ?: ' ' . $entry->getValue()), true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/CloneForm.php b/src/MyPlot/forms/subforms/CloneForm.php index a7bcdff0..4bb0ae20 100644 --- a/src/MyPlot/forms/subforms/CloneForm.php +++ b/src/MyPlot/forms/subforms/CloneForm.php @@ -1,103 +1,38 @@ getPlotByPosition($player->getPosition()); - $this->setPlot($plot); - if($plot === null) { - $plot = new \stdClass(); - $plot->X = ""; - $plot->Z = ""; - $plot->levelName = $player->getWorld()->getFolderName(); - } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("clone.form")]), - [ - new Label( - "0", - $plugin->getLanguage()->get("clone.formlabel1") - ), - new Input( - "1", - $plugin->getLanguage()->get("clone.formxcoord"), - "2", - (string)$plot->X - ), - new Input( - "2", - $plugin->getLanguage()->get("clone.formzcoord"), - "-4", - (string)$plot->Z - ), - new Input( - "3", - $plugin->getLanguage()->get("clone.formworld"), - "world", - $plot->levelName - ), - new Label( - "4", - $plugin->getLanguage()->get("clone.formlabel2") - ), - new Input( - "5", - $plugin->getLanguage()->get("clone.formxcoord"), - "2" - ), - new Input( - "6", - $plugin->getLanguage()->get("clone.formzcoord"), - "-4" - ), - new Input( - "7", - $plugin->getLanguage()->get("clone.formworld"), - "world", - $plot->levelName - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - if(is_numeric($response->getString("1")) and is_numeric($response->getString("2")) and is_numeric($response->getString("5")) and is_numeric($response->getString("6"))) { - $originPlot = MyPlot::getInstance()->getProvider()->getPlot($response->getString("3") === '' ? $player->getWorld()->getFolderName() : $response->getString("3"), (int)$response->getString("1"), (int)$response->getString("2")); - $clonedPlot = MyPlot::getInstance()->getProvider()->getPlot($response->getString("7") === '' ? $player->getWorld()->getFolderName() : $response->getString("7"), (int)$response->getString("5"), (int)$response->getString("6")); - }else - throw new FormValidationException("Unexpected form data returned"); + public function __construct(Myplot $plugin, Player $player, ?BasePlot $plot){ + if($plot === null) + throw new \InvalidArgumentException("A plot must be provided"); - if($originPlot->owner !== $player->getName() and !$player->hasPermission("myplot.admin.clone")) { - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("notowner")); - return; - } - if($clonedPlot->owner !== $player->getName() and !$player->hasPermission("myplot.admin.clone")) { - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("notowner")); - return; - } - if(!$plugin->isLevelLoaded($originPlot->levelName)) - throw new FormValidationException("Invalid world given"); - $plotLevel = $plugin->getLevelSettings($originPlot->levelName); - $economy = $plugin->getEconomyProvider(); - if($economy !== null and !$economy->reduceMoney($player, $plotLevel->clonePrice)) { - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("clone.nomoney")); - return; - } - if($plugin->clonePlot($originPlot, $clonedPlot)) { - $player->sendMessage($plugin->getLanguage()->translateString("clone.success", [$clonedPlot->__toString(), $originPlot->__toString()])); - }else{ - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("error")); - } - } + $this->clonedPlot = new BasePlot($plot->levelName, $plot->X, $plot->Z); + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("clone.form")])); + $this->addEntry(new LabelEntry($plugin->getLanguage()->get('clone.formcoordslabel'))); + $this->addEntry( + new InputEntry($plugin->getLanguage()->get('clone.formxcoord'), '2', (string) $plot->X), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $this->clonedPlot->X = (int) $entry->getValue()) + ); + $this->addEntry( + new InputEntry($plugin->getLanguage()->get('clone.formzcoord'), '-4', (string) $plot->Z), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $this->clonedPlot->Z = (int) $entry->getValue()) + ); + $this->addEntry( + new InputEntry($plugin->getLanguage()->get('clone.formworld'), 'world', $plot->levelName), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $this->clonedPlot->levelName = $entry->getValue()) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/DenyPlayerForm.php b/src/MyPlot/forms/subforms/DenyPlayerForm.php index b629da60..37ac6cfb 100644 --- a/src/MyPlot/forms/subforms/DenyPlayerForm.php +++ b/src/MyPlot/forms/subforms/DenyPlayerForm.php @@ -1,44 +1,46 @@ denied, true)) { + if(!in_array("*", $plot->denied, true)){ $players = ["*"]; - $this->players = ["*"]; + $this->players['*'] = ["*"]; } - foreach($plugin->getServer()->getOnlinePlayers() as $player) { - $players[] = $player->getDisplayName(); - $this->players[] = $player->getName(); + foreach($plugin->getServer()->getOnlinePlayers() as $onlinePlayer){ + $players[] = $onlinePlayer->getDisplayName(); + $this->players[$onlinePlayer->getDisplayName()] = $onlinePlayer->getName(); } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("denyplayer.form")]), - [ - new Dropdown( - "0", - $plugin->getLanguage()->get("denyplayer.dropdown"), - array_map(function(string $text) : string { - return TextFormat::DARK_BLUE.$text; - }, $players) + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("denyplayer.form")])); + $this->addEntry( + new DropdownEntry( + $plugin->getLanguage()->get("denyplayer.dropdown"), + ...array_map( + function(string $text) : string{ + return TextFormat::DARK_BLUE . $text; + }, + $players ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("denyplayer.name").' "'.$this->players[$response->getInt("0")].'"', true); - } + ), + \Closure::fromCallable(fn(Player $player, DropdownEntry $entry) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("denyplayer.name") . ' "' . $this->players[$entry->getValue()] . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/FillForm.php b/src/MyPlot/forms/subforms/FillForm.php index 14fc264f..0bce87b8 100644 --- a/src/MyPlot/forms/subforms/FillForm.php +++ b/src/MyPlot/forms/subforms/FillForm.php @@ -1,31 +1,26 @@ getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("fill.form")]), - [ - new Input( - "0", - $plugin->getLanguage()->get("fill.formtitle"), - "1:0", - "1:0" - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("fill.name").' "'.$response->getString("0").'"', true); - } +class FillForm extends CustomForm implements MyPlotForm{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("fill.form")])); + $this->addEntry( + new InputEntry( + $plugin->getLanguage()->get("fill.formtitle"), + "1:0", + "1:0" + ), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("fill.name") . ' "' . $entry->getValue() . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/GenerateForm.php b/src/MyPlot/forms/subforms/GenerateForm.php index b72ae7ae..e121e226 100644 --- a/src/MyPlot/forms/subforms/GenerateForm.php +++ b/src/MyPlot/forms/subforms/GenerateForm.php @@ -1,99 +1,81 @@ getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("generate.form")])); + + static $outputs = []; + $this->addEntry( + new InputEntry($plugin->getLanguage()->get("generate.formworld"), 'plots'), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $outputs[] = $entry->getValue()) + ); + $this->addEntry( + new InputEntry($plugin->getLanguage()->get("generate.formgenerator"), '', 'myplot'), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $outputs[] = $entry->getValue()) + ); - public function __construct() { - $plugin = MyPlot::getInstance(); - $elements = [ - new Input( - "0", - $plugin->getLanguage()->get("generate.formworld"), - "plots" - ), - new Input( - "1", - $plugin->getLanguage()->get("generate.formgenerator"), - "", - "myplot" - ) - ]; - $i = 2; - foreach($plugin->getConfig()->get("DefaultWorld", []) as $key => $value) { - if(is_numeric($value)) { + foreach($plugin->getConfig()->get("DefaultWorld", []) as $key => $value){ + if(is_numeric($value)){ if($value > 0) - $elements[] = new Slider("$i", $key, 1, 4 * (float)$value, 1, (float)$value); + $this->addEntry( + new SliderEntry($key, 1, 4 * $value, 1, $value), + \Closure::fromCallable(fn(Player $player, SliderEntry $entry) => $outputs[] = $entry->getValue()) + ); else - $elements[] = new Slider("$i", $key, 1, 1000, 1, 1.0); - }elseif(is_bool($value)) { - $elements[] = new Toggle("$i", $key, $value); - }elseif(is_string($value)) { - $elements[] = new Input("$i", $key, "", $value); + $this->addEntry( + new SliderEntry($key, 1, 1000, 1, 1), + \Closure::fromCallable(fn(Player $player, SliderEntry $entry) => $outputs[] = $entry->getValue()) + ); + }elseif(is_bool($value)){ + $this->addEntry( + new ToggleEntry($key, $value), + \Closure::fromCallable(fn(Player $player, ToggleEntry $entry) => $outputs[] = $entry->getValue()) + ); + }elseif(is_string($value)){ + $this->addEntry( + new InputEntry($key, '', $value), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $outputs[] = $entry->getValue()) + ); } - $this->keys[] = $key; - $i++; } - $this->keys[] = "teleport"; - $elements[] = new Toggle("$i", $plugin->getLanguage()->get("generate.formteleport"), true); - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("generate.form")]), - $elements, - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $copy = []; - foreach($response->getAll() as $key => $value) { - if(isset($this->keys[((int)$key)-2])) - $copy[$this->keys[((int)$key)-2]] = $value; - else - $copy[] = $value; - } - $data = $copy; - - $world = array_shift($data); - if($player->getServer()->getWorldManager()->isWorldGenerated($world)) { - $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("generate.exists", [$world])); + $this->addEntry( + new ToggleEntry($plugin->getLanguage()->get("generate.formteleport"), true), + \Closure::fromCallable(function(Player $player, ToggleEntry $entry) use ($plugin, $outputs){ + $worldName = array_shift($outputs); + if($player->getServer()->getWorldManager()->isWorldGenerated($worldName)){ + $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("generate.exists", [$worldName])); return; } - $teleport = array_pop($data); - $blockIds = array_slice($data, -5, 5, true); - $blockIds = array_map(function($val) { - if(str_contains($val, ':')) { - $peices = explode(':', $val); - if(defined(BlockLegacyIds::class."::".strtoupper(str_replace(' ', '_', $peices[0])))) - return constant(BlockLegacyIds::class."::".strtoupper(str_replace(' ', '_', $val))).':'.($peices[1] ?? 0); - return $val; - }elseif(is_numeric($val)) - return $val.':0'; - elseif(defined(BlockLegacyIds::class."::".strtoupper(str_replace(' ', '_', $val)))) - return constant(BlockLegacyIds::class."::".strtoupper(str_replace(' ', '_', $val))).':0'; - return $val; - }, $blockIds); - foreach($blockIds as $key => $val) - $data[$key] = $val; + $blockNames = array_slice($outputs, -6, 5, true); // TODO: UPDATE WHEN CONFIG IS UPDATED + $blockNames = array_map(fn(string $blockName) => str_replace(' ', '_', $blockName), $blockNames); + $blockNames = array_filter($blockNames, fn(string $blockName) => StringToItemParser::getInstance()->parse($blockName) instanceof ItemBlock); + $outputs = array_merge($outputs, $blockNames); - if($plugin->generateLevel($world, array_shift($data), $data)) { - if($teleport) - $plugin->teleportPlayerToPlot($player, new Plot($world, 0, 0)); - $player->sendMessage($plugin->getLanguage()->translateString("generate.success", [$world])); + if($plugin->generateLevel($worldName, array_shift($outputs), $outputs)){ + if($entry->getValue() === true) + $plugin->teleportPlayerToPlot($player, new BasePlot($worldName, 0, 0)); + $player->sendMessage($plugin->getLanguage()->translateString("generate.success", [$worldName])); }else{ $player->sendMessage(TextFormat::RED . $plugin->getLanguage()->translateString("generate.error")); } - } + }) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/GiveForm.php b/src/MyPlot/forms/subforms/GiveForm.php index cc8eb7d0..e358d28a 100644 --- a/src/MyPlot/forms/subforms/GiveForm.php +++ b/src/MyPlot/forms/subforms/GiveForm.php @@ -1,37 +1,25 @@ getServer()->getOnlinePlayers() as $player) { - $players[] = $player->getDisplayName(); - $this->players[] = $player->getName(); - } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("give.form")]), - [ - new Dropdown( - "0", - $plugin->getLanguage()->get("give.dropdown"), - $players - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("give.name").' "'.$this->players[$response->getInt("0")].'"', true); - } +class GiveForm extends CustomForm implements MyPlotForm{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("give.form")])); + $this->addEntry( + new DropdownEntry( + $plugin->getLanguage()->get("give.dropdown"), + ...array_map(fn(Player $player) => $player->getDisplayName(), $plugin->getServer()->getOnlinePlayers()) + ), + \Closure::fromCallable(fn(Player $player, DropdownEntry $entry) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("give.name") . ' "' . $entry->getValue() . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/HomeForm.php b/src/MyPlot/forms/subforms/HomeForm.php index 1af20a01..a8f4d2e1 100644 --- a/src/MyPlot/forms/subforms/HomeForm.php +++ b/src/MyPlot/forms/subforms/HomeForm.php @@ -1,31 +1,22 @@ getPlotsOfPlayer($player->getName(), $player->getWorld()->getFolderName()); - $i = 1; - $elements = []; - foreach($plots as $plot) { - $elements[] = new MenuOption(TextFormat::DARK_RED.$i++.") ".$plot->name." ". $plot); - } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("home.form")]), - "", - $elements, - function(Player $player, int $selectedOption) use ($plugin) : void { - // TODO: merge list and home into one form - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("home.name").' "'.($selectedOption+1).'"', true); - } - ); +class HomeForm extends SimpleForm implements MyPlotForm{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("home.form")])); + // TODO: merge list and home into one form + $i = 0; + foreach($plugin->getPlotsOfPlayer($player->getName(), $player->getWorld()->getFolderName()) as $plot) + $this->addButton(new Button(TextFormat::DARK_RED . ++$i . ") " . $plot->name . " " . $plot), \Closure::fromCallable(fn(Player $player, int $data) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("home.name") . ' "' . ($data + 1) . '"', true))); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/InfoForm.php b/src/MyPlot/forms/subforms/InfoForm.php index 4f3c0b24..46d5a3f7 100644 --- a/src/MyPlot/forms/subforms/InfoForm.php +++ b/src/MyPlot/forms/subforms/InfoForm.php @@ -1,65 +1,61 @@ setPlot($plot); +class InfoForm extends CustomForm implements MyPlotForm{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + if(!$plot instanceof SinglePlot) + throw new \InvalidArgumentException("Plot must be a SinglePlot"); + + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("info.form")])); - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("info.form")]), - [ - new Label( - "0", - $plugin->getLanguage()->translateString("info.formcoords", [(string)$this->plot]) - ), - new Label( - "1", - $plugin->getLanguage()->translateString("info.formowner", [TextFormat::BOLD.$this->plot->owner]) - ), - new Label( - "2", - $plugin->getLanguage()->translateString("info.formpname", [TextFormat::BOLD.$this->plot->name]) - ), - new Dropdown( - "3", - $plugin->getLanguage()->get("info.formhelpers"), - count($this->plot->helpers) === 0 ? [TextFormat::DARK_BLUE.$plugin->getLanguage()->get("info.formnohelpers")] : array_map(function(string $text) : string { - return TextFormat::DARK_BLUE.$text; - }, $this->plot->helpers) - ), - new Dropdown( - "4", - $plugin->getLanguage()->get("info.formdenied"), - count($this->plot->denied) === 0 ? [TextFormat::DARK_BLUE.$plugin->getLanguage()->get("info.formnodenied")] : array_map(function(string $text) : string { - return TextFormat::DARK_BLUE.$text; - }, $this->plot->denied) - ), - new Dropdown( - "5", - $plugin->getLanguage()->get("info.formbiome"), - array_map(function(string $text) : string { - return TextFormat::DARK_BLUE.ucfirst(strtolower(str_replace("_", " ", $text))); - }, array_keys(BiomeSubCommand::BIOMES)), - (int)array_search($this->plot->biome, array_keys(BiomeSubCommand::BIOMES), true) - ), - new Label( - "6", - $plugin->getLanguage()->translateString("info.formpvp", [$this->plot->pvp ? "Enabled" : "Disabled"]) // TODO: translations - ) - ], - function(Player $player, CustomFormResponse $response) : void{} - ); + $this->addEntry(new LabelEntry($plugin->getLanguage()->translateString("info.formcoords", [(string) $plot]))); + $this->addEntry(new LabelEntry($plugin->getLanguage()->translateString("info.formowner", [TextFormat::BOLD . $plot->owner]))); + $this->addEntry(new LabelEntry($plugin->getLanguage()->translateString("info.formpname", [TextFormat::BOLD . $plot->name]))); + $this->addEntry(new DropdownEntry( + $plugin->getLanguage()->get("info.formhelpers"), + ...(count($plot->helpers) === 0 ? + [TextFormat::DARK_BLUE . $plugin->getLanguage()->get("info.formnohelpers")] : + array_map( + function(string $text) : string{ + return TextFormat::DARK_BLUE . $text; + }, + $plot->helpers + )) + )); + $this->addEntry(new DropdownEntry( + $plugin->getLanguage()->get("info.formdenied"), + ...(count($plot->denied) === 0 ? + [TextFormat::DARK_BLUE . $plugin->getLanguage()->get("info.formnodenied")] : + array_map( + function(string $text) : string{ + return TextFormat::DARK_BLUE . $text; + }, + $plot->denied + )) + )); + $this->addEntry(new DropdownEntry( + $plugin->getLanguage()->get("info.formbiome"), + ...array_map( + function(string $text) : string{ + return TextFormat::DARK_BLUE . ucfirst(strtolower(str_replace("_", " ", $text))); + }, + array_keys(BiomeSubCommand::BIOMES) + ), + (int) array_search($plot->biome, array_keys(BiomeSubCommand::BIOMES), true) + )); + $this->addEntry(new LabelEntry($plugin->getLanguage()->translateString("info.formpvp", [$plot->pvp ? "Enabled" : "Disabled"]))); // TODO: translations } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/KickForm.php b/src/MyPlot/forms/subforms/KickForm.php index 2f669984..32290411 100644 --- a/src/MyPlot/forms/subforms/KickForm.php +++ b/src/MyPlot/forms/subforms/KickForm.php @@ -1,44 +1,35 @@ setPlot($plot); - $players = []; - foreach($plugin->getServer()->getOnlinePlayers() as $player) { - $plot = $plugin->getPlotByPosition($player->getPosition()); - if($plot === null) - continue; - if($this->plot !== null and !$plot->isSame($this->plot)) - continue; - $players[] = $player->getDisplayName(); - $this->players[] = $player->getName(); - } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("kick.form")]), - [ - new Dropdown( - "0", - $plugin->getLanguage()->get("kick.dropdown"), - $players + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("kick.form")])); + $this->addEntry( + new DropdownEntry( + $plugin->getLanguage()->get("kick.dropdown"), + ...array_map( + fn(Player $player2) => $player2->getDisplayName(), + array_filter( + array_filter( + $plugin->getServer()->getOnlinePlayers(), + fn(Player $player2) => $player2->getWorld()->getFolderName() === $plot->levelName + ), + fn(Player $player2) => $plugin->getPlotFast($player2->getPosition()->x, $player2->getPosition()->z, $plugin->getLevelSettings($player2->getWorld()->getFolderName()))?->isSame($plot) + ) ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("kick.name").' "'.$this->players[$response->getInt("0")].'"', true); - } + ), + \Closure::fromCallable(fn(Player $player, DropdownEntry $entry) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("kick.name") . ' "' . $entry->getValue() . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/NameForm.php b/src/MyPlot/forms/subforms/NameForm.php index 0dad5994..f9f64666 100644 --- a/src/MyPlot/forms/subforms/NameForm.php +++ b/src/MyPlot/forms/subforms/NameForm.php @@ -1,33 +1,30 @@ setPlot($plot); +class NameForm extends CustomForm implements MyPlotForm{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + if(!$plot instanceof SinglePlot) + throw new \InvalidArgumentException("Plot must be a SinglePlot"); - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("name.form")]), - [ - new Input( - "0", - $plugin->getLanguage()->get("name.formtitle"), - $player->getDisplayName()."'s Plot", - $this->plot->name - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("name.name").' "'.$response->getString("0").'"', true); - } + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("name.form")])); + $this->addEntry( + new InputEntry( + $plugin->getLanguage()->get("name.formtitle"), + $player->getDisplayName() . "'s Plot", + $plot->name + ), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("name.name") . ' "' . $entry->getValue() . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/OwnerForm.php b/src/MyPlot/forms/subforms/OwnerForm.php index edc9ed9d..bc98e232 100644 --- a/src/MyPlot/forms/subforms/OwnerForm.php +++ b/src/MyPlot/forms/subforms/OwnerForm.php @@ -1,38 +1,29 @@ getServer()->getOnlinePlayers() as $player) { - $players[] = $player->getDisplayName(); - $this->players[] = $player->getName(); - } - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("setowner.form")]), - [ - new Dropdown( - "0", - $plugin->getLanguage()->get("setowner.dropdown"), - $players + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("setowner.form")])); + $this->addEntry( + new DropdownEntry( + $plugin->getLanguage()->get("setowner.dropdown"), + ...array_map( + fn(Player $player) => $player->getDisplayName(), + $plugin->getServer()->getOnlinePlayers() ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("setowner.name").' "'.$this->players[$response->getInt("0")].'"', true); - } + ), + \Closure::fromCallable(fn(Player $player, DropdownEntry $entry) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("setowner.name") . ' "' . $entry->getValue() . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/RemoveHelperForm.php b/src/MyPlot/forms/subforms/RemoveHelperForm.php index 96bf89f8..00af7758 100644 --- a/src/MyPlot/forms/subforms/RemoveHelperForm.php +++ b/src/MyPlot/forms/subforms/RemoveHelperForm.php @@ -1,35 +1,31 @@ setPlot($plot); - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("removehelper.form")]), - [ - new Dropdown( - "0", - $plugin->getLanguage()->get("removehelper.dropdown"), - count($this->plot->helpers) < 1 ? [TextFormat::DARK_BLUE.$plugin->getLanguage()->get("removehelper.formnohelpers")] : array_map(function(string $text) { - return TextFormat::DARK_BLUE.$text; - }, $this->plot->helpers) - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - if(count($this->plot->helpers) < 1) - return; - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("removehelper.name").' "'.$this->plot->helpers[$response->getInt("0")].'"', true); - } +class RemoveHelperForm extends CustomForm implements MyPlotForm{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + if(!$plot instanceof SinglePlot) + throw new \InvalidArgumentException("Plot must be a SinglePlot"); + + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("removehelper.form")])); + $this->addEntry( + new DropdownEntry( + $plugin->getLanguage()->get("removehelper.dropdown"), + ...(count($plot->helpers) < 1 ? [TextFormat::DARK_BLUE . $plugin->getLanguage()->get("removehelper.formnohelpers")] : array_map(function(string $text){ + return TextFormat::DARK_BLUE . $text; + }, $plot->helpers)) + ), + \Closure::fromCallable(fn(Player $player, DropdownEntry $entry) => $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("removehelper.name") . ' "' . $entry->getValue() . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/UndenyPlayerForm.php b/src/MyPlot/forms/subforms/UndenyPlayerForm.php index 389224cb..5f980dd4 100644 --- a/src/MyPlot/forms/subforms/UndenyPlayerForm.php +++ b/src/MyPlot/forms/subforms/UndenyPlayerForm.php @@ -1,35 +1,31 @@ setPlot($plot); - parent::__construct( - TextFormat::BLACK.$plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("undenyplayer.form")]), - [ - new Dropdown( - "0", - $plugin->getLanguage()->get("undenyplayer.dropdown"), - count($this->plot->denied) < 1 ? [TextFormat::DARK_BLUE.$plugin->getLanguage()->get("undenyplayer.formnodenied")] : array_map(function(string $text) { - return TextFormat::DARK_BLUE.$text; - }, $this->plot->denied) - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - if(count($this->plot->denied) < 1) - return; - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("undenyplayer.name").' "'.$this->plot->denied[$response->getInt("0")].'"', true); - } +class UndenyPlayerForm extends CustomForm implements MyPlotForm{ + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + if(!$plot instanceof SinglePlot) + throw new \InvalidArgumentException("Plot must be a SinglePlot"); + + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("undenyplayer.form")])); + $this->addEntry( + new DropdownEntry( + $plugin->getLanguage()->get("undenyplayer.dropdown"), + ...(count($plot->denied) < 1 ? [TextFormat::DARK_BLUE . $plugin->getLanguage()->get("undenyplayer.formnodenied")] : array_map(function(string $text){ + return TextFormat::DARK_BLUE . $text; + }, $plot->denied)) + ), + \Closure::fromCallable(fn(Player $player, DropdownEntry $entry) => $plugin->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("undenyplayer.name") . ' "' . $entry->getValue() . '"', true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/forms/subforms/WarpForm.php b/src/MyPlot/forms/subforms/WarpForm.php index d8bfcfdd..6160c060 100644 --- a/src/MyPlot/forms/subforms/WarpForm.php +++ b/src/MyPlot/forms/subforms/WarpForm.php @@ -1,55 +1,41 @@ getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("warp.form")]), - [ - new Input( - "0", - $plugin->getLanguage()->get("warp.formxcoord"), - "2" - ), - new Input( - "1", - $plugin->getLanguage()->get("warp.formzcoord"), - "-4" - ), - new Input( - "2", - $plugin->getLanguage()->get("warp.formworld"), - "world", - $player->getWorld()->getFolderName() - ) - ], - function(Player $player, CustomFormResponse $response) use ($plugin) : void { - if(is_numeric($response->getString("0")) and is_numeric($response->getString("1")) and $plugin->isLevelLoaded($response->getString("2"))) - $data =[ - (int)$response->getString("0"), - (int)$response->getString("1"), - $response->getString("2") === '' ? $player->getWorld()->getFolderName() : $response->getString("2") - ]; - elseif($response->getString("0") === '' and $response->getString("1") === '') { - $player->sendForm(new self($player)); - throw new FormValidationException("Invalid form data returned"); - }else - throw new FormValidationException("Unexpected form data returned"); +class WarpForm extends CustomForm implements MyPlotForm{ - $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name")." ".$plugin->getLanguage()->get("warp.name")." $data[0];$data[1] $data[2]", true); - } + public function __construct(MyPlot $plugin, Player $player, ?BasePlot $plot){ + parent::__construct(TextFormat::BLACK . $plugin->getLanguage()->translateString("form.header", [$plugin->getLanguage()->get("warp.form")])); + $this->addEntry( + new InputEntry( + $plugin->getLanguage()->get("warp.formxcoord"), + "2" + ), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $plot->X = (int) $entry->getValue()) + ); + $this->addEntry( + new InputEntry( + $plugin->getLanguage()->get("warp.formzcoord"), + "-4" + ), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $plot->Z = (int) $entry->getValue()) + ); + $this->addEntry( + new InputEntry( + $plugin->getLanguage()->get("warp.formworld"), + $player->getWorld()->getFolderName() + ), + \Closure::fromCallable(fn(Player $player, InputEntry $entry) => $player->getServer()->dispatchCommand($player, $plugin->getLanguage()->get("command.name") . " " . $plugin->getLanguage()->get("warp.name") . " $plot->X;$plot->Z {$entry->getValue()}", true)) ); } } \ No newline at end of file diff --git a/src/MyPlot/plot/BasePlot.php b/src/MyPlot/plot/BasePlot.php index 8dc0813d..4c8f0b71 100644 --- a/src/MyPlot/plot/BasePlot.php +++ b/src/MyPlot/plot/BasePlot.php @@ -4,24 +4,24 @@ use pocketmine\math\Facing; -class BasePlot { - public function __construct(public string $levelName, public int $X, public int $Z) {} +class BasePlot{ + public function __construct(public string $levelName, public int $X, public int $Z){ } - public function isSame(BasePlot $plot) : bool { + public function isSame(BasePlot $plot) : bool{ return $this->levelName === $plot->levelName and $this->X === $plot->X and $this->Z === $plot->Z; } - public function getSide(int $side, int $step = 1) : BasePlot { - return match($side) { + public function getSide(int $side, int $step = 1) : BasePlot{ + return match ($side) { Facing::NORTH => new BasePlot($this->levelName, $this->X, $this->Z - $step), Facing::SOUTH => new BasePlot($this->levelName, $this->X, $this->Z + $step), Facing::EAST => new BasePlot($this->levelName, $this->X + $step, $this->Z), Facing::WEST => new BasePlot($this->levelName, $this->X - $step, $this->Z), - default => throw new \InvalidArgumentException("Invalid side: ".Facing::toString($side)) + default => throw new \InvalidArgumentException("Invalid side: " . Facing::toString($side)) }; } - public function __toString() : string { - return "(" . $this->X . ";" . $this->Z . ")"; + public function __toString() : string{ + return "($this->X;$this->Z)"; } } \ No newline at end of file diff --git a/src/MyPlot/plot/MergedPlot.php b/src/MyPlot/plot/MergedPlot.php index 1ff7df12..39c0116c 100644 --- a/src/MyPlot/plot/MergedPlot.php +++ b/src/MyPlot/plot/MergedPlot.php @@ -55,19 +55,19 @@ public static function fromSingle(SinglePlot $plot, int $xWidth, int $zWidth) : * * @return bool */ - public function isSame(BasePlot $plot) : bool { + public function isSame(BasePlot $plot) : bool{ if(parent::isSame($plot)) return true; return ( - new AxisAlignedBB( - $this->X, - 0, - $this->Z, - $this->X + $this->xWidth, - 1, - $this->Z + $this->zWidth - ) + new AxisAlignedBB( + $this->X, + 0, + $this->Z, + $this->X + $this->xWidth, + 1, + $this->Z + $this->zWidth + ) )->isVectorInXZ(new Vector3($plot->X, 0, $plot->Z)); } diff --git a/src/MyPlot/plot/SinglePlot.php b/src/MyPlot/plot/SinglePlot.php index e664ac83..39f13666 100644 --- a/src/MyPlot/plot/SinglePlot.php +++ b/src/MyPlot/plot/SinglePlot.php @@ -4,7 +4,7 @@ use MyPlot\MyPlot; -class SinglePlot extends BasePlot { +class SinglePlot extends BasePlot{ public bool $pvp = true; public function __construct(public string $levelName, public int $X, public int $Z, public string $name = "", public string $owner = "", public array $helpers = [], public array $denied = [], public string $biome = "PLAINS", ?bool $pvp = null, public int $price = -1){ @@ -22,7 +22,7 @@ public function __construct(public string $levelName, public int $X, public int $this->price = 0; } - public static function fromBase(BasePlot $plot, string $name, string $owner, array $helpers, array $denied, string $biome, ?bool $pvp, int $price) : SinglePlot{ + public static function fromBase(BasePlot $plot, string $name = '', string $owner = '', array $helpers = [], array $denied = [], string $biome = "PLAINS", ?bool $pvp = null, int $price = -1) : SinglePlot{ return new SinglePlot( $plot->levelName, $plot->X, @@ -55,8 +55,8 @@ public function isHelper(string $username) : bool{ * * @return bool */ - public function addHelper(string $username) : bool { - if(!$this->isHelper($username)) { + public function addHelper(string $username) : bool{ + if(!$this->isHelper($username)){ $this->unDenyPlayer($username); $this->helpers[] = $username; return true; @@ -71,12 +71,12 @@ public function addHelper(string $username) : bool { * * @return bool */ - public function removeHelper(string $username) : bool { - if(!$this->isHelper($username)) { + public function removeHelper(string $username) : bool{ + if(!$this->isHelper($username)){ return false; } $key = array_search($username, $this->helpers, true); - if($key === false) { + if($key === false){ return false; } unset($this->helpers[$key]); @@ -90,7 +90,7 @@ public function removeHelper(string $username) : bool { * * @return bool */ - public function isDenied(string $username) : bool { + public function isDenied(string $username) : bool{ return in_array($username, $this->denied, true); } @@ -101,8 +101,8 @@ public function isDenied(string $username) : bool { * * @return bool */ - public function denyPlayer(string $username) : bool { - if(!$this->isDenied($username)) { + public function denyPlayer(string $username) : bool{ + if(!$this->isDenied($username)){ $this->removeHelper($username); $this->denied[] = $username; return true; @@ -117,12 +117,12 @@ public function denyPlayer(string $username) : bool { * * @return bool */ - public function unDenyPlayer(string $username) : bool { - if(!$this->isDenied($username)) { + public function unDenyPlayer(string $username) : bool{ + if(!$this->isDenied($username)){ return false; } $key = array_search($username, $this->denied, true); - if($key === false) { + if($key === false){ return false; } unset($this->denied[$key]); diff --git a/src/MyPlot/provider/DataProvider.php b/src/MyPlot/provider/DataProvider.php index 1aaddf9c..dd780d7c 100644 --- a/src/MyPlot/provider/DataProvider.php +++ b/src/MyPlot/provider/DataProvider.php @@ -2,26 +2,47 @@ declare(strict_types=1); namespace MyPlot\provider; +use MyPlot\InternalAPI; use MyPlot\MyPlot; use MyPlot\plot\BasePlot; use MyPlot\plot\MergedPlot; use MyPlot\plot\SinglePlot; use poggit\libasynql\DataConnector; use poggit\libasynql\libasynql; +use poggit\libasynql\SqlThread; +use SOFe\AwaitGenerator\Await; -final class DataProvider { +final class DataProvider{ /** @var BasePlot[] $cache */ private array $cache = []; private int $cacheSize; private DataConnector $database; - public function __construct(private MyPlot $plugin) { + /** @noinspection PhpVoidFunctionResultUsedInspection */ + public function __construct(private MyPlot $plugin, InternalAPI $internalAPI){ $this->database = libasynql::create($plugin, $plugin->getConfig()->get("Database"), [ 'sqlite' => 'sqlite.sql', 'mysql' => 'mysql.sql', - ]); - $this->cacheSize = $plugin->getConfig()->get("PlotCacheSize", 2048); + ], true); + $this->database->executeGeneric('myplot.init.plots'); + $this->database->executeGeneric('myplot.init.mergedPlots'); + $this->database->executeSelect( + 'myplot.test.table', + ['tableName' => 'plotsV2'], + fn(array $rows) => $rows[0]['tables'] === 0 ?: $this->database->executeMulti('myplot.convert.tables', [], SqlThread::MODE_CHANGE) + ); + $this->cacheSize = $plugin->getConfig()->get("PlotCacheSize", 2500); + $maxPlotCoord = floor(sqrt($this->cacheSize) / 2); + foreach($internalAPI->getAllLevelSettings() as $levelName => $settings){ + for($x = -$maxPlotCoord; $x < $maxPlotCoord; ++$x){ + for($z = -$maxPlotCoord; $z < $maxPlotCoord; ++$z){ + Await::g2c( + $this->getMergedPlot(new BasePlot($levelName, $x, $z)) + ); + } + } + } } private function cachePlot(BasePlot $plot) : void{ @@ -52,15 +73,15 @@ private function cachePlot(BasePlot $plot) : void{ } } - private function getPlotFromCache(string $levelName, int $X, int $Z) : ?BasePlot{ + public function getPlotFromCache(string $levelName, int $X, int $Z) : BasePlot{ if($this->cacheSize > 0){ $key = $levelName . ';' . $X . ';' . $Z; if(isset($this->cache[$key])){ - #$this->plugin->getLogger()->debug("Plot {$X};{$Z} was loaded from the cache"); - return $this->cache[$key]; + $this->plugin->getLogger()->debug("Plot {$X};{$Z} was loaded from the cache"); + return $this->cache[$key] ?? new BasePlot($levelName, $X, $Z); } } - return null; + return new BasePlot($levelName, $X, $Z); } /** @@ -69,7 +90,7 @@ private function getPlotFromCache(string $levelName, int $X, int $Z) : ?BasePlot * @return \Generator */ public function savePlot(SinglePlot $plot) : \Generator{ - [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.plot', [ + [$insertId, $affectedRows] = yield from $this->database->asyncInsert('myplot.add.plot', [ 'level' => $plot->levelName, 'X' => $plot->X, 'Z' => $plot->Z, @@ -97,7 +118,7 @@ public function deletePlot(BasePlot $plot) : \Generator{ if($plot instanceof MergedPlot){ $plotLevel = $this->plugin->getLevelSettings($plot->levelName); - $changedRows = yield $this->database->asyncChange('myplot.remove.merge.by-xz', [ + $changedRows = yield from $this->database->asyncChange('myplot.remove.merge.by-xz', [ 'level' => $plot->levelName, 'X' => $plot->X, 'Z' => $plot->Z, @@ -106,7 +127,7 @@ public function deletePlot(BasePlot $plot) : \Generator{ ]); $this->cachePlot(new MergedPlot($plot->levelName, $plot->X, $plot->Z, $plot->xWidth, $plot->zWidth, pvp: !$plotLevel->restrictPVP, price: $plotLevel->claimPrice)); }else{ - $changedRows = yield $this->database->asyncChange('myplot.remove.plot.by-xz', [ + $changedRows = yield from $this->database->asyncChange('myplot.remove.plot.by-xz', [ 'level' => $plot->levelName, 'X' => $plot->X, 'Z' => $plot->Z, @@ -124,22 +145,22 @@ public function deletePlot(BasePlot $plot) : \Generator{ * @param int $X * @param int $Z * - * @return \Generator + * @return \Generator */ public function getPlot(string $levelName, int $X, int $Z) : \Generator{ $plot = $this->getPlotFromCache($levelName, $X, $Z); if($plot instanceof SinglePlot){ return $plot; } - $row = yield $this->database->asyncSelect('myplot.get.plot.by-xz', [ + $row = (yield from $this->database->asyncSelect('myplot.get.plot.by-xz', [ 'level' => $levelName, 'X' => $X, 'Z' => $Z - ]); + ]))[0]; if(count($row) < 1) - return null; + return $plot; - return new SinglePlot($levelName, $X, $Z, $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], $row['pvp'], $row['price']); + return new SinglePlot($levelName, $X, $Z, $row['name'], $row['owner'], explode(",", $row['helpers']), explode(",", $row['denied']), $row['biome'], (bool) $row['pvp'], $row['price']); } /** @@ -149,19 +170,19 @@ public function getPlot(string $levelName, int $X, int $Z) : \Generator{ * @return \Generator> */ public function getPlotsByOwner(string $owner, string $levelName = "") : \Generator{ - if($levelName !== null){ - $rows = yield $this->database->asyncSelect('myplot.get.all-plots.by-owner-and-level', [ + if($levelName !== ''){ + $rows = yield from $this->database->asyncSelect('myplot.get.all-plots.by-owner-and-level', [ 'owner' => $owner, 'level' => $levelName, ]); }else{ - $rows = yield $this->database->asyncSelect('myplot.get.all-plots.by-owner', [ + $rows = yield from $this->database->asyncSelect('myplot.get.all-plots.by-owner', [ 'owner' => $owner, ]); } $plots = []; foreach($rows as $row){ - $plots[] = yield $this->getMergedPlot(new BasePlot($row['level'], $row['X'], $row['Z'])); + $plots[] = yield from $this->getMergedPlot(new BasePlot($row['level'], $row['X'], $row['Z'])); } return $plots; } @@ -174,7 +195,7 @@ public function getPlotsByOwner(string $owner, string $levelName = "") : \Genera */ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : \Generator{ for($i = 0; $limitXZ <= 0 or $i < $limitXZ; $i++){ - $rows = yield $this->database->asyncSelect('myplot.get.highest-existing.by-interval', [ + $rows = yield from $this->database->asyncSelect('myplot.get.highest-existing.by-interval', [ 'level' => $levelName, 'number' => $i, ]); @@ -196,12 +217,12 @@ public function getNextFreePlot(string $levelName, int $limitXZ = 0) : \Generato } /** - * @param SinglePlot $base + * @param MergedPlot $base * @param BasePlot ...$plots * * @return \Generator */ - public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ + public function mergePlots(MergedPlot $base, BasePlot ...$plots) : \Generator{ $minX = 0; $minZ = 0; foreach($plots as $plot){ @@ -214,7 +235,7 @@ public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ $ret = true; foreach($plots as $plot){ if($minX !== $base->X and $minZ !== $base->Z){ - $affectedRows = yield $this->database->asyncChange('myplot.remove.merge-entry', [ + $affectedRows = yield from $this->database->asyncChange('myplot.remove.merge-entry', [ 'level' => $plot->levelName, 'originX' => $base->X, 'originZ' => $base->Z, @@ -226,7 +247,7 @@ public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ $ret = false; } } - [$insertId, $affectedRows] = yield $this->database->asyncInsert('myplot.add.merge', [ + [$insertId, $affectedRows] = yield from $this->database->asyncInsert('myplot.add.merge', [ 'level' => $plot->levelName, 'originX' => $minX, 'originZ' => $minZ, @@ -244,26 +265,26 @@ public function mergePlots(SinglePlot $base, BasePlot ...$plots) : \Generator{ /** * @param BasePlot $plot * - * @return \Generator + * @return \Generator */ public function getMergedPlot(BasePlot $plot) : \Generator{ $plot = $this->getPlotFromCache($plot->levelName, $plot->X, $plot->Z); if($plot instanceof MergedPlot) return $plot; - $rows = yield $this->database->asyncSelect('myplot.get.merge-plots.by-origin', [ + $rows = yield from $this->database->asyncSelect('myplot.get.merge-plots.by-origin', [ 'level' => $plot->levelName, 'originX' => $plot->X, 'originZ' => $plot->Z ]); if(count($rows) < 1){ - $rows = yield $this->database->asyncSelect('myplot.get.merge-plots.by-merged', [ + $rows = yield from $this->database->asyncSelect('myplot.get.merge-plots.by-merged', [ 'level' => $plot->levelName, 'mergedX' => $plot->X, 'mergedZ' => $plot->Z ]); if(count($rows) < 1){ - return yield $this->getPlot($plot->levelName, $plot->X, $plot->Z); + return yield from $this->getPlot($plot->levelName, $plot->X, $plot->Z); } } $highestX = $highestZ = $lowestX = $lowestZ = 0; @@ -314,13 +335,13 @@ private static function findEmptyPlotSquared(int $a, int $b, array $plots) : ?ar if(!isset($plots[$b][-$a])) return [$b, -$a]; } - if($b !== 0) { + if($b !== 0){ if(!isset($plots[-$b][$a])) return [-$b, $a]; if(!isset($plots[$a][-$b])) return [$a, -$b]; } - if(($a | $b) === 0) { + if(($a | $b) === 0){ if(!isset($plots[-$a][-$b])) return [-$a, -$b]; if(!isset($plots[-$b][-$a])) diff --git a/src/MyPlot/provider/InternalBedrockEconomyProvider.php b/src/MyPlot/provider/InternalBedrockEconomyProvider.php new file mode 100644 index 00000000..53a58956 --- /dev/null +++ b/src/MyPlot/provider/InternalBedrockEconomyProvider.php @@ -0,0 +1,75 @@ +api->subtractFromPlayerBalance( + $player->getName(), + $amount, + ClosureContext::create( + static function(bool $response, callable $stopRunning, ?string $error) use ($onSuccess, $onError) : void{ + $error === null ?: $onError($error); + $onSuccess($response); + } + ), + 'MyPlot' + ); + return yield Await::ONCE; + } + + /** + * @inheritDoc + */ + public function addMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator{ + $onSuccess = yield Await::RESOLVE; + $onError = yield Await::REJECT; + $this->api->addToPlayerBalance( + $player->getName(), + $amount, + ClosureContext::create( + static function(bool $response, callable $stopRunning, ?string $error) use ($onSuccess, $onError) : void{ + $error === null ?: $onError($error); + $onSuccess($response); + } + ), + 'MyPlot' + ); + return yield Await::ONCE; + } + + /** + * @inheritDoc + */ + public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = "Unknown") : \Generator{ + $onSuccess = yield Await::RESOLVE; + $onError = yield Await::REJECT; + $this->api->transferFromPlayerBalance( + $player1->getName(), + $player2->getName(), + $amount, + ClosureContext::create( + static function(bool $response, callable $stopRunning, ?string $error) use ($onSuccess, $onError) : void{ + $error === null ?: $onError($error); + $onSuccess($response); + } + ) + // no issuer for some reason + ); + return yield Await::ONCE; + } +} \ No newline at end of file diff --git a/src/MyPlot/provider/InternalCapitalProvider.php b/src/MyPlot/provider/InternalCapitalProvider.php index f67d2e66..1da921b5 100644 --- a/src/MyPlot/provider/InternalCapitalProvider.php +++ b/src/MyPlot/provider/InternalCapitalProvider.php @@ -21,7 +21,7 @@ public function __construct(){ /** * @inheritDoc */ - public function reduceMoney(Player $player, int $amount, string $reason = 'Unknown') : \Generator { + public function reduceMoney(Player $player, int $amount, string $reason = 'Unknown') : \Generator{ /** @var Capital $api */ $api = yield from Capital::get(MainClass::$context); yield from $api->takeMoney( @@ -36,7 +36,7 @@ public function reduceMoney(Player $player, int $amount, string $reason = 'Unkno /** * @inheritDoc */ - public function addMoney(Player $player, int $amount, string $reason = 'Unknown') : \Generator { + public function addMoney(Player $player, int $amount, string $reason = 'Unknown') : \Generator{ /** @var Capital $api */ $api = yield from Capital::get(MainClass::$context); yield from $api->addMoney( @@ -51,7 +51,7 @@ public function addMoney(Player $player, int $amount, string $reason = 'Unknown' /** * @inheritDoc */ - public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = 'Unknown') : \Generator { + public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = 'Unknown') : \Generator{ /** @var Capital $api */ $api = yield from Capital::get(MainClass::$context); yield from $api->pay( diff --git a/src/MyPlot/provider/InternalEconomySProvider.php b/src/MyPlot/provider/InternalEconomySProvider.php index 78d5a351..02396bd4 100644 --- a/src/MyPlot/provider/InternalEconomySProvider.php +++ b/src/MyPlot/provider/InternalEconomySProvider.php @@ -19,7 +19,7 @@ public function reduceMoney(Player $player, int $amount, string $reason = "Unkno $amount = -$amount; } $ret = $this->plugin->reduceMoney($player, $amount, false, "MyPlot"); - if($ret === EconomyAPI::RET_SUCCESS) { + if($ret === EconomyAPI::RET_SUCCESS){ $this->plugin->getLogger()->debug("MyPlot Reduced money of " . $player->getName()); return true; } @@ -29,13 +29,13 @@ public function reduceMoney(Player $player, int $amount, string $reason = "Unkno /** * @inheritDoc */ - public function addMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator { + public function addMoney(Player $player, int $amount, string $reason = "Unknown") : \Generator{ 0 && yield; - if($amount === 0) { + if($amount === 0){ return true; } $ret = $this->plugin->addMoney($player, $amount, false, "MyPlot"); - if($ret === EconomyAPI::RET_SUCCESS) { + if($ret === EconomyAPI::RET_SUCCESS){ return true; } return false; @@ -44,17 +44,17 @@ public function addMoney(Player $player, int $amount, string $reason = "Unknown" /** * @inheritDoc */ - public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = "Unknown") : \Generator { + public function transactMoney(Player $player1, Player $player2, int $amount, string $reason = "Unknown") : \Generator{ 0 && yield; if($amount < 1){ return true; } $ret = $this->plugin->reduceMoney($player1, $amount, true, "MyPlot"); - if($ret !== EconomyAPI::RET_SUCCESS) { + if($ret !== EconomyAPI::RET_SUCCESS){ return false; } $ret = $this->plugin->addMoney($player2, $amount, true, "MyPlot"); - if($ret !== EconomyAPI::RET_SUCCESS) { + if($ret !== EconomyAPI::RET_SUCCESS){ return false; } return true; diff --git a/src/MyPlot/subcommand/AddHelperSubCommand.php b/src/MyPlot/subcommand/AddHelperSubCommand.php index e66b1530..1f10edd0 100644 --- a/src/MyPlot/subcommand/AddHelperSubCommand.php +++ b/src/MyPlot/subcommand/AddHelperSubCommand.php @@ -1,5 +1,6 @@ hasPermission("myplot.command.addhelper"); +class AddHelperSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.addhelper")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -28,7 +38,7 @@ function() use ($sender, $args) : \Generator{ return; } $helperName = $args[0]; - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -40,7 +50,7 @@ function() use ($sender, $args) : \Generator{ $helper = $this->plugin->getServer()->getPlayerByPrefix($helperName); if($helper === null) $helper = $this->plugin->getServer()->getOfflinePlayer($helperName); - if(yield $this->internalAPI->generateAddPlotHelper($plot, $helper->getName())){ + if(yield from $this->internalAPI->generateAddPlotHelper($plot, $helper->getName())){ $sender->sendMessage($this->translateString("addhelper.success", [$helper->getName()])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/AutoSubCommand.php b/src/MyPlot/subcommand/AutoSubCommand.php index 3be53bc9..ee62c50e 100644 --- a/src/MyPlot/subcommand/AutoSubCommand.php +++ b/src/MyPlot/subcommand/AutoSubCommand.php @@ -1,5 +1,6 @@ hasPermission("myplot.command.auto"); +class AutoSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + return $sender->hasPermission("myplot.command.auto") and $sender instanceof Player; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -27,12 +27,12 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("auto.notplotworld")); return; } - $plot = yield $this->internalAPI->generateNextFreePlot($levelName, 0); + $plot = yield from $this->internalAPI->generateNextFreePlot($levelName, 0); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("auto.noplots")); return; } - if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, true)){ + if($this->internalAPI->teleportPlayerToPlot($sender, $plot, true)){ $sender->sendMessage($this->translateString("auto.success", [$plot->X, $plot->Z])); $cmd = new ClaimSubCommand($this->plugin, $this->internalAPI, "claim"); if(isset($args[0]) and strtolower($args[0]) === "true" and $cmd->canUse($sender)) diff --git a/src/MyPlot/subcommand/BiomeSubCommand.php b/src/MyPlot/subcommand/BiomeSubCommand.php index 40a99659..93a7679a 100644 --- a/src/MyPlot/subcommand/BiomeSubCommand.php +++ b/src/MyPlot/subcommand/BiomeSubCommand.php @@ -1,5 +1,6 @@ BiomeIds::PLAINS, "DESERT" => BiomeIds::DESERT, "MOUNTAINS" => BiomeIds::ICE_MOUNTAINS, "FOREST" => BiomeIds::FOREST, "TAIGA" => BiomeIds::TAIGA, "SWAMP" => BiomeIds::SWAMPLAND, "NETHER" => BiomeIds::HELL, "HELL" => BiomeIds::HELL, "ICE_PLAINS" => BiomeIds::ICE_PLAINS]; +class BiomeSubCommand extends SubCommand{ + public const BIOMES = ["PLAINS" => BiomeIds::PLAINS, "DESERT" => BiomeIds::DESERT, "MOUNTAINS" => BiomeIds::ICE_MOUNTAINS, "FOREST" => BiomeIds::FOREST, "TAIGA" => BiomeIds::TAIGA, "SWAMP" => BiomeIds::SWAMPLAND, "NETHER" => BiomeIds::HELL, "HELL" => BiomeIds::HELL, "ICE_PLAINS" => BiomeIds::ICE_PLAINS]; + + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.biome")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($pos->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } - public function canUse(CommandSender $sender) : bool { - return ($sender instanceof Player) and $sender->hasPermission("myplot.command.biome"); + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -36,7 +47,7 @@ function() use ($sender, $args) : \Generator{ if($player === null) return; $biome = strtoupper($args[0]); - $plot = yield $this->internalAPI->generatePlotByPosition($player->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($player->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -65,7 +76,7 @@ function() use ($sender, $args) : \Generator{ } $biome = BiomeRegistry::getInstance()->getBiome(constant(BiomeIds::class . "::" . $biome)); } - if(yield $this->internalAPI->generatePlotBiome($plot, $biome)){ + if(yield from $this->internalAPI->generatePlotBiome($plot, $biome)){ $sender->sendMessage($this->translateString("biome.success", [$biome->getName()])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/BuySubCommand.php b/src/MyPlot/subcommand/BuySubCommand.php index 36f49cbd..9974052b 100644 --- a/src/MyPlot/subcommand/BuySubCommand.php +++ b/src/MyPlot/subcommand/BuySubCommand.php @@ -1,5 +1,6 @@ hasPermission("myplot.command.buy"); +class BuySubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.buy")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -28,7 +39,7 @@ function() use ($sender, $args) : \Generator{ $command->execute($sender, []); return; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -42,7 +53,7 @@ function() use ($sender, $args) : \Generator{ return; } $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); - if(count(yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), null)) >= $maxPlots){ + if(count(yield from $this->internalAPI->generatePlotsOfPlayer($sender->getName(), null)) >= $maxPlots){ $sender->sendMessage(TextFormat::RED . $this->translateString("claim.maxplots", [$maxPlots])); return; } @@ -52,7 +63,7 @@ function() use ($sender, $args) : \Generator{ return; } $oldOwner = $this->plugin->getServer()->getPlayerExact($plot->owner); - if(yield $this->internalAPI->generateBuyPlot($plot, $sender)){ + if(yield from $this->internalAPI->generateBuyPlot($plot, $sender)){ $sender->sendMessage($this->translateString("buy.success", ["$plot->X;$plot->Z", $price])); $oldOwner?->sendMessage($this->translateString("buy.sold", [$sender->getName(), "$plot->X;$plot->Z", $price])); // TODO: queue messages for sending when player rejoins }else{ diff --git a/src/MyPlot/subcommand/ClaimSubCommand.php b/src/MyPlot/subcommand/ClaimSubCommand.php index aa3142bc..b7129e1e 100644 --- a/src/MyPlot/subcommand/ClaimSubCommand.php +++ b/src/MyPlot/subcommand/ClaimSubCommand.php @@ -1,21 +1,23 @@ hasPermission("myplot.command.claim"); +class ClaimSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + return $sender->hasPermission("myplot.command.claim") and $sender instanceof Player; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -23,16 +25,48 @@ public function canUse(CommandSender $sender) : bool { public function execute(CommandSender $sender, array $args) : bool{ Await::f2c( function() use ($sender, $args) : \Generator{ + $pos = $sender->getPosition(); + $x = $pos->x; + $z = $pos->z; + $levelName = $sender->getWorld()->getFolderName(); + $plot = $this->internalAPI->getPlotFast($x, $z, $this->internalAPI->getLevelSettings($levelName)); + $name = ""; - if(isset($args[0])){ - $name = $args[0]; + switch(count($args)){ + case 1: + if(str_contains($args[0], ';')){ + $coords = explode(';', $args[0]); + if(count($coords) !== 2 or !is_numeric($coords[0]) or !is_numeric($coords[1])){ + $sender->sendMessage(TextFormat::RED . 'Usage: ' . $this->translateString('claim.usage')); + return; + } + $plot = new BasePlot($levelName, (int) $coords[0], (int) $coords[1]); + }else{ + $name = $args[0]; + } + break; + case 2: + if(!str_contains($args[0], ';')){ + $sender->sendMessage(TextFormat::RED . 'Usage: /plot claim '); + return; + } + $coords = explode(';', $args[0]); + if(count($coords) !== 2 or !is_numeric($coords[0]) or !is_numeric($coords[1])){ + $sender->sendMessage(TextFormat::RED . 'Usage: /plot claim '); + return; + } + $plot = new BasePlot($levelName, (int) $coords[0], (int) $coords[1]); + $name = $args[1]; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; } - if($plot->owner != ""){ + $plot = yield from $this->internalAPI->generatePlot($plot); + if(!$plot instanceof SinglePlot) + $plot = SinglePlot::fromBase($plot); + + if($plot->owner !== ""){ if($plot->owner === $sender->getName()){ $sender->sendMessage(TextFormat::RED . $this->translateString("claim.yourplot")); }else{ @@ -41,23 +75,16 @@ function() use ($sender, $args) : \Generator{ return; } $maxPlots = $this->plugin->getMaxPlotsOfPlayer($sender); - $plotsOfPlayer = 0; - foreach($this->internalAPI->getAllLevelSettings() as $worldName => $settings){ - $worldName = $this->plugin->getServer()->getWorldManager()->getWorldByName($worldName); - if($worldName !== null and $worldName->isLoaded()){ - $plotsOfPlayer += count(yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $worldName->getFolderName())); - } - } - if($plotsOfPlayer >= $maxPlots){ + if(count(yield from $this->internalAPI->generatePlotsOfPlayer($sender->getName(), null)) >= $maxPlots){ $sender->sendMessage(TextFormat::RED . $this->translateString("claim.maxplots", [$maxPlots])); return; } $economy = $this->internalAPI->getEconomyProvider(); - if($economy !== null and !(yield $economy->reduceMoney($sender, $plot->price, 'used plot claim command'))){ + if($economy !== null and !(yield from $economy->reduceMoney($sender, $plot->price, 'used plot claim command'))){ $sender->sendMessage(TextFormat::RED . $this->translateString("claim.nomoney")); return; } - if(yield $this->internalAPI->generateClaimPlot($plot, $sender->getName(), $name)){ + if(yield from $this->internalAPI->generateClaimPlot($plot, $sender->getName(), $name)){ $sender->sendMessage($this->translateString("claim.success")); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/ClearSubCommand.php b/src/MyPlot/subcommand/ClearSubCommand.php index a488e5ea..e9ded398 100644 --- a/src/MyPlot/subcommand/ClearSubCommand.php +++ b/src/MyPlot/subcommand/ClearSubCommand.php @@ -1,5 +1,6 @@ hasPermission("myplot.command.clear"); +class ClearSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.clear")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -22,7 +32,7 @@ public function canUse(CommandSender $sender) : bool { public function execute(CommandSender $sender, array $args) : bool{ Await::f2c( function() use ($sender, $args) : \Generator{ - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -38,14 +48,14 @@ function() use ($sender, $args) : \Generator{ } $economy = $this->internalAPI->getEconomyProvider(); $price = $this->internalAPI->getLevelSettings($plot->levelName)->clearPrice; - if($economy !== null and !(yield $economy->reduceMoney($sender, $price, 'used plot clear command'))){ + if($economy !== null and !(yield from $economy->reduceMoney($sender, $price, 'used plot clear command'))){ $sender->sendMessage(TextFormat::RED . $this->translateString("clear.nomoney")); return; } $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); if(!is_int($maxBlocksPerTick)) $maxBlocksPerTick = 256; - if(yield $this->internalAPI->generateClearPlot($plot, $maxBlocksPerTick)){ + if(yield from $this->internalAPI->generateClearPlot($plot, $maxBlocksPerTick)){ $sender->sendMessage($this->translateString("clear.success")); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/CloneSubCommand.php b/src/MyPlot/subcommand/CloneSubCommand.php index 690bded3..c935e288 100644 --- a/src/MyPlot/subcommand/CloneSubCommand.php +++ b/src/MyPlot/subcommand/CloneSubCommand.php @@ -1,22 +1,33 @@ hasPermission("myplot.command.clone"); +class CloneSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.clone")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -34,8 +45,8 @@ function() use ($sender, $args) : \Generator{ return; } $levelName = $args[1] ?? $sender->getWorld()->getFolderName(); - $selectedPlot = yield $this->internalAPI->generatePlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1]); - $standingPlot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $selectedPlot = yield from $this->internalAPI->generatePlot(new BasePlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1])); + $standingPlot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($standingPlot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -50,11 +61,11 @@ function() use ($sender, $args) : \Generator{ } $plotLevel = $this->plugin->getLevelSettings($standingPlot->levelName); $economy = $this->internalAPI->getEconomyProvider(); - if($economy !== null and !(yield $economy->reduceMoney($sender, $plotLevel->clonePrice))){ + if($economy !== null and !(yield from $economy->reduceMoney($sender, $plotLevel->clonePrice))){ $sender->sendMessage(TextFormat::RED . $this->translateString("clone.nomoney")); return; } - if(yield $this->internalAPI->generateClonePlot($selectedPlot, $standingPlot)){ + if($this->internalAPI->clonePlot($selectedPlot, $standingPlot)){ $sender->sendMessage($this->translateString("clone.success", [$selectedPlot->__toString(), $standingPlot->__toString()])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/DenyPlayerSubCommand.php b/src/MyPlot/subcommand/DenyPlayerSubCommand.php index 76b2c344..32fcb2d6 100644 --- a/src/MyPlot/subcommand/DenyPlayerSubCommand.php +++ b/src/MyPlot/subcommand/DenyPlayerSubCommand.php @@ -1,22 +1,32 @@ hasPermission("myplot.command.denyplayer"); +class DenyPlayerSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.denyplayer")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -29,7 +39,7 @@ function() use ($sender, $args) : \Generator{ return; } $dplayer = $args[0]; - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -39,11 +49,11 @@ function() use ($sender, $args) : \Generator{ return; } if($dplayer === "*"){ - if(yield $this->internalAPI->generateAddPlotDenied($plot, $dplayer)){ + if(yield from $this->internalAPI->generateAddPlotDenied($plot, $dplayer)){ $sender->sendMessage($this->translateString("denyplayer.success1", [$dplayer])); foreach($this->plugin->getServer()->getOnlinePlayers() as $player){ - if((yield $this->internalAPI->generatePlotBB($plot))->isVectorInside($player) and !($player->getName() === $plot->owner) and !$player->hasPermission("myplot.admin.denyplayer.bypass") and !$plot->isHelper($player->getName())) - $this->internalAPI->generatePlayerTeleport($player, $plot, false); + if($this->internalAPI->getPlotBB($plot)->isVectorInside($player->getPosition()) and !($player->getName() === $plot->owner) and !$player->hasPermission("myplot.admin.denyplayer.bypass") and !$plot->isHelper($player->getName())) + $this->internalAPI->teleportPlayerToPlot($player, $plot, false); else{ $sender->sendMessage($this->translateString("denyplayer.cannotdeny", [$player->getName()])); $player->sendMessage($this->translateString("denyplayer.attempteddeny", [$sender->getName()])); @@ -65,11 +75,11 @@ function() use ($sender, $args) : \Generator{ $dplayer->sendMessage($this->translateString("denyplayer.attempteddeny", [$sender->getName()])); return; } - if(yield $this->plugin->addPlotDenied($plot, $dplayer->getName())){ + if(yield from $this->internalAPI->generateAddPlotDenied($plot, $dplayer->getName())){ $sender->sendMessage($this->translateString("denyplayer.success1", [$dplayer->getName()])); $dplayer->sendMessage($this->translateString("denyplayer.success2", [$plot->X, $plot->Z, $sender->getName()])); - if((yield $this->internalAPI->generatePlotBB($plot))->isVectorInside($dplayer)) - $this->internalAPI->generatePlayerTeleport($dplayer, $plot, false); + if($this->internalAPI->getPlotBB($plot)->isVectorInside($dplayer->getPosition())) + $this->internalAPI->teleportPlayerToPlot($dplayer, $plot, false); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); } diff --git a/src/MyPlot/subcommand/DisposeSubCommand.php b/src/MyPlot/subcommand/DisposeSubCommand.php index 6d1d7fc1..d15e51b0 100644 --- a/src/MyPlot/subcommand/DisposeSubCommand.php +++ b/src/MyPlot/subcommand/DisposeSubCommand.php @@ -1,21 +1,31 @@ hasPermission("myplot.command.dispose"); +class DisposeSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.dispose")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -23,7 +33,7 @@ public function canUse(CommandSender $sender) : bool { public function execute(CommandSender $sender, array $args) : bool{ Await::f2c( function() use ($sender, $args) : \Generator{ - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -39,11 +49,11 @@ function() use ($sender, $args) : \Generator{ } $economy = $this->internalAPI->getEconomyProvider(); $price = $this->plugin->getLevelSettings($plot->levelName)->disposePrice; - if($economy !== null and !(yield $economy->reduceMoney($sender, $price))){ + if($economy !== null and !(yield from $economy->reduceMoney($sender, $price))){ $sender->sendMessage(TextFormat::RED . $this->translateString("dispose.nomoney")); return; } - if(yield $this->plugin->disposePlot($plot)){ + if(yield from $this->internalAPI->generateDisposePlot($plot)){ $sender->sendMessage(TextFormat::GREEN . $this->translateString("dispose.success")); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/FillSubCommand.php b/src/MyPlot/subcommand/FillSubCommand.php index f856a37a..ce0ff20e 100644 --- a/src/MyPlot/subcommand/FillSubCommand.php +++ b/src/MyPlot/subcommand/FillSubCommand.php @@ -1,10 +1,9 @@ hasPermission("myplot.command.fill"); + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.fill")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -36,7 +46,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); return; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -52,14 +62,14 @@ function() use ($sender, $args) : \Generator{ } $economy = $this->internalAPI->getEconomyProvider(); $price = $this->internalAPI->getLevelSettings($plot->levelName)->fillPrice; - if($economy !== null and !(yield $economy->reduceMoney($sender, $price, 'used plot fill command'))){ + if($economy !== null and !(yield from $economy->reduceMoney($sender, $price, 'used plot fill command'))){ $sender->sendMessage(TextFormat::RED . $this->translateString("fill.nomoney")); return; } $maxBlocksPerTick = $this->plugin->getConfig()->get("FillBlocksPerTick", 256); if(!is_int($maxBlocksPerTick)) $maxBlocksPerTick = 256; - if(yield $this->plugin->fillPlot($plot, $item->getBlock(), $maxBlocksPerTick)){ + if($this->internalAPI->fillPlot($plot, $item->getBlock(), $maxBlocksPerTick)){ $sender->sendMessage($this->translateString("fill.success", [$item->getBlock()->getName()])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/GenerateSubCommand.php b/src/MyPlot/subcommand/GenerateSubCommand.php index d1beb301..1207ab58 100644 --- a/src/MyPlot/subcommand/GenerateSubCommand.php +++ b/src/MyPlot/subcommand/GenerateSubCommand.php @@ -1,50 +1,43 @@ hasPermission("myplot.command.generate"); } /** * @param CommandSender $sender - * @param string[] $args + * @param string[] $args * * @return bool */ public function execute(CommandSender $sender, array $args) : bool{ - Await::f2c( - function() use ($sender, $args) : \Generator{ - if(count($args) === 0){ - $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); - return; - } - $levelName = $args[0]; - if($sender->getServer()->getWorldManager()->isWorldGenerated($levelName)){ - $sender->sendMessage(TextFormat::RED . $this->translateString("generate.exists", [$levelName])); - return; - } - if($this->plugin->generateLevel($levelName, $args[2] ?? MyPlotGenerator::NAME)){ - if(isset($args[1]) and $args[1] == true and $sender instanceof Player){ - yield $this->internalAPI->generatePlayerTeleport($sender, new BasePlot($levelName, 0, 0), false); - } - $sender->sendMessage($this->translateString("generate.success", [$levelName])); - }else{ - $sender->sendMessage(TextFormat::RED . $this->translateString("generate.error")); - } + if(count($args) === 0){ + return false; + } + $levelName = $args[0]; + if($sender->getServer()->getWorldManager()->isWorldGenerated($levelName)){ + $sender->sendMessage(TextFormat::RED . $this->translateString("generate.exists", [$levelName])); + return true; + } + if($this->plugin->generateLevel($levelName, $args[2] ?? MyPlotGenerator::NAME)){ + if(isset($args[1]) and $args[1] == true and $sender instanceof Player){ + $this->internalAPI->teleportPlayerToPlot($sender, new BasePlot($levelName, 0, 0), false); } - ); + $sender->sendMessage($this->translateString("generate.success", [$levelName])); + }else{ + $sender->sendMessage(TextFormat::RED . $this->translateString("generate.error")); + } return true; } diff --git a/src/MyPlot/subcommand/GiveSubCommand.php b/src/MyPlot/subcommand/GiveSubCommand.php index bb89dadd..e809c696 100644 --- a/src/MyPlot/subcommand/GiveSubCommand.php +++ b/src/MyPlot/subcommand/GiveSubCommand.php @@ -1,23 +1,32 @@ hasPermission("myplot.command.give"); +class GiveSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.give")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -30,7 +39,7 @@ function() use ($sender, $args) : \Generator{ return; } $newOwner = $args[0]; - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -48,7 +57,7 @@ function() use ($sender, $args) : \Generator{ return; } $maxPlots = $this->plugin->getMaxPlotsOfPlayer($newOwner); - if(count(yield $this->internalAPI->generatePlotsOfPlayer($newOwner->getName(), null)) >= $maxPlots){ + if(count(yield from $this->internalAPI->generatePlotsOfPlayer($newOwner->getName(), null)) >= $maxPlots){ $sender->sendMessage(TextFormat::RED . $this->translateString("give.maxedout", [$maxPlots])); return; } @@ -58,7 +67,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage($this->translateString("give.confirm", [$plotId, $newOwnerName])); return; } - if(yield $this->internalAPI->generateClaimPlot($plot, $newOwner->getName(), '')){ + if(yield from $this->internalAPI->generateClaimPlot($plot, $newOwner->getName(), '')){ $plotId = TextFormat::GREEN . $plot . TextFormat::WHITE; $oldOwnerName = TextFormat::GREEN . $sender->getName() . TextFormat::WHITE; $newOwnerName = TextFormat::GREEN . $newOwner->getName() . TextFormat::WHITE; diff --git a/src/MyPlot/subcommand/HelpSubCommand.php b/src/MyPlot/subcommand/HelpSubCommand.php index 0a7ce6ae..f9b7fdd7 100644 --- a/src/MyPlot/subcommand/HelpSubCommand.php +++ b/src/MyPlot/subcommand/HelpSubCommand.php @@ -1,13 +1,12 @@ cmds->getCommands() as $command) { - if ($command->canUse($sender)) { + foreach($this->cmds->getCommands() as $command){ + if($command->canUse($sender)){ $commands[$command->getName()] = $command; } } ksort($commands, SORT_NATURAL | SORT_FLAG_CASE); - $commands = array_chunk($commands, (int) ($sender->getScreenLineHeight()/2)); + $commands = array_chunk($commands, (int) ($sender->getScreenLineHeight() / 2)); /** @var SubCommand[][] $commands */ $pageNumber = min(count($commands), $pageNumber); - $sender->sendMessage(TextFormat::GREEN.$this->translateString("help.header", [$pageNumber, count($commands)])); - foreach($commands[$pageNumber - 1] as $command) { - $sender->sendMessage(TextFormat::BLUE . $command->getUsage().TextFormat::WHITE.":"); + $sender->sendMessage(TextFormat::GREEN . $this->translateString("help.header", [$pageNumber, count($commands)])); + foreach($commands[$pageNumber - 1] as $command){ + $sender->sendMessage(TextFormat::BLUE . $command->getUsage() . TextFormat::WHITE . ":"); $sender->sendMessage(TextFormat::AQUA . $command->getDescription()); } return true; diff --git a/src/MyPlot/subcommand/HomeSubCommand.php b/src/MyPlot/subcommand/HomeSubCommand.php index 6edf1cef..0019c4c1 100644 --- a/src/MyPlot/subcommand/HomeSubCommand.php +++ b/src/MyPlot/subcommand/HomeSubCommand.php @@ -1,24 +1,33 @@ hasPermission("myplot.command.home"); +class HomeSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.home")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -39,7 +48,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("error", [$levelName])); return; } - $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); + $plots = yield from $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); if(count($plots) === 0){ $sender->sendMessage(TextFormat::RED . $this->translateString("home.noplots")); return; @@ -55,7 +64,7 @@ function() use ($sender, $args) : \Generator{ return ($plot1->levelName < $plot2->levelName) ? -1 : 1; }); $plot = $plots[$plotNumber - 1]; - if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, false)){ + if($this->internalAPI->teleportPlayerToPlot($sender, $plot, false)){ $sender->sendMessage($this->translateString("home.success", [$plot->__toString(), $plot->levelName])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("home.error")); diff --git a/src/MyPlot/subcommand/HomesSubCommand.php b/src/MyPlot/subcommand/HomesSubCommand.php index 690766cb..b618158c 100644 --- a/src/MyPlot/subcommand/HomesSubCommand.php +++ b/src/MyPlot/subcommand/HomesSubCommand.php @@ -1,21 +1,31 @@ hasPermission("myplot.command.homes"); +class HomesSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.homes")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -28,7 +38,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("error", [$levelName])); return; } - $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); + $plots = yield from $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); if(count($plots) === 0){ $sender->sendMessage(TextFormat::RED . $this->translateString("homes.noplots")); return; diff --git a/src/MyPlot/subcommand/InfoSubCommand.php b/src/MyPlot/subcommand/InfoSubCommand.php index 8dc5144d..76e34c00 100644 --- a/src/MyPlot/subcommand/InfoSubCommand.php +++ b/src/MyPlot/subcommand/InfoSubCommand.php @@ -1,22 +1,32 @@ hasPermission("myplot.command.info"); +class InfoSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.info")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -27,7 +37,7 @@ function() use ($sender, $args) : \Generator{ if(isset($args[0])){ if(isset($args[1]) and is_numeric($args[1])){ $key = max(((int) $args[1] - 1), 1); - $plots = yield $this->internalAPI->generatePlotsOfPlayer($args[0], null); + $plots = yield from $this->internalAPI->generatePlotsOfPlayer($args[0], null); if(isset($plots[$key])){ $plot = $plots[$key]; $sender->sendMessage($this->translateString("info.about", [TextFormat::GREEN . $plot])); @@ -46,7 +56,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); return; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; diff --git a/src/MyPlot/subcommand/KickSubCommand.php b/src/MyPlot/subcommand/KickSubCommand.php index 9197ff48..376d670f 100644 --- a/src/MyPlot/subcommand/KickSubCommand.php +++ b/src/MyPlot/subcommand/KickSubCommand.php @@ -1,23 +1,32 @@ hasPermission("myplot.command.kick"); +class KickSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.kick")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -29,7 +38,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); return; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -43,7 +52,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("kick.noPlayer")); return; } - if(($targetPlot = yield $this->internalAPI->generatePlotByPosition($target->getPosition())) === null or !$plot->isSame($targetPlot)){ + if(($targetPlot = yield from $this->internalAPI->generatePlotByPosition($target->getPosition())) === null or !$plot->isSame($targetPlot)){ $sender->sendMessage(TextFormat::RED . $this->translateString("kick.notInPlot")); return; } @@ -52,7 +61,7 @@ function() use ($sender, $args) : \Generator{ $target->sendMessage($this->translateString("kick.attemptkick", [$target->getName()])); return; } - if(!yield $this->internalAPI->generatePlayerTeleport($target, $plot, false)){ + if($this->internalAPI->teleportPlayerToPlot($target, $plot, false)){ $sender->sendMessage($this->translateString("kick.success1", [$target->getName(), $plot->__toString()])); $target->sendMessage($this->translateString("kick.success2", [$sender->getName(), $plot->__toString()])); }else{ diff --git a/src/MyPlot/subcommand/ListSubCommand.php b/src/MyPlot/subcommand/ListSubCommand.php index ca6a583c..f6c81e4b 100644 --- a/src/MyPlot/subcommand/ListSubCommand.php +++ b/src/MyPlot/subcommand/ListSubCommand.php @@ -1,20 +1,20 @@ hasPermission("myplot.command.list"); } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -22,38 +22,16 @@ public function canUse(CommandSender $sender) : bool { public function execute(CommandSender $sender, array $args) : bool{ Await::f2c( function() use ($sender, $args) : \Generator{ - if($sender->hasPermission("myplot.admin.list")){ - if(count($args) > 0){ - foreach($this->internalAPI->getAllLevelSettings() as $levelName => $settings){ - $plots = yield $this->internalAPI->generatePlotsOfPlayer($args[0], $levelName); - foreach($plots as $plot){ - $name = $plot->name; - $x = $plot->X; - $z = $plot->Z; - $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); - } - } - }else{ - foreach($this->internalAPI->getAllLevelSettings() as $levelName => $settings){ - $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); - foreach($plots as $plot){ - $name = $plot->name; - $x = $plot->X; - $z = $plot->Z; - $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); - } - } - } - }elseif($sender->hasPermission("myplot.command.list")){ - foreach($this->internalAPI->getAllLevelSettings() as $levelName => $settings){ - $plots = yield $this->internalAPI->generatePlotsOfPlayer($sender->getName(), $levelName); - foreach($plots as $plot){ - $name = $plot->name; - $x = $plot->X; - $z = $plot->Z; - $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); - } - } + if(count($args) > 0 and $sender->hasPermission("myplot.admin.list")) + $plots = yield from $this->internalAPI->generatePlotsOfPlayer($args[0], null); + else + $plots = yield from $this->internalAPI->generatePlotsOfPlayer($sender->getName(), null); + + foreach($plots as $plot){ + $name = $plot->name; + $x = $plot->X; + $z = $plot->Z; + $sender->sendMessage(TF::YELLOW . $this->translateString("list.found", [$name, $x, $z])); } } ); diff --git a/src/MyPlot/subcommand/MergeSubCommand.php b/src/MyPlot/subcommand/MergeSubCommand.php index b24db51f..35a1f037 100644 --- a/src/MyPlot/subcommand/MergeSubCommand.php +++ b/src/MyPlot/subcommand/MergeSubCommand.php @@ -1,22 +1,32 @@ hasPermission("myplot.command.merge")); +class MergeSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.merge")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -24,7 +34,7 @@ public function canUse(CommandSender $sender) : bool { public function execute(CommandSender $sender, array $args) : bool{ Await::f2c( function() use ($sender) : \Generator{ - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -101,7 +111,7 @@ function() use ($sender) : \Generator{ $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); if(!is_int($maxBlocksPerTick)) $maxBlocksPerTick = 256; - if(yield $this->internalAPI->generateMergePlots($plot, $direction, $maxBlocksPerTick)){ + if(yield from $this->internalAPI->generateMergePlots($plot, $direction, $maxBlocksPerTick)){ $plot = TextFormat::GREEN . $plot . TextFormat::WHITE; $sender->sendMessage($this->translateString("merge.success", [$plot, $args[0]])); }else{ diff --git a/src/MyPlot/subcommand/MiddleSubCommand.php b/src/MyPlot/subcommand/MiddleSubCommand.php index 61db57bd..efa4863c 100644 --- a/src/MyPlot/subcommand/MiddleSubCommand.php +++ b/src/MyPlot/subcommand/MiddleSubCommand.php @@ -1,21 +1,31 @@ hasPermission("myplot.command.middle")); +class MiddleSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.middle")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -27,7 +37,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); return; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -36,7 +46,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); return; } - if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, true)){ + if($this->internalAPI->teleportPlayerToPlot($sender, $plot, true)){ $sender->sendMessage(TextFormat::GREEN . $this->translateString("middle.success")); } } diff --git a/src/MyPlot/subcommand/NameSubCommand.php b/src/MyPlot/subcommand/NameSubCommand.php index 1f68639f..171f951b 100644 --- a/src/MyPlot/subcommand/NameSubCommand.php +++ b/src/MyPlot/subcommand/NameSubCommand.php @@ -1,23 +1,32 @@ hasPermission("myplot.command.name"); +class NameSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.name")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -28,7 +37,7 @@ function() use ($sender, $args) : \Generator{ if(count($args) === 0){ $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -37,7 +46,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("notowner")); return; } - if(yield $this->internalAPI->generateRenamePlot($plot, $args[0])){ + if(yield from $this->internalAPI->generateRenamePlot($plot, $args[0])){ $sender->sendMessage($this->translateString("name.success")); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/PvpSubCommand.php b/src/MyPlot/subcommand/PvpSubCommand.php index 9d20a6dc..604d8812 100644 --- a/src/MyPlot/subcommand/PvpSubCommand.php +++ b/src/MyPlot/subcommand/PvpSubCommand.php @@ -1,21 +1,21 @@ hasPermission("myplot.command.pvp"); } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -23,7 +23,7 @@ public function canUse(CommandSender $sender) : bool { public function execute(CommandSender $sender, array $args) : bool{ Await::f2c( function() use ($sender, $args) : \Generator{ - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -37,7 +37,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("pvp.world")); return; } - if(yield $this->internalAPI->generatePlotPvp($plot, !$plot->pvp)){ + if(yield from $this->internalAPI->generatePlotPvp($plot, !$plot->pvp)){ $sender->sendMessage($this->translateString("pvp.success", [!$plot->pvp ? "enabled" : "disabled"])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/RemoveHelperSubCommand.php b/src/MyPlot/subcommand/RemoveHelperSubCommand.php index 7fff1afc..a0be5b52 100644 --- a/src/MyPlot/subcommand/RemoveHelperSubCommand.php +++ b/src/MyPlot/subcommand/RemoveHelperSubCommand.php @@ -1,23 +1,32 @@ hasPermission("myplot.command.removehelper"); +class RemoveHelperSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.removehelper")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -30,7 +39,7 @@ function() use ($sender, $args) : \Generator{ return; } $helperName = $args[0]; - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -42,7 +51,8 @@ function() use ($sender, $args) : \Generator{ $helper = $this->plugin->getServer()->getPlayerByPrefix($helperName); if($helper === null) $helper = $this->plugin->getServer()->getOfflinePlayer($helperName); - if(yield $this->internalAPI->generateRemovePlotHelper($plot, $helper->getName())){ + + if(yield from $this->internalAPI->generateRemovePlotHelper($plot, $helper->getName())){ $sender->sendMessage($this->translateString("removehelper.success", [$helper->getName()])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/ResetSubCommand.php b/src/MyPlot/subcommand/ResetSubCommand.php index 0064b865..3fa31470 100644 --- a/src/MyPlot/subcommand/ResetSubCommand.php +++ b/src/MyPlot/subcommand/ResetSubCommand.php @@ -1,21 +1,31 @@ hasPermission("myplot.command.reset"); +class ResetSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.reset")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -23,7 +33,7 @@ public function canUse(CommandSender $sender) : bool { public function execute(CommandSender $sender, array $args) : bool{ Await::f2c( function() use ($sender, $args) : \Generator{ - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -39,14 +49,14 @@ function() use ($sender, $args) : \Generator{ } $economy = $this->internalAPI->getEconomyProvider(); $price = $this->plugin->getLevelSettings($plot->levelName)->resetPrice; - if($economy !== null and !(yield $economy->reduceMoney($sender, $price))){ + if($economy !== null and !(yield from $economy->reduceMoney($sender, $price))){ $sender->sendMessage(TextFormat::RED . $this->translateString("reset.nomoney")); return; } $maxBlocksPerTick = $this->plugin->getConfig()->get("ClearBlocksPerTick", 256); if(!is_int($maxBlocksPerTick)) $maxBlocksPerTick = 256; - if(yield $this->internalAPI->generateResetPlot($plot, $maxBlocksPerTick)){ + if(yield from $this->internalAPI->generateResetPlot($plot, $maxBlocksPerTick)){ $sender->sendMessage($this->translateString("reset.success")); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/SellSubCommand.php b/src/MyPlot/subcommand/SellSubCommand.php index 6a822a92..9f93809c 100644 --- a/src/MyPlot/subcommand/SellSubCommand.php +++ b/src/MyPlot/subcommand/SellSubCommand.php @@ -1,21 +1,31 @@ hasPermission("myplot.command.sell"); +class SellSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.sell")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -27,7 +37,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); return; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -45,7 +55,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("sell.unlisted", ["$plot->X;$plot->Z"])); return; } - if(yield $this->internalAPI->generateSellPlot($plot, $price)){ + if(yield from $this->internalAPI->generateSellPlot($plot, $price)){ $sender->sendMessage($this->translateString("sell.success", ["$plot->X;$plot->Z", $price])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/SetOwnerSubCommand.php b/src/MyPlot/subcommand/SetOwnerSubCommand.php index babb60c2..e34d1d59 100644 --- a/src/MyPlot/subcommand/SetOwnerSubCommand.php +++ b/src/MyPlot/subcommand/SetOwnerSubCommand.php @@ -1,22 +1,32 @@ hasPermission("myplot.admin.setowner"); +class SetOwnerSubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.admin.setowner")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -28,7 +38,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage($this->translateString("subcommand.usage", [$this->getUsage()])); return; } - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -38,7 +48,7 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("setowner.maxplots", [$maxPlots])); return; } - if(yield $this->internalAPI->generateClaimPlot($plot, $args[0], '')){ + if(yield from $this->internalAPI->generateClaimPlot($plot, $args[0], '')){ $sender->sendMessage($this->translateString("setowner.success", [$args[0]])); }else{ $sender->sendMessage(TextFormat::RED . $this->translateString("error")); diff --git a/src/MyPlot/subcommand/SubCommand.php b/src/MyPlot/subcommand/SubCommand.php index 9e66fa6b..3b512968 100644 --- a/src/MyPlot/subcommand/SubCommand.php +++ b/src/MyPlot/subcommand/SubCommand.php @@ -1,12 +1,11 @@ plugin->getFallBackLang()->get($this->name . ".usage"); // TODO: use normal language when command autofill gains support - return ($usage == $this->name . ".usage") ? "" : $usage; - } - - public function getName() : string { - $name = $this->plugin->getLanguage()->get($this->name . ".name"); - return ($name == $this->name . ".name") ? "" : $name; - } + $usage = $this->plugin->getFallBackLang()->get($this->name . ".usage"); // TODO: use normal language when command autofill gains support + return ($usage == $this->name . ".usage") ? "" : $usage; + } + + public function getName() : string{ + $name = $this->plugin->getLanguage()->get($this->name . ".name"); + return ($name == $this->name . ".name") ? "" : $name; + } public function getDescription() : string{ $desc = $this->plugin->getLanguage()->get($this->name . ".desc"); diff --git a/src/MyPlot/subcommand/UnDenySubCommand.php b/src/MyPlot/subcommand/UnDenySubCommand.php index 60f8ae07..4148f406 100644 --- a/src/MyPlot/subcommand/UnDenySubCommand.php +++ b/src/MyPlot/subcommand/UnDenySubCommand.php @@ -1,23 +1,32 @@ hasPermission("myplot.command.undenyplayer"); +class UnDenySubCommand extends SubCommand{ + public function canUse(CommandSender $sender) : bool{ + if(!$sender->hasPermission("myplot.command.undenyplayer")){ + return false; + } + if($sender instanceof Player){ + $pos = $sender->getPosition(); + $plotLevel = $this->internalAPI->getLevelSettings($sender->getWorld()->getFolderName()); + if($this->internalAPI->getPlotFast($pos->x, $pos->z, $plotLevel) === null){ + return false; + } + } + + return true; } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -30,7 +39,7 @@ function() use ($sender, $args) : \Generator{ return; } $dplayerName = $args[0]; - $plot = yield $this->internalAPI->generatePlotByPosition($sender->getPosition()); + $plot = yield from $this->internalAPI->generatePlotByPosition($sender->getPosition()); if($plot === null){ $sender->sendMessage(TextFormat::RED . $this->translateString("notinplot")); return; @@ -42,7 +51,8 @@ function() use ($sender, $args) : \Generator{ $dplayer = $this->plugin->getServer()->getPlayerByPrefix($dplayerName); if($dplayer === null) $dplayer = $this->plugin->getServer()->getOfflinePlayer($dplayerName); - if(yield $this->internalAPI->generateRemovePlotDenied($plot, $dplayer->getName())){ + + if(yield from $this->internalAPI->generateRemovePlotDenied($plot, $dplayer->getName())){ $sender->sendMessage($this->translateString("undenyplayer.success1", [$dplayer->getName()])); if($dplayer instanceof Player){ $dplayer->sendMessage($this->translateString("undenyplayer.success2", [$plot->X, $plot->Z, $sender->getName()])); diff --git a/src/MyPlot/subcommand/WarpSubCommand.php b/src/MyPlot/subcommand/WarpSubCommand.php index f7a6a268..7bd640ce 100644 --- a/src/MyPlot/subcommand/WarpSubCommand.php +++ b/src/MyPlot/subcommand/WarpSubCommand.php @@ -1,22 +1,22 @@ hasPermission("myplot.command.warp"); } /** - * @param Player $sender + * @param Player $sender * @param string[] $args * * @return bool @@ -38,12 +38,12 @@ function() use ($sender, $args) : \Generator{ $sender->sendMessage(TextFormat::RED . $this->translateString("warp.wrongid")); return; } - $plot = yield $this->internalAPI->generatePlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1]); + $plot = yield from $this->internalAPI->generatePlot(new BasePlot($levelName, (int) $plotIdArray[0], (int) $plotIdArray[1])); if($plot->owner == "" and !$sender->hasPermission("myplot.admin.warp")){ $sender->sendMessage(TextFormat::RED . $this->translateString("warp.unclaimed")); return; } - if(yield $this->internalAPI->generatePlayerTeleport($sender, $plot, false)){ + if($this->internalAPI->teleportPlayerToPlot($sender, $plot, false)){ $plot = TextFormat::GREEN . $plot . TextFormat::WHITE; $sender->sendMessage($this->translateString("warp.success", [$plot])); }else{ diff --git a/src/MyPlot/task/BorderCorrectionTask.php b/src/MyPlot/task/BorderCorrectionTask.php index 8718afc8..6343d5c5 100644 --- a/src/MyPlot/task/BorderCorrectionTask.php +++ b/src/MyPlot/task/BorderCorrectionTask.php @@ -3,9 +3,10 @@ namespace MyPlot\task; use MyPlot\MyPlot; -use MyPlot\Plot; -use pocketmine\block\Block; +use MyPlot\plot\BasePlot; +use MyPlot\PlotLevelSettings; use pocketmine\block\VanillaBlocks; +use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\scheduler\CancelTaskException; @@ -13,60 +14,43 @@ use pocketmine\world\World; class BorderCorrectionTask extends Task{ - protected MyPlot $plugin; - protected Plot $start; - protected World $level; - protected int $height; - protected Block $plotWallBlock; + protected AxisAlignedBB $aabb; protected Vector3 $plotBeginPos; - protected int $xMax; - protected int $zMax; - protected int $direction; - protected Block $roadBlock; - protected Block $groundBlock; - protected Block $bottomBlock; - protected Plot $end; - protected bool $fillCorner; - protected int $cornerDirection; + protected PlotLevelSettings $plotLevel; protected Vector3 $pos; - protected int $maxBlocksPerTick; + protected World $world; - public function __construct(MyPlot $plugin, Plot $start, Plot $end, bool $fillCorner = false, int $cornerDirection = -1, int $maxBlocksPerTick = 256) { - $this->plugin = $plugin; - $this->start = $start; - $this->end = $end; - $this->fillCorner = $fillCorner; - $this->cornerDirection = $cornerDirection; - $this->maxBlocksPerTick = $maxBlocksPerTick; + public function __construct(private MyPlot $plugin, private BasePlot $start, private BasePlot $end, private bool $fillCorner = false, private int $cornerDirection = -1, private int $maxBlocksPerTick = 256){ + if($start->isSame($end)) + throw new \Exception("Plot arguments cannot be the same plot or already be merged"); + if(abs($start->X - $end->X) !== 1 and abs($start->Z - $end->Z) !== 1) + throw new \Exception("Plot arguments must be adjacent plots"); - $this->plotBeginPos = $plugin->getPlotPosition($start, false); - $this->level = $this->plotBeginPos->getWorld(); + $this->world = $this->plugin->getServer()->getWorldManager()->getWorldByName($start->levelName); + $this->plotLevel = $plugin->getLevelSettings($start->levelName); + $this->aabb = $aabb = null; + $this->plotBeginPos = $this->pos = new Vector3( + $aabb->minX, + $aabb->minY, + $aabb->minZ + ); - $plotLevel = $plugin->getLevelSettings($start->levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $this->height = $plotLevel->groundHeight; - $this->plotWallBlock = $plotLevel->wallBlock; - $this->roadBlock = $plotLevel->roadBlock; - $this->groundBlock = $plotLevel->plotFillBlock; - $this->bottomBlock = $plotLevel->bottomBlock; - - if(($start->Z - $end->Z) === 1) { // North Z- + if(($start->Z - $end->Z) === 1){ // North Z- $this->plotBeginPos = $this->plotBeginPos->subtract(0, 0, $roadWidth); $this->xMax = (int) ($this->plotBeginPos->x + $plotSize); $this->zMax = (int) ($this->plotBeginPos->z + $roadWidth); $this->direction = Facing::NORTH; - }elseif(($start->X - $end->X) === -1) { // East X+ + }elseif(($start->X - $end->X) === -1){ // East X+ $this->plotBeginPos = $this->plotBeginPos->add($plotSize, 0, 0); $this->xMax = (int) ($this->plotBeginPos->x + $roadWidth); $this->zMax = (int) ($this->plotBeginPos->z + $plotSize); $this->direction = Facing::EAST; - }elseif(($start->Z - $end->Z) === -1) { // South Z+ + }elseif(($start->Z - $end->Z) === -1){ // South Z+ $this->plotBeginPos = $this->plotBeginPos->add(0, 0, $plotSize); $this->xMax = (int) ($this->plotBeginPos->x + $plotSize); $this->zMax = (int) ($this->plotBeginPos->z + $roadWidth); $this->direction = Facing::SOUTH; - }elseif(($start->X - $end->X) === 1) { // West X- + }elseif(($start->X - $end->X) === 1){ // West X- $this->plotBeginPos = $this->plotBeginPos->subtract($roadWidth, 0, 0); $this->xMax = (int) ($this->plotBeginPos->x + $roadWidth); $this->zMax = (int) ($this->plotBeginPos->z + $plotSize); @@ -80,11 +64,11 @@ public function __construct(MyPlot $plugin, Plot $start, Plot $end, bool $fillCo $plugin->getLogger()->debug("Border Correction Task started between plots $start->X;$start->Z and $end->X;$end->Z"); } - public function onRun() : void { + public function onRun() : void{ $blocks = 0; - if($this->direction === Facing::NORTH or $this->direction === Facing::SOUTH) { - while($this->pos->z < $this->zMax) { - while($this->pos->y < $this->level->getMaxY()) { + if($this->direction === Facing::NORTH or $this->direction === Facing::SOUTH){ + while($this->pos->z < $this->zMax){ + while($this->pos->y < $this->level->getMaxY()){ if($this->pos->y > $this->height + 1) $block = VanillaBlocks::AIR(); elseif($this->pos->y === $this->height + 1){ @@ -102,7 +86,7 @@ public function onRun() : void { $this->pos->y++; $blocks += 2; - if($blocks >= $this->maxBlocksPerTick) { + if($blocks >= $this->maxBlocksPerTick){ $this->setHandler(null); $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); throw new CancelTaskException(); @@ -112,8 +96,8 @@ public function onRun() : void { $this->pos->z++; } }else{ - while($this->pos->x < $this->xMax) { - while($this->pos->y < $this->level->getMaxY()) { + while($this->pos->x < $this->xMax){ + while($this->pos->y < $this->level->getMaxY()){ if($this->pos->y > $this->height + 1) $block = VanillaBlocks::AIR(); elseif($this->pos->y === $this->height + 1) @@ -128,7 +112,7 @@ public function onRun() : void { $this->level->setBlock(new Vector3($this->pos->x, $this->pos->y, $this->zMax), $block, false); $this->pos->y++; $blocks += 2; - if($blocks >= $this->maxBlocksPerTick) { + if($blocks >= $this->maxBlocksPerTick){ $this->setHandler(null); $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); throw new CancelTaskException(); diff --git a/src/MyPlot/task/ClearBorderTask.php b/src/MyPlot/task/ClearBorderTask.php index 338c3df3..76ad803e 100644 --- a/src/MyPlot/task/ClearBorderTask.php +++ b/src/MyPlot/task/ClearBorderTask.php @@ -3,95 +3,80 @@ namespace MyPlot\task; use MyPlot\MyPlot; -use MyPlot\Plot; -use pocketmine\block\Block; +use MyPlot\plot\BasePlot; +use MyPlot\PlotLevelSettings; use pocketmine\block\VanillaBlocks; +use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; +use pocketmine\scheduler\CancelTaskException; use pocketmine\scheduler\Task; use pocketmine\world\World; -class ClearBorderTask extends Task { - protected MyPlot $plugin; - protected Plot $plot; - protected World $level; - protected int $height; - protected Block $plotWallBlock; +class ClearBorderTask extends Task{ + protected AxisAlignedBB $aabb; protected Vector3 $plotBeginPos; - protected int $xMax; - protected int $zMax; - protected Block $roadBlock; - protected Block $groundBlock; - protected Block $bottomBlock; + protected PlotLevelSettings $plotLevel; + protected Vector3 $pos; + protected World $world; - /** - * ClearBorderTask constructor. - * - * @param MyPlot $plugin - * @param Plot $plot - */ - public function __construct(MyPlot $plugin, Plot $plot) { - $this->plugin = $plugin; - $this->plot = $plot; - $plotLevel = $plugin->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $this->plotBeginPos = $plugin->getPlotPosition($plot, false); - $this->xMax = (int)($this->plotBeginPos->x + $plotSize); - $this->zMax = (int)($this->plotBeginPos->z + $plotSize); - foreach ($plugin->getProvider()->getMergedPlots($plot) as $mergedPlot){ - $xplot = $plugin->getPlotPosition($mergedPlot, false)->x; - $zplot = $plugin->getPlotPosition($mergedPlot, false)->z; - $xMaxPlot = (int)($xplot + $plotSize); - $zMaxPlot = (int)($zplot + $plotSize); - if($this->plotBeginPos->x > $xplot) $this->plotBeginPos->x = $xplot; - if($this->plotBeginPos->z > $zplot) $this->plotBeginPos->z = $zplot; - if($this->xMax < $xMaxPlot) $this->xMax = $xMaxPlot; - if($this->zMax < $zMaxPlot) $this->zMax = $zMaxPlot; - } - - --$this->plotBeginPos->x; - --$this->plotBeginPos->z; - $this->level = $this->plotBeginPos->getWorld(); - $this->height = $plotLevel->groundHeight; - $this->plotWallBlock = $plotLevel->wallBlock; - $this->roadBlock = $plotLevel->roadBlock; - $this->groundBlock = $plotLevel->plotFillBlock; - $this->bottomBlock = $plotLevel->bottomBlock; + public function __construct(private MyPlot $plugin, private BasePlot $plot, private int $maxBlocksPerTick = 256){ + $this->world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + $this->plotLevel = $plugin->getLevelSettings($plot->levelName); + $this->aabb = $aabb = $this->plugin->getPlotBB($plot)->expand(1, 0, 1); + $this->plotBeginPos = $this->pos = new Vector3( + $aabb->minX, + $aabb->minY, + $aabb->minZ + ); $plugin->getLogger()->debug("Border Clear Task started at plot $plot->X;$plot->Z"); } - public function onRun() : void { - for($x = $this->plotBeginPos->x; $x <= $this->xMax; $x++) { - for($y = 0; $y < $this->level->getMaxY(); ++$y) { - if($y > $this->height + 1) + public function onRun() : void{ + $blocks = 0; + for($x = $this->plotBeginPos->x; $x <= $this->aabb->maxX; $x++){ + for($y = 0; $y < $this->aabb->maxY; ++$y){ + if($y > $this->plotLevel->groundHeight + 1) $block = VanillaBlocks::AIR(); - elseif($y === $this->height + 1) - $block = $this->plotWallBlock; - elseif($y === $this->height) - $block = $this->roadBlock; - elseif($y === 0) - $block = $this->bottomBlock; - else//if($y < $this->height) - $block = $this->groundBlock; - $this->level->setBlock(new Vector3($x, $y, $this->plotBeginPos->z), $block, false); - $this->level->setBlock(new Vector3($x, $y, $this->zMax), $block, false); + elseif($y === $this->plotLevel->groundHeight + 1) + $block = $this->plotLevel->wallBlock; + elseif($y === $this->plotLevel->groundHeight) + $block = $this->plotLevel->roadBlock; + elseif($y === $this->aabb->minY) + $block = $this->plotLevel->bottomBlock; + else//if($y < $this->plotLevel->groundHeight) + $block = $this->plotLevel->plotFloorBlock; + $this->world->setBlock(new Vector3($x, $y, $this->plotBeginPos->z), $block, false); + $this->world->setBlock(new Vector3($x, $y, $this->aabb->maxZ), $block, false); + $blocks += 2; } } - for($z = $this->plotBeginPos->z; $z <= $this->zMax; $z++) { - for($y = 0; $y < $this->level->getMaxY(); ++$y) { - if($y > $this->height+1) + if($blocks >= $this->maxBlocksPerTick){ + $this->setHandler(null); + $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); + throw new CancelTaskException(); + } + for($z = $this->plotBeginPos->z; $z <= $this->aabb->maxZ; $z++){ + for($y = 0; $y < $this->aabb->maxY; ++$y){ + if($y > $this->plotLevel->groundHeight + 1) $block = VanillaBlocks::AIR(); - elseif($y === $this->height + 1) - $block = $this->plotWallBlock; - elseif($y === $this->height) - $block = $this->roadBlock; - elseif($y === 0) - $block = $this->bottomBlock; - else//if($y < $this->height) - $block = $this->groundBlock; - $this->level->setBlock(new Vector3($this->plotBeginPos->x, $y, $z), $block, false); - $this->level->setBlock(new Vector3($this->xMax, $y, $z), $block, false); + elseif($y === $this->plotLevel->groundHeight + 1) + $block = $this->plotLevel->wallBlock; + elseif($y === $this->plotLevel->groundHeight) + $block = $this->plotLevel->roadBlock; + elseif($y === $this->aabb->minY) + $block = $this->plotLevel->bottomBlock; + else//if($y < $this->plotLevel->groundHeight) + $block = $this->plotLevel->plotFloorBlock; + $this->world->setBlock(new Vector3($this->plotBeginPos->x, $y, $z), $block, false); + $this->world->setBlock(new Vector3($this->aabb->maxX, $y, $z), $block, false); + $blocks += 2; } } - $this->plugin->getLogger()->debug("Border Clear Task completed"); + if($blocks >= $this->maxBlocksPerTick){ + $this->setHandler(null); + $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); + throw new CancelTaskException(); + } + $this->plugin->getLogger()->debug("Border Clear Task completed at {$this->plot->X};{$this->plot->Z}"); } } \ No newline at end of file diff --git a/src/MyPlot/task/ClearPlotTask.php b/src/MyPlot/task/ClearPlotTask.php index dfb298f6..a44cc361 100644 --- a/src/MyPlot/task/ClearPlotTask.php +++ b/src/MyPlot/task/ClearPlotTask.php @@ -3,73 +3,39 @@ namespace MyPlot\task; use MyPlot\MyPlot; -use MyPlot\Plot; -use pocketmine\block\Block; +use MyPlot\plot\BasePlot; +use MyPlot\PlotLevelSettings; use pocketmine\block\VanillaBlocks; use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\scheduler\CancelTaskException; use pocketmine\scheduler\Task; -use pocketmine\world\Position; use pocketmine\world\World; -class ClearPlotTask extends Task { - protected MyPlot $plugin; - protected Plot $plot; - protected World $level; - protected int $height; - protected Block $bottomBlock; - protected Block $plotFillBlock; - protected Block $plotFloorBlock; - protected Position $plotBeginPos; - protected int $xMax; - protected int $zMax; - protected int $maxBlocksPerTick; +class ClearPlotTask extends Task{ + protected AxisAlignedBB $aabb; + protected Vector3 $plotBeginPos; + protected PlotLevelSettings $plotLevel; protected Vector3 $pos; - protected ?AxisAlignedBB $plotBB; + protected World $world; - /** - * ClearPlotTask constructor. - * - * @param MyPlot $plugin - * @param Plot $plot - * @param int $maxBlocksPerTick - */ - public function __construct(MyPlot $plugin, Plot $plot, int $maxBlocksPerTick = 256) { - $this->plugin = $plugin; - $this->plot = $plot; - $plotLevel = $plugin->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $this->height = $plotLevel->groundHeight; - $this->bottomBlock = $plotLevel->bottomBlock; - $this->plotFillBlock = $plotLevel->plotFillBlock; - $this->plotFloorBlock = $plotLevel->plotFloorBlock; - $this->maxBlocksPerTick = $maxBlocksPerTick; - - $this->plotBeginPos = $plugin->getPlotPosition($plot, false); - $this->xMax = (int)($this->plotBeginPos->x + $plotSize); - $this->zMax = (int)($this->plotBeginPos->z + $plotSize); - foreach ($plugin->getProvider()->getMergedPlots($plot) as $mergedPlot){ - $xplot = $plugin->getPlotPosition($mergedPlot, false)->x; - $zplot = $plugin->getPlotPosition($mergedPlot, false)->z; - $xMaxPlot = (int)($xplot + $plotSize); - $zMaxPlot = (int)($zplot + $plotSize); - if($this->plotBeginPos->x > $xplot) $this->plotBeginPos->x = $xplot; - if($this->plotBeginPos->z > $zplot) $this->plotBeginPos->z = $zplot; - if($this->xMax < $xMaxPlot) $this->xMax = $xMaxPlot; - if($this->zMax < $zMaxPlot) $this->zMax = $zMaxPlot; - } - $this->level = $this->plotBeginPos->getWorld(); - $this->pos = new Vector3($this->plotBeginPos->x, 0, $this->plotBeginPos->z); - $this->plotBB = $this->plugin->getPlotBB($plot); + public function __construct(private MyPlot $plugin, private BasePlot $plot, private int $maxBlocksPerTick = 256){ + $this->world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + $this->plotLevel = $plugin->getLevelSettings($plot->levelName); + $this->aabb = $aabb = $this->plugin->getPlotBB($plot); + $this->plotBeginPos = $this->pos = new Vector3( + $aabb->minX, + $aabb->minY, + $aabb->minZ + ); $plugin->getLogger()->debug("Plot Clear Task started at plot $plot->X;$plot->Z"); } - public function onRun() : void { - foreach($this->level->getEntities() as $entity) { - if($this->plotBB->isVectorInXZ($entity->getPosition())) { - if(!$entity instanceof Player) { + public function onRun() : void{ + foreach($this->world->getEntities() as $entity){ + if($this->aabb->isVectorInXZ($entity->getPosition())){ + if(!$entity instanceof Player){ $entity->flagForDespawn(); }else{ $this->plugin->teleportPlayerToPlot($entity, $this->plot); @@ -77,40 +43,35 @@ public function onRun() : void { } } $blocks = 0; - while($this->pos->x < $this->xMax) { - while($this->pos->z < $this->zMax) { - while($this->pos->y < $this->level->getMaxY()) { - if($this->pos->y === 0) { - $block = $this->bottomBlock; - }elseif($this->pos->y < $this->height) { - $block = $this->plotFillBlock; - }elseif($this->pos->y === $this->height) { - $block = $this->plotFloorBlock; - }else{ + for(; $this->pos->x < $this->aabb->maxX; ++$this->pos->x, $this->pos->z = $this->aabb->minZ){ + for(; $this->pos->z < $this->aabb->maxZ; ++$this->pos->z, $this->pos->y = $this->aabb->minY){ + for(; $this->pos->y < $this->aabb->maxY; ++$this->pos->y){ + if($this->pos->y === $this->aabb->minY) + $block = $this->plotLevel->bottomBlock; + elseif($this->pos->y < $this->plotLevel->groundHeight) + $block = $this->plotLevel->plotFillBlock; + elseif($this->pos->y === $this->plotLevel->groundHeight) + $block = $this->plotLevel->plotFloorBlock; + else $block = VanillaBlocks::AIR(); - } - $this->level->setBlock($this->pos, $block, false); - $blocks++; - if($blocks >= $this->maxBlocksPerTick) { + $this->world->setBlock($this->pos, $block, false); + + if(++$blocks >= $this->maxBlocksPerTick){ $this->setHandler(null); $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); throw new CancelTaskException(); } - $this->pos->y++; } - $this->pos->y = 0; - $this->pos->z++; } - $this->pos->z = $this->plotBeginPos->z; - $this->pos->x++; } - - foreach($this->plugin->getPlotChunks($this->plot) as [$chunkX, $chunkZ, $chunk]) { - foreach($chunk->getTiles() as $tile) { - $tile->close(); - } + foreach($this->plugin->getPlotChunks($this->plot) as [$chunkX, $chunkZ, $chunk]){ + if($chunk === null) + continue; + foreach($chunk->getTiles() as $tile) + if($this->aabb->isVectorInXZ($tile->getPosition())) + $tile->close(); } - $this->plugin->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this->plugin, $this->plot), 1); - $this->plugin->getLogger()->debug("Plot Clear task completed at {$this->plotBeginPos->x};{$this->plotBeginPos->z}"); + $this->plugin->getScheduler()->scheduleDelayedTask(new ClearBorderTask($this->plugin, $this->plot, $this->maxBlocksPerTick), 1); + $this->plugin->getLogger()->debug("Plot Clear Task completed at {$this->plot->X};{$this->plot->Z}"); } } \ No newline at end of file diff --git a/src/MyPlot/task/CornerCorrectionTask.php b/src/MyPlot/task/CornerCorrectionTask.php index a0a5f7bc..dd79af56 100644 --- a/src/MyPlot/task/CornerCorrectionTask.php +++ b/src/MyPlot/task/CornerCorrectionTask.php @@ -3,9 +3,10 @@ namespace MyPlot\task; use MyPlot\MyPlot; -use MyPlot\Plot; -use pocketmine\block\Block; +use MyPlot\plot\BasePlot; +use MyPlot\PlotLevelSettings; use pocketmine\block\VanillaBlocks; +use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; @@ -14,64 +15,53 @@ use pocketmine\world\World; class CornerCorrectionTask extends Task{ - - protected MyPlot $plugin; - protected Plot $start; - protected ?World $level; - protected int $height; - protected Block $plotWallBlock; - protected int $maxBlocksPerTick; - protected ?Vector3 $plotBeginPos; - protected int $xMax; - protected int $zMax; - protected int $direction; - protected Block $roadBlock; - protected Block $groundBlock; - protected Block $bottomBlock; + protected AxisAlignedBB $aabb; + protected Vector3 $plotBeginPos; + protected PlotLevelSettings $plotLevel; protected Vector3 $pos; + protected World $world; - public function __construct(MyPlot $plugin, Plot $start, Plot $end, int $cornerDirection, int $maxBlocksPerTick = 256) { - $this->plugin = $plugin; - $this->start = $start; - $this->plotBeginPos = $plugin->getPlotPosition($start, false); - $this->level = $this->plotBeginPos->getWorld(); - $this->maxBlocksPerTick = $maxBlocksPerTick; + public function __construct(private MyPlot $plugin, private BasePlot $start, private BasePlot $end, private int $cornerDirection, private int $maxBlocksPerTick = 256){ + if($start->isSame($end)) + throw new \Exception("Plot arguments cannot be the same plot or already be merged"); + if(abs($start->X - $end->X) !== 1 and abs($start->Z - $end->Z) !== 1) + throw new \Exception("Plot arguments must be adjacent plots"); - $plotLevel = $plugin->getLevelSettings($start->levelName); - $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $this->height = $plotLevel->groundHeight; - $this->plotWallBlock = $plotLevel->wallBlock; - $this->roadBlock = $plotLevel->plotFloorBlock; - $this->groundBlock = $plotLevel->plotFillBlock; - $this->bottomBlock = $plotLevel->bottomBlock; + $this->world = $this->plugin->getServer()->getWorldManager()->getWorldByName($start->levelName); + $this->plotLevel = $plugin->getLevelSettings($start->levelName); + $this->aabb = $aabb = null; + $this->plotBeginPos = $this->pos = new Vector3( + $aabb->minX, + $aabb->minY, + $aabb->minZ + ); - if(($start->Z - $end->Z) === 1) { // North Z- - if($cornerDirection === Facing::EAST) { + if(($start->Z - $end->Z) === 1){ // North Z- + if($cornerDirection === Facing::EAST){ $this->plotBeginPos = $this->plotBeginPos->subtract(0, 0, $roadWidth); $this->plotBeginPos = $this->plotBeginPos->add($plotSize, 0, 0); - }elseif($cornerDirection === Facing::WEST) { + }elseif($cornerDirection === Facing::WEST){ $this->plotBeginPos = $this->plotBeginPos->subtract($roadWidth, 0, $roadWidth); } - }elseif(($start->X - $end->X) === -1) { // East X+ - if($cornerDirection === Facing::NORTH) { + }elseif(($start->X - $end->X) === -1){ // East X+ + if($cornerDirection === Facing::NORTH){ $this->plotBeginPos = $this->plotBeginPos->add($plotSize, 0, 0); $this->plotBeginPos = $this->plotBeginPos->subtract(0, 0, $roadWidth); - }elseif($cornerDirection === Facing::SOUTH) { + }elseif($cornerDirection === Facing::SOUTH){ $this->plotBeginPos = $this->plotBeginPos->add($plotSize, 0, $plotSize); } - }elseif(($start->Z - $end->Z) === -1) { // South Z+ - if($cornerDirection === Facing::EAST) { + }elseif(($start->Z - $end->Z) === -1){ // South Z+ + if($cornerDirection === Facing::EAST){ $this->plotBeginPos = $this->plotBeginPos->add($plotSize, 0, $plotSize); $this->plotBeginPos = $this->plotBeginPos->add($plotSize, 0, 0); - }elseif($cornerDirection === Facing::WEST) { + }elseif($cornerDirection === Facing::WEST){ $this->plotBeginPos = $this->plotBeginPos->add(0, 0, $plotSize); $this->plotBeginPos = $this->plotBeginPos->subtract($roadWidth, 0, 0); } - }elseif(($start->X - $end->X) === 1) { // West X- - if($cornerDirection === Facing::NORTH) { + }elseif(($start->X - $end->X) === 1){ // West X- + if($cornerDirection === Facing::NORTH){ $this->plotBeginPos = $this->plotBeginPos->subtract($roadWidth, 0, $roadWidth); - }elseif($cornerDirection === Facing::SOUTH) { + }elseif($cornerDirection === Facing::SOUTH){ $this->plotBeginPos = $this->plotBeginPos->add(0, 0, $plotSize); $this->plotBeginPos = $this->plotBeginPos->subtract($roadWidth, 0, 0); } @@ -82,11 +72,11 @@ public function __construct(MyPlot $plugin, Plot $start, Plot $end, int $cornerD $plugin->getLogger()->debug("Corner Correction Task started between plots $start->X;$start->Z and $end->X;$end->Z"); } - public function onRun() : void { - foreach($this->level->getEntities() as $entity) { - if($entity->getPosition()->x > $this->pos->x - 1 and $entity->getPosition()->x < $this->xMax + 1) { - if($entity->getPosition()->z > $this->pos->z - 1 and $entity->getPosition()->z < $this->zMax + 1) { - if(!$entity instanceof Player) { + public function onRun() : void{ + foreach($this->level->getEntities() as $entity){ + if($entity->getPosition()->x > $this->pos->x - 1 and $entity->getPosition()->x < $this->xMax + 1){ + if($entity->getPosition()->z > $this->pos->z - 1 and $entity->getPosition()->z < $this->zMax + 1){ + if(!$entity instanceof Player){ $entity->flagForDespawn(); }else{ $this->plugin->teleportPlayerToPlot($entity, $this->start); @@ -95,9 +85,9 @@ public function onRun() : void { } } $blocks = 0; - while($this->pos->x < $this->xMax) { - while($this->pos->z < $this->zMax) { - while($this->pos->y < $this->level->getMaxY()) { + while($this->pos->x < $this->xMax){ + while($this->pos->z < $this->zMax){ + while($this->pos->y < $this->level->getMaxY()){ if($this->pos->y === 0) $block = $this->bottomBlock; elseif($this->pos->y < $this->height) @@ -110,7 +100,7 @@ public function onRun() : void { $this->pos->y++; $blocks++; - if($blocks >= $this->maxBlocksPerTick) { + if($blocks >= $this->maxBlocksPerTick){ $this->setHandler(null); $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); throw new CancelTaskException(); diff --git a/src/MyPlot/task/FillPlotTask.php b/src/MyPlot/task/FillPlotTask.php index 9bcb1e56..19a4236e 100644 --- a/src/MyPlot/task/FillPlotTask.php +++ b/src/MyPlot/task/FillPlotTask.php @@ -3,104 +3,77 @@ namespace MyPlot\task; use MyPlot\MyPlot; -use MyPlot\Plot; +use MyPlot\plot\BasePlot; +use MyPlot\PlotLevelSettings; use pocketmine\block\Block; use pocketmine\block\VanillaBlocks; +use pocketmine\math\AxisAlignedBB; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\scheduler\CancelTaskException; use pocketmine\scheduler\Task; -use pocketmine\world\Position; use pocketmine\world\World; -class FillPlotTask extends Task { - /** @var MyPlot $plugin */ - protected $plugin; - /** @var Plot $plot */ - protected $plot; - /** @var World|null $level */ - protected $level; - /** @var int $height */ - protected $height; - /** @var Block $fillBlock */ - protected $fillBlock; - /** @var Block $bottomBlock */ - protected $bottomBlock; - /** @var Position|null $plotBeginPos */ - protected $plotBeginPos; - /** @var int $xMax */ - protected $xMax; - /** @var int $zMax */ - protected $zMax; - /** @var int $maxBlocksPerTick */ - protected $maxBlocksPerTick; - /** @var Vector3 $pos */ - protected $pos; +class FillPlotTask extends Task{ + protected AxisAlignedBB $aabb; + protected Vector3 $plotBeginPos; + protected PlotLevelSettings $plotLevel; + protected Vector3 $pos; + protected World $world; - /** - * FillPlotTask constructor. - * - * @param MyPlot $plugin - * @param Plot $plot - * @param int $maxBlocksPerTick - */ - public function __construct(MyPlot $plugin, Plot $plot, Block $plotFillBlock, int $maxBlocksPerTick = 256) { - $this->plugin = $plugin; - $this->plot = $plot; - $this->plotBeginPos = $plugin->getPlotPosition($plot); - $this->level = $this->plotBeginPos->getWorld(); - $plotLevel = $plugin->getLevelSettings($plot->levelName); - $plotSize = $plotLevel->plotSize; - $this->xMax = (int)($this->plotBeginPos->x + $plotSize); - $this->zMax = (int)($this->plotBeginPos->z + $plotSize); - $this->height = $plotLevel->groundHeight; - $this->fillBlock = $plotFillBlock; - $this->bottomBlock = $plotLevel->bottomBlock; - $this->maxBlocksPerTick = $maxBlocksPerTick; - $this->pos = new Vector3($this->plotBeginPos->x, 0, $this->plotBeginPos->z); + public function __construct(private MyPlot $plugin, private BasePlot $plot, private Block $plotFillBlock, private int $maxBlocksPerTick = 256){ + $this->world = $this->plugin->getServer()->getWorldManager()->getWorldByName($plot->levelName); + $this->plotLevel = $plugin->getLevelSettings($plot->levelName); + $this->aabb = $aabb = $this->plugin->getPlotBB($plot); + $this->plotBeginPos = $this->pos = new Vector3( + $aabb->minX, + $aabb->minY, + $aabb->minZ + ); $plugin->getLogger()->debug("Plot Fill Task started at plot $plot->X;$plot->Z"); } - public function onRun() : void { - foreach($this->level->getEntities() as $entity) { - if($this->plugin->getPlotBB($this->plot)->isVectorInXZ($entity->getPosition())) { - if(!$entity instanceof Player) { + public function onRun() : void{ + foreach($this->world->getEntities() as $entity){ + if($this->aabb->isVectorInXZ($entity->getPosition()) and + $entity->getPosition()->y <= $this->plotLevel->groundHeight + ){ + if(!$entity instanceof Player){ $entity->flagForDespawn(); - }else { + }else{ $this->plugin->teleportPlayerToPlot($entity, $this->plot); } } } $blocks = 0; - while($this->pos->x < $this->xMax) { - while($this->pos->z < $this->zMax) { - while($this->pos->y < $this->level->getMaxY()) { - if($this->pos->y === 0) { - $block = $this->bottomBlock; - }elseif($this->pos->y <= $this->height) { - $block = $this->fillBlock; - }else { + for(; $this->pos->x < $this->aabb->maxX; ++$this->pos->x, $this->pos->z = $this->aabb->minZ){ + for(; $this->pos->z < $this->aabb->maxZ; ++$this->pos->z, $this->pos->y = $this->aabb->minY){ + for(; $this->pos->y < $this->aabb->maxY; ++$this->pos->y){ + if($this->pos->y === $this->aabb->minY) + $block = $this->plotLevel->bottomBlock; + elseif($this->pos->y < $this->plotLevel->groundHeight) + $block = $this->plotFillBlock; + else $block = VanillaBlocks::AIR(); - } - $this->level->setBlock($this->pos, $block, false); - $blocks++; - if($blocks >= $this->maxBlocksPerTick) { + $this->world->setBlock($this->pos, $block, false); + + if(++$blocks >= $this->maxBlocksPerTick){ $this->setHandler(null); $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); throw new CancelTaskException(); } - $this->pos->y++; } - $this->pos->y = 0; - $this->pos->z++; } - $this->pos->z = $this->plotBeginPos->z; - $this->pos->x++; } - foreach($this->plugin->getPlotChunks($this->plot) as [$chunkX, $chunkZ, $chunk]) { - foreach($chunk->getTiles() as $tile) { - $tile->close(); - } + foreach($this->plugin->getPlotChunks($this->plot) as [$chunkX, $chunkZ, $chunk]){ + if($chunk === null) + continue; + foreach($chunk->getTiles() as $tile) + if($this->aabb->isVectorInXZ($tile->getPosition()) and + $tile->getPosition()->y <= $this->plotLevel->groundHeight + ){ + $tile->close(); + } } $this->plugin->getLogger()->debug("Plot Fill task completed at {$this->plotBeginPos->x};{$this->plotBeginPos->z}"); } diff --git a/src/MyPlot/task/RoadFillTask.php b/src/MyPlot/task/RoadFillTask.php index 1d4adde4..977f9304 100644 --- a/src/MyPlot/task/RoadFillTask.php +++ b/src/MyPlot/task/RoadFillTask.php @@ -3,121 +3,170 @@ namespace MyPlot\task; use MyPlot\MyPlot; -use MyPlot\Plot; -use pocketmine\block\Block; +use MyPlot\plot\MergedPlot; +use MyPlot\PlotLevelSettings; use pocketmine\block\VanillaBlocks; +use pocketmine\math\Axis; +use pocketmine\math\AxisAlignedBB; use pocketmine\math\Facing; use pocketmine\math\Vector3; use pocketmine\player\Player; use pocketmine\scheduler\CancelTaskException; use pocketmine\scheduler\Task; +use pocketmine\world\format\Chunk; use pocketmine\world\World; class RoadFillTask extends Task{ - protected MyPlot $plugin; - protected Plot $start; - protected Plot $end; - protected World $level; - protected int $height; - protected ?Vector3 $plotBeginPos; - protected int $xMax; - protected int $zMax; - protected Block $roadBlock; - protected Block $groundBlock; - protected Block $bottomBlock; - protected int $maxBlocksPerTick; - protected Vector3 $pos; - protected bool $fillCorner; - protected int $cornerDirection = -1; - - public function __construct(MyPlot $plugin, Plot $start, Plot $end, bool $fillCorner = false, int $cornerDirection = -1, int $maxBlocksPerTick = 256) { - if($start->isSame($end)) - throw new \Exception("Plot arguments cannot be the same plot or already be merged"); + public const LOW_BORDER = 0; + public const HIGH_BORDER = 1; + public const BOTH_BORDERS = 2; - $this->plugin = $plugin; - $this->start = $start; - $this->end = $end; - $this->fillCorner = $fillCorner; - $this->cornerDirection = $cornerDirection === -1 ? -1 : Facing::opposite($cornerDirection); - - $this->plotBeginPos = $plugin->getPlotPosition($start, false); - $this->level = $this->plotBeginPos->getWorld(); + protected AxisAlignedBB $aabb; + protected Vector3 $plotBeginPos; + protected PlotLevelSettings $plotLevel; + protected Vector3 $pos; + protected World $world; - $plotLevel = $plugin->getLevelSettings($start->levelName); + public function __construct(private MyPlot $plugin, private MergedPlot $start, private int $direction, private int $handleBorder = self::BOTH_BORDERS, private int $maxBlocksPerTick = 256){ + $this->world = $this->plugin->getServer()->getWorldManager()->getWorldByName($start->levelName); + $this->plotLevel = $plotLevel = $plugin->getLevelSettings($start->levelName); $plotSize = $plotLevel->plotSize; - $roadWidth = $plotLevel->roadWidth; - $this->height = $plotLevel->groundHeight; - $this->roadBlock = $plotLevel->plotFloorBlock; - $this->groundBlock = $plotLevel->plotFillBlock; - $this->bottomBlock = $plotLevel->bottomBlock; - - if(($start->Z - $end->Z) === 1){ // North Z- - $this->plotBeginPos = $this->plotBeginPos->subtract(0, 0, $roadWidth); - $this->xMax = (int) ($this->plotBeginPos->x + $plotSize); - $this->zMax = (int) ($this->plotBeginPos->z + $roadWidth); - }elseif(($start->X - $end->X) === -1){ // East X+ - $this->plotBeginPos = $this->plotBeginPos->add($plotSize, 0, 0); - $this->xMax = (int) ($this->plotBeginPos->x + $roadWidth); - $this->zMax = (int) ($this->plotBeginPos->z + $plotSize); - }elseif(($start->Z - $end->Z) === -1){ // South Z+ - $this->plotBeginPos = $this->plotBeginPos->add(0, 0, $plotSize); - $this->xMax = (int) ($this->plotBeginPos->x + $plotSize); - $this->zMax = (int) ($this->plotBeginPos->z + $roadWidth); - }elseif(($start->X - $end->X) === 1){ // West X- - $this->plotBeginPos = $this->plotBeginPos->subtract($roadWidth, 0, 0); - $this->xMax = (int) ($this->plotBeginPos->x + $roadWidth); - $this->zMax = (int) ($this->plotBeginPos->z + $plotSize); - } - - $this->maxBlocksPerTick = $maxBlocksPerTick; - $this->pos = new Vector3($this->plotBeginPos->x, 0, $this->plotBeginPos->z); + $totalSize = $plotSize + $plotLevel->roadWidth; + $aabb = $plugin->getPlotBB($start); + $this->aabb = $aabb = match ($direction) { + Facing::NORTH => new AxisAlignedBB( + $aabb->minX, + $aabb->minY, + $aabb->minZ - $plotLevel->roadWidth, + $aabb->maxX, + $aabb->maxY, + $aabb->minZ + ), + Facing::EAST => new AxisAlignedBB( + $aabb->maxX + ($totalSize * ($this->start->xWidth - 1)), + $aabb->minY, + $aabb->minZ, + $aabb->maxX + ($totalSize * ($this->start->xWidth - 1)) + $plotLevel->roadWidth, + $aabb->maxY, + $aabb->maxZ + ), + Facing::SOUTH => new AxisAlignedBB( + $aabb->minX, + $aabb->minY, + $aabb->maxZ + ($totalSize * ($this->start->zWidth - 1)), + $aabb->maxX, + $aabb->maxY, + $aabb->maxZ + ($totalSize * ($this->start->zWidth - 1)) + $plotLevel->roadWidth + ), + Facing::WEST => new AxisAlignedBB( + $aabb->minX - $plotLevel->roadWidth, + $aabb->minY, + $aabb->minZ, + $aabb->minX, + $aabb->maxY, + $aabb->maxZ + ), + default => throw new \InvalidArgumentException("Invalid direction $direction") + }; + $this->plotBeginPos = $this->pos = new Vector3( + $aabb->minX, + $aabb->minY, + $aabb->minZ + ); - $plugin->getLogger()->debug("Road Clear Task started between plots $start->X;$start->Z and $end->X;$end->Z"); + $plugin->getLogger()->debug("Road Clear Task started between plots $start->X;$start->Z facing" . Facing::toString($direction)); } - public function onRun() : void { - foreach($this->level->getEntities() as $entity) { - if($entity->getPosition()->x > $this->pos->x - 1 and $entity->getPosition()->x < $this->xMax + 1) { - if($entity->getPosition()->z > $this->pos->z - 1 and $entity->getPosition()->z < $this->zMax + 1) { - if(!$entity instanceof Player){ - $entity->flagForDespawn(); - }else{ - $this->plugin->teleportPlayerToPlot($entity, $this->start); - } + public function onRun() : void{ + foreach($this->world->getEntities() as $entity){ + if($this->aabb->isVectorInXZ($entity->getPosition())){ + if(!$entity instanceof Player){ + $entity->flagForDespawn(); + }else{ + $this->plugin->teleportPlayerToPlot($entity, $this->start); } } } $blocks = 0; - while($this->pos->x < $this->xMax) { - while($this->pos->z < $this->zMax) { - while($this->pos->y < $this->level->getMaxY()) { - if($this->pos->y === 0) - $block = $this->bottomBlock; - elseif($this->pos->y < $this->height) - $block = $this->groundBlock; - elseif($this->pos->y === $this->height) - $block = $this->roadBlock; + for(; $this->pos->x < $this->aabb->maxX; ++$this->pos->x, $this->pos->z = $this->aabb->minZ){ + for(; $this->pos->z < $this->aabb->maxZ; ++$this->pos->z, $this->pos->y = $this->aabb->minY){ + for(; $this->pos->y < $this->aabb->maxY; ++$this->pos->y){ + if($this->pos->y === $this->aabb->minY) + $block = $this->plotLevel->bottomBlock; + elseif($this->pos->y < $this->plotLevel->groundHeight) + $block = $this->plotLevel->plotFillBlock; + elseif($this->pos->y === $this->plotLevel->groundHeight) + $block = $this->plotLevel->plotFloorBlock; + elseif($this->pos->y === $this->plotLevel->groundHeight + 1 and + ( + ( + Facing::axis($this->direction) === Axis::X and + ( + ( + ( + $this->handleBorder === self::LOW_BORDER or + $this->handleBorder === self::BOTH_BORDERS + ) and + $this->pos->z === $this->aabb->maxZ + ) or ( + ( + $this->handleBorder === self::HIGH_BORDER or + $this->handleBorder === self::BOTH_BORDERS + ) and + $this->pos->z === $this->aabb->minZ + ) + ) + ) or ( + Facing::axis($this->direction) === Axis::Z and + ( + ( + ( + $this->handleBorder === self::LOW_BORDER or + $this->handleBorder === self::BOTH_BORDERS + ) and + $this->pos->x === $this->aabb->maxX + ) or ( + ( + $this->handleBorder === self::HIGH_BORDER or + $this->handleBorder === self::BOTH_BORDERS + ) and + $this->pos->x === $this->aabb->minX + ) + ) + ) + ) + ) + $block = $this->plotLevel->wallBlock; else $block = VanillaBlocks::AIR(); + $this->world->setBlock($this->pos, $block, false); - $this->level->setBlock($this->pos, $block, false); - $this->pos->y++; - - $blocks++; - if($blocks >= $this->maxBlocksPerTick) { + if(++$blocks >= $this->maxBlocksPerTick){ $this->setHandler(null); $this->plugin->getScheduler()->scheduleDelayedTask($this, 1); throw new CancelTaskException(); } } - $this->pos->y = 0; - $this->pos->z++; } - $this->pos->z = $this->plotBeginPos->z; - $this->pos->x++; } - $this->plugin->getLogger()->debug("Plot Road Clear task completed at {$this->start->X};{$this->start->Z}"); - $this->plugin->getScheduler()->scheduleTask(new BorderCorrectionTask($this->plugin, $this->start, $this->end, $this->fillCorner, $this->cornerDirection)); + $aabb = $this->aabb; + $xMin = $aabb->minX >> Chunk::COORD_MASK; + $zMin = $aabb->minZ >> Chunk::COORD_MASK; + $xMax = $aabb->maxX >> Chunk::COORD_MASK; + $zMax = $aabb->maxZ >> Chunk::COORD_MASK; + + $level = $this->plugin->getServer()->getWorldManager()->getWorldByName($this->start->levelName); + for($x = $xMin; $x <= $xMax; ++$x){ + for($z = $zMin; $z <= $zMax; ++$z){ + $chunk = $level->getChunk($x, $z); + if($chunk === null) + continue; + foreach($chunk->getTiles() as $tile) + if($aabb->isVectorInXZ($tile->getPosition())) + $tile->close(); + } + } + $this->plugin->getLogger()->debug("Plot Road Clear task completed at {$this->start->X};{$this->start->Z}"); } } \ No newline at end of file diff --git a/src/MyPlot/utils/AsyncVariants.php b/src/MyPlot/utils/AsyncVariants.php index 2a13951d..585634ed 100644 --- a/src/MyPlot/utils/AsyncVariants.php +++ b/src/MyPlot/utils/AsyncVariants.php @@ -6,7 +6,7 @@ class AsyncVariants{ public static function array_map(?callable $callback, array $array, array ...$arrays) : \Generator{ $result = []; foreach([$array, ...$arrays] as $key => $value){ - $result[$key] = $callback === null ? $value : yield $callback($value, $key); + $result[$key] = $callback === null ? $value : yield from $callback($value, $key); } return $result; } diff --git a/src/MyPlot/utils/Utils.php b/src/MyPlot/utils/Utils.php new file mode 100644 index 00000000..6bd62729 --- /dev/null +++ b/src/MyPlot/utils/Utils.php @@ -0,0 +1,24 @@ +maxX - $alignedBB->minX; + $height = $alignedBB->maxY - $alignedBB->minY; + $length = $alignedBB->maxZ - $alignedBB->minZ; + if($width <= 0 or $length <= 0 or $height <= 0) + throw new \InvalidArgumentException("AxisAlignedBB cannot have a width, length, or height of 0"); + + return match ($axis) { + Axis::X => new AxisAlignedBB(0, 0, 0, $width, $length, $height), + Axis::Y => new AxisAlignedBB(0, 0, 0, $length, $height, $width), + Axis::Z => new AxisAlignedBB(0, 0, 0, $height, $width, $length), + default => throw new \InvalidArgumentException("Invalid axis $axis") + }; + } +} \ No newline at end of file From 3056bcab9c1f80812d4a58b086c430b7fd75bf5d Mon Sep 17 00:00:00 2001 From: AIPTU <85402087+AIPTU@users.noreply.github.com> Date: Fri, 8 Apr 2022 04:05:05 +0700 Subject: [PATCH 45/47] Fix await-generator (#473) --- .poggit.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.poggit.yml b/.poggit.yml index 1348ff25..56b32546 100644 --- a/.poggit.yml +++ b/.poggit.yml @@ -6,7 +6,7 @@ projects: libs: - src: poggit/libasynql/libasynql version: ^3.3.0 - - src: SOFe/AwaitGenerator/await-generator + - src: SOF3/await-generator/await-generator version: ^3.1.1 - src: dktapps-pm-pl/pmforms/pmforms version: ^2.0.0 @@ -19,4 +19,4 @@ projects: - .gitignore - CONTRIBUTING.md - SECURITY.md -... \ No newline at end of file +... From ce4e7c4369d8422f768ba1d346841db842a3f9a7 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Thu, 7 Apr 2022 17:10:03 -0400 Subject: [PATCH 46/47] Fixed bad argument --- src/MyPlot/forms/subforms/InfoForm.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/MyPlot/forms/subforms/InfoForm.php b/src/MyPlot/forms/subforms/InfoForm.php index 46d5a3f7..4ce915c4 100644 --- a/src/MyPlot/forms/subforms/InfoForm.php +++ b/src/MyPlot/forms/subforms/InfoForm.php @@ -53,9 +53,7 @@ function(string $text) : string{ return TextFormat::DARK_BLUE . ucfirst(strtolower(str_replace("_", " ", $text))); }, array_keys(BiomeSubCommand::BIOMES) - ), - (int) array_search($plot->biome, array_keys(BiomeSubCommand::BIOMES), true) - )); + ))); $this->addEntry(new LabelEntry($plugin->getLanguage()->translateString("info.formpvp", [$plot->pvp ? "Enabled" : "Disabled"]))); // TODO: translations } } \ No newline at end of file From 1a0dc77c35377e2903b4fac4478470375c775fc1 Mon Sep 17 00:00:00 2001 From: jasonwynn10 Date: Thu, 7 Apr 2022 17:10:26 -0400 Subject: [PATCH 47/47] capitalization change --- resources/mysql.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/mysql.sql b/resources/mysql.sql index 215e52c9..64796fbe 100644 --- a/resources/mysql.sql +++ b/resources/mysql.sql @@ -130,7 +130,7 @@ FROM plotsV2 ON mergedPlotsV2.level = plotsV2.level AND mergedX = X AND mergedZ = Z -WHERE mergedplotsV2.level = :level +WHERE mergedPlotsV2.level = :level AND originX = :originX AND originZ = :originZ; -- # }