Created
April 12, 2017 17:33
-
-
Save Kris-Driv/1599e55ea8275104eb2a7018c5d23415 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace schematic; | |
use pocketmine\nbt\NBT; | |
use pocketmine\utils\Binary; | |
use pocketmine\block\Block; | |
use pocketmine\item\Item; | |
use pocketmine\Server; | |
class Schematic { | |
/** | |
* For schematics exported from Minecraft Alpha and newer | |
*/ | |
const MATERIALS_ALPHA = "Alpha"; | |
/** | |
* For schematics exported from Minecraft Classic | |
*/ | |
const MATERIALS_CLASSIC = "Classic"; | |
/** | |
* Fallback | |
*/ | |
const MATERIALS_UNKNOWN = "Unknown"; | |
/** | |
* Order YXZ: | |
* Height - Along Y axis | |
* Width - Along X axis | |
* Length - Along Z axis | |
* @var int | |
*/ | |
protected $height, $width, $length; | |
/** @var Block[] */ | |
protected $blocks = []; | |
/** @var string */ | |
protected $materials = self::MATERIALS_UNKNOWN; | |
/** @var CompoundTag */ | |
protected $entities; | |
/** @var CompoundTag */ | |
protected $tileEntities; | |
protected $raw; | |
/** | |
* @param string $data Schematic file contents | |
*/ | |
public function __construct(string $data) { | |
$this->raw = $data; | |
} | |
/** | |
* Raw -> NBT -> Class properties | |
*/ | |
public function decode() { | |
if(empty($this->raw)) { | |
throw new \InvalidStateException("no data to decode"); | |
} | |
try{ | |
$nbt = $this->getNBT(); | |
$data = $nbt->getData(); | |
$this->width = $data["Width"]; | |
$this->height = $data["Height"]; | |
$this->length = $data["Length"]; | |
$this->materials = $data["Materials"]; | |
$this->blocks = self::decodeBlocks($data["Blocks"], $data["Data"], $this->height, $this->width, $this->length); | |
$this->entities = $data["Entities"]; | |
$this->tileEntities = $data["TileEntities"]; | |
}catch(\Throwable $e){ //zlib decode error / corrupt data | |
Server::getInstance()->getLogger()->error("Error decoding schematic: ".$e->getMessage()); | |
} | |
} | |
/** | |
* Class properties into NBT -> Raw | |
*/ | |
public function encode() { | |
} | |
public function fixBlockIds() { | |
$replace = null; | |
foreach ($this->blocks as $k => $block) { | |
switch ($block->getId()) { | |
case 126: | |
$replace = Block::get(Item::WOOD_SLAB); | |
break; | |
case 95: | |
$replace = Block::get(Item::GLASS); | |
break; | |
case 160: | |
$replace = Block::get(Item::GLASS_PANE); | |
break; | |
case 125: | |
$replace = Block::get(Item::DOUBLE_WOODEN_SLAB); | |
break; | |
case 188: | |
$replace = Block::get(Item::FENCE, 1); | |
break; | |
case 189: | |
$replace = Block::get(Item::FENCE, 2); | |
break; | |
case 190: | |
$replace = Block::get(Item::FENCE, 3); | |
break; | |
case 191: | |
$replace = Block::get(Item::FENCE, 4); | |
break; | |
case 192: | |
$replace = Block::get(Item::FENCE, 5); | |
break; | |
default: | |
break; | |
} | |
if($replace) { | |
$this->blocks[$k] = $replace; | |
} | |
$replace = null; | |
} | |
} | |
public function getBlocks(): array { | |
return $this->blocks; | |
} | |
public function setBlocks(array $blocks) { | |
$this->blocks = $blocks; | |
} | |
public function getMaterials(): string { | |
return $this->materials; | |
} | |
public function setMaterials(string $materials) { | |
$this->materials = $materials; | |
} | |
public function getEntities() { | |
return $this->entities; | |
} | |
public function setEntities($entities) { | |
$this->entities; | |
} | |
public function getTileEntities() { | |
return $this->tileEntities; | |
} | |
public function setTileEntities($entities) { | |
$this->tileEntities = $entities; | |
} | |
public function getNBT() { | |
$nbt = new NBT(NBT::BIG_ENDIAN); | |
$nbt->readCompressed($this->raw); | |
return $nbt; | |
} | |
public function setNBT(NBT $nbt) { | |
$this->nbt = $nbt; | |
} | |
public function getLength(): int { | |
return $this->length; | |
} | |
public function getHeight(): int { | |
return $this->height; | |
} | |
public function getWidth(): int { | |
return $this->width; | |
} | |
public static function decodeBlocks(string $blocks, string $meta, int $height, int $width, int $length): array { | |
$bytes = array_values(unpack("c*", $blocks)); | |
$meta = array_values(unpack("c*", $meta)); | |
$realBlocks = []; | |
for ($x=0; $x < $width; $x++) { | |
for ($y=0; $y < $height; $y++) { | |
for ($z=0; $z < $length; $z++) { | |
$index = ($y*$length + $z)*$width + $x; | |
$block = Block::get($bytes[$index]); | |
$block->setComponents($x, $y, $z); | |
if(isset($meta[$index])) { | |
$block->setDamage($meta[$index] & 0x0F); | |
} | |
$realBlocks[] = $block; | |
} | |
} | |
} | |
return $realBlocks; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment