Skip to content

Commit

Permalink
Update to api 4.0.0-beta3, new /img place command
Browse files Browse the repository at this point in the history
  • Loading branch information
VixikHD committed Oct 3, 2021
1 parent afa4409 commit 9bd5df0
Show file tree
Hide file tree
Showing 11 changed files with 433 additions and 132 deletions.
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@
"ext-yaml": "*",
"ext-pthreads": "*",
"ext-json": "*",
"pocketmine/pocketmine-mp": "dev-master",
"pocketmine/pocketmine-mp": "4.0.0-BETA3",
"ext-gd": "*"
},
"require-dev": {
"phpstan/phpstan": "0.12.83"
"phpstan/phpstan": "0.12.99"
},
"autoload": {
"psr-4": {
Expand Down
218 changes: 152 additions & 66 deletions composer.lock

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions src/czechpmdevs/imageonmap/DataProviderTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@ trait DataProviderTrait {
*/
public function loadCachedMaps(string $path): void {
$files = glob($path . "/map_*.dat");
if(!$files) {
if (!$files) {
return;
}

$serializer = new BigEndianNbtSerializer();
foreach ($files as $file) {
$content = file_get_contents($file);
if(!$content) {
if (!$content) {
throw new InvalidStateException("Could not access file $file"); // TODO - Better name
}

$this->cachedMaps[(int) substr(basename($file, ".dat"), 4)] = Image::load($serializer->read($content)->mustGetCompoundTag());
$this->cachedMaps[(int)substr(basename($file, ".dat"), 4)] = Image::load($serializer->read($content)->mustGetCompoundTag());
}
}

Expand All @@ -67,15 +67,15 @@ public function loadCachedMaps(string $path): void {
public function saveCachedMaps(string $path): void {
$serializer = new BigEndianNbtSerializer();
foreach ($this->cachedMaps as $id => $map) {
if(!file_put_contents($file = "$path/map_$id.dat", $serializer->write(new TreeRoot($map->save())))) {
if (!file_put_contents($file = "$path/map_$id.dat", $serializer->write(new TreeRoot($map->save())))) {
throw new InvalidStateException("Could not access file $file"); // TODO - Better name
}
}
}

public function getImageFromFile(string $file, int $chunkCount, int $xOffset, int $yOffset): int {
$id = crc32(hash_file("md5", $file) . "$chunkCount:$xOffset:$yOffset");
if(!array_key_exists($id, $this->cachedMaps)) {
if (!array_key_exists($id, $this->cachedMaps)) {
$this->cachedMaps[$id] = ImageLoader::loadImage($file, $chunkCount, $xOffset, $yOffset);
}

Expand Down
5 changes: 2 additions & 3 deletions src/czechpmdevs/imageonmap/ImageOnMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
use czechpmdevs\imageonmap\command\ImageCommand;
use czechpmdevs\imageonmap\image\BlankImage;
use czechpmdevs\imageonmap\item\FilledMap;
use czechpmdevs\imageonmap\utils\Image;
use pocketmine\event\Listener;
use pocketmine\event\server\DataPacketReceiveEvent;
use pocketmine\item\ItemFactory;
Expand Down Expand Up @@ -64,11 +63,11 @@ protected function onDisable(): void {

public function onDataPacketReceive(DataPacketReceiveEvent $event): void {
$packet = $event->getPacket();
if(!$packet instanceof MapInfoRequestPacket) {
if (!$packet instanceof MapInfoRequestPacket) {
return;
}

if(!array_key_exists($packet->mapId, $this->cachedMaps)) {
if (!array_key_exists($packet->mapId, $this->cachedMaps)) {
$event->getOrigin()->sendDataPacket(BlankImage::get()->getPacket($packet->mapId));
$this->getLogger()->debug("Unknown map id $packet->mapId received from {$event->getOrigin()->getDisplayName()}");
return;
Expand Down
190 changes: 190 additions & 0 deletions src/czechpmdevs/imageonmap/ImagePlaceSession.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
<?php

declare(strict_types=1);

namespace czechpmdevs\imageonmap;

use czechpmdevs\imageonmap\item\FilledMap;
use pocketmine\block\Block;
use pocketmine\block\ItemFrame;
use pocketmine\block\VanillaBlocks;
use pocketmine\event\block\BlockBreakEvent;
use pocketmine\event\HandlerListManager;
use pocketmine\event\Listener;
use pocketmine\event\player\PlayerChatEvent;
use pocketmine\event\player\PlayerQuitEvent;
use pocketmine\math\Facing;
use pocketmine\player\Player;
use pocketmine\utils\AssumptionFailedError;
use pocketmine\world\Position;
use function max;
use function min;

class ImagePlaceSession implements Listener {
private Position $firstPosition;
private Position $secondPosition;

public function __construct(
private Player $player,
private string $imageFile,
private ImageOnMap $plugin
) {}

public function run(): void {
$this->player->sendMessage("§aBreak first ItemFrame.");
$this->plugin->getServer()->getPluginManager()->registerEvents($this, $this->plugin);
}

public function onBreak(BlockBreakEvent $event): void {
$player = $event->getPlayer();
if ($player->getId() != $this->player->getId()) {
$player->sendMessage("{$player->getId()}:{$this->player->getId()}");
return;
}

$event->cancel();

if (!$event->getBlock()->isSameType(VanillaBlocks::ITEM_FRAME())) {
$player->sendMessage("§6Block you want to place map on must be Item Frame.");
return;
}

if (!isset($this->firstPosition)) {
$player->sendMessage("§aFirst position set to {$event->getBlock()->getPosition()->getX()}, {$event->getBlock()->getPosition()->getY()}, {$event->getBlock()->getPosition()->getZ()}. Break second block.");
$this->firstPosition = clone $event->getBlock()->getPosition();
return;
}

if ($this->firstPosition->getWorld()->getId() != $event->getBlock()->getPosition()->getWorld()->getId()) {
$player->sendMessage("§cSecond positions must be in same world as the first one!");
return;
}

if (
$this->firstPosition->getX() != $event->getBlock()->getPosition()->getX() &&
$this->firstPosition->getZ() != $event->getBlock()->getPosition()->getZ()
) {
$player->sendMessage("§cImage could not be placed that way!");
return;
}

$player->sendMessage("§aSecond position set to {$event->getBlock()->getPosition()->getX()}, {$event->getBlock()->getPosition()->getY()}, {$event->getBlock()->getPosition()->getZ()}");
$this->secondPosition = clone $event->getBlock()->getPosition();

$this->finish();
}

public function onChat(PlayerChatEvent $event): void {
$player = $event->getPlayer();
if ($player->getId() != $this->player->getId()) {
return;
}

$event->cancel();

if ($event->getMessage() == "cancel") {
$player->sendMessage("§aImage placing cancelled");
$this->close();
return;
}

$player->sendMessage("§cYou are now in 'image-place-mode'. Type §lcancel§r§c to cancel image placement.");
}

public function onQuit(PlayerQuitEvent $event): void {
if ($event->getPlayer()->getId() == $this->player->getId()) {
$this->close();
}
}

private function finish(): void {
/** @var int $minX */
$minX = min($this->firstPosition->getX(), $this->secondPosition->getX());
/** @var int $maxX */
$maxX = max($this->firstPosition->getX(), $this->secondPosition->getX());
/** @var int $minY */
$minY = min($this->firstPosition->getY(), $this->secondPosition->getY());

/** @var int $maxY */
$maxY = max($this->firstPosition->getY(), $this->secondPosition->getY());
/** @var int $minZ */
$minZ = min($this->firstPosition->getZ(), $this->secondPosition->getZ());
/** @var int $maxZ */
$maxZ = max($this->firstPosition->getZ(), $this->secondPosition->getZ());

$world = $this->player->getPosition()->getWorld();

$getItemFrame = function (int $x, int $y, int $z) use ($world): ItemFrame {
$block = $world->getBlockAt($x, $y, $z, true, false);
if ($block instanceof ItemFrame) {
return $block;
}

$world->setBlockAt($x, $y, $z, VanillaBlocks::ITEM_FRAME());
$block = $world->getBlockAt($x, $y, $z, true, false);
if (!$block instanceof ItemFrame) {
throw new AssumptionFailedError("Block must be item frame");
}

return $block;
};

/** @var ItemFrame $pattern */
$pattern = $world->getBlock($this->secondPosition);

/** @var Block[] $blocks */
$blocks = [];

$height = $maxY - $minY;
if ($minX == $maxX) {
$width = $maxZ - $minZ;
if($pattern->getFacing() == Facing::NORTH) {
for ($x = 0; $x <= $width; ++$x) {
for ($y = 0; $y <= $height; ++$y) {
$blocks[] = $getItemFrame($minX, $minY + $y, $minZ + $x)
->setFramedItem(FilledMap::get()->setMapId($this->plugin->getImageFromFile($this->imageFile, $width + 1, $x, $height - $y)))
->setHasMap(true);
}
}
} else {
for ($x = 0; $x <= $width; ++$x) {
for ($y = 0; $y <= $height; ++$y) {
$blocks[] = $getItemFrame($minX, $minY + $y, $maxZ - $x)
->setFramedItem(FilledMap::get()->setMapId($this->plugin->getImageFromFile($this->imageFile, $width + 1, $x, $height - $y)))
->setHasMap(true);
}
}
}
} else {
$width = $maxX - $minX;
if($pattern->getFacing() == Facing::SOUTH) {
for ($x = 0; $x <= $width; ++$x) {
for ($y = 0; $y <= $height; ++$y) {
$blocks[] = $getItemFrame($minX + $x, $minY + $y, $minZ)
->setFramedItem(FilledMap::get()->setMapId($this->plugin->getImageFromFile($this->imageFile, $width + 1, $x, $height - $y)))
->setHasMap(true);
}
}
} else {
for ($x = 0; $x <= $width; ++$x) {
for ($y = 0; $y <= $height; ++$y) {
$blocks[] = $getItemFrame($maxX - $x, $minY + $y, $minZ)
->setFramedItem(FilledMap::get()->setMapId($this->plugin->getImageFromFile($this->imageFile, $width + 1, $x, $height - $y)))
->setHasMap(true);
}
}
}
}

foreach ($blocks as $block) {
$world->setBlock($block->getPosition(), $block);
}

$this->player->sendMessage("§aPicture placed!");
$this->close();
}

private function close(): void {
HandlerListManager::global()->unregisterAll($this);
}
}
Loading

0 comments on commit 9bd5df0

Please sign in to comment.