├── .gitignore ├── .poggit.yml ├── src └── xenialdan │ └── libstructure │ ├── PacketListener.php │ ├── StructureUI.php │ ├── packet │ ├── StructureBlockUpdatePacket.php │ ├── StructureEditorData.php │ └── StructureSettings.php │ ├── plans.md │ ├── tile │ └── StructureBlockTags.php │ └── window │ └── StructureBlockInventory.php └── virion.yml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea -------------------------------------------------------------------------------- /.poggit.yml: -------------------------------------------------------------------------------- 1 | --- # Poggit-CI Manifest. Open the CI at https://poggit.pmmp.io/ci/thebigsmileXD/libstructure 2 | branches: 3 | - master 4 | projects: 5 | libstructure: 6 | path: "" 7 | model: virion 8 | type: library 9 | ... 10 | -------------------------------------------------------------------------------- /src/xenialdan/libstructure/PacketListener.php: -------------------------------------------------------------------------------- 1 | getServer()->getPluginManager()->registerEvents(new self, $plugin); 45 | PacketPool::registerPacket(new StructureBlockUpdatePacket()); 46 | } 47 | 48 | public function onDataPacketReceiveEvent(DataPacketReceiveEvent $e) 49 | { 50 | if ($e->getPacket() instanceof StructureBlockUpdatePacket) $this->onStructureBlockUpdatePacket($e); 51 | if ($e->getPacket() instanceof StructureTemplateDataExportRequestPacket) $this->onStructureTemplateDataExportRequestPacket($e); 52 | if ($e->getPacket() instanceof StructureTemplateDataExportResponsePacket) $this->onStructureTemplateDataExportResponsePacket($e); 53 | } 54 | 55 | private function onStructureBlockUpdatePacket(DataPacketReceiveEvent $e) 56 | { 57 | if (!($pk = $e->getPacket()) instanceof StructureBlockUpdatePacket) throw new \InvalidArgumentException(get_class($pk) . " is not a " . StructureBlockUpdatePacket::class); 58 | /** @var StructureBlockUpdatePacket $pk */ 59 | var_dump($e->getPacket()); 60 | } 61 | 62 | private function onStructureTemplateDataExportRequestPacket(DataPacketReceiveEvent $e) 63 | { 64 | } 65 | 66 | private function onStructureTemplateDataExportResponsePacket(DataPacketReceiveEvent $e) 67 | { 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /src/xenialdan/libstructure/StructureUI.php: -------------------------------------------------------------------------------- 1 | readonly(); 40 | $this->fromV3 = $fromV3; 41 | $this->toV3 = $toV3; 42 | parent::__construct($menu, [], 0, $title); 43 | } 44 | 45 | /** 46 | * @param Vector3 $fromV3 47 | * @return StructureUI 48 | */ 49 | public function setFromV3(Vector3 $fromV3): StructureUI 50 | { 51 | $this->fromV3 = $fromV3; 52 | return $this; 53 | } 54 | 55 | /** 56 | * @param Vector3 $toV3 57 | * @return StructureUI 58 | */ 59 | public function setToV3(Vector3 $toV3): StructureUI 60 | { 61 | $this->toV3 = $toV3; 62 | return $this; 63 | } 64 | 65 | /** 66 | * @param string $title 67 | * @return StructureUI 68 | */ 69 | public function setTitle(string $title): StructureUI 70 | { 71 | $this->title = $title; 72 | return $this; 73 | } 74 | 75 | /** 76 | * @param bool $hideStructureBlock 77 | * @return StructureUI 78 | */ 79 | public function setHideStructureBlock(bool $hideStructureBlock): StructureUI 80 | { 81 | $this->hideStructureBlock = $hideStructureBlock; 82 | return $this; 83 | } 84 | 85 | /** 86 | * @param bool $showPlayers 87 | * @return StructureUI 88 | */ 89 | public function setShowPlayers(bool $showPlayers): StructureUI 90 | { 91 | $this->showPlayers = $showPlayers; 92 | return $this; 93 | } 94 | 95 | /** 96 | * @param bool $showEntities 97 | * @return StructureUI 98 | */ 99 | public function setShowEntities(bool $showEntities): StructureUI 100 | { 101 | $this->showEntities = $showEntities; 102 | return $this; 103 | } 104 | 105 | /** 106 | * @param bool $showBlocks 107 | * @return StructureUI 108 | */ 109 | public function setShowBlocks(bool $showBlocks): StructureUI 110 | { 111 | $this->showBlocks = $showBlocks; 112 | return $this; 113 | } 114 | 115 | /** 116 | * @param bool $showBoundingBox 117 | * @return StructureUI 118 | */ 119 | public function setShowBoundingBox(bool $showBoundingBox): StructureUI 120 | { 121 | $this->showBoundingBox = $showBoundingBox; 122 | return $this; 123 | } 124 | 125 | private function calculateOffset(Vector3 $holderV3): Vector3 126 | { 127 | return $holderV3->subtract(self::getMinV3($this->fromV3, $this->toV3))->multiply(-1)->floor(); 128 | } 129 | 130 | private function calculateSize(): Vector3 131 | { 132 | return $this->fromV3->subtract($this->toV3)->abs()->add(1, 1, 1); 133 | } 134 | 135 | /** 136 | * @param Vector3 $v1 137 | * @param Vector3 $v2 138 | * @return Vector3 139 | */ 140 | public static function getMinV3(Vector3 $v1, Vector3 $v2): Vector3 141 | { 142 | return (new Vector3(min($v1->x, $v2->x), min($v1->y, $v2->y), min($v1->z, $v2->z)))->floor(); 143 | } 144 | 145 | /** 146 | * @param Vector3 $v1 147 | * @param Vector3 $v2 148 | * @return Vector3 149 | */ 150 | public static function getMaxV3(Vector3 $v1, Vector3 $v2): Vector3 151 | { 152 | return (new Vector3(max($v1->x, $v2->x), max($v1->y, $v2->y), max($v1->z, $v2->z)))->floor(); 153 | } 154 | 155 | /* InvMenu */ 156 | 157 | protected function sendFakeBlockData(Player $player, HolderData $data): void 158 | { 159 | $block = $this->getBlock()->setComponents($data->position->x, $data->position->y, $data->position->z); 160 | $player->getLevel()->sendBlocks([$player], [$block]); 161 | 162 | $tag = new CompoundTag(); 163 | if ($data->custom_name !== null) { 164 | $tag->setString("CustomName", $data->custom_name); 165 | } 166 | $offset = $this->calculateOffset($block->asVector3()); 167 | $size = $this->calculateSize(); 168 | var_dump("offset", $offset, "size", $size, "blockV3", $block->asVector3()); 169 | $tag->setInt("data", (int)$this->mode); 170 | $tag->setString("dataField", ""); 171 | $tag->setByte("ignoreEntities", $this->showEntities ? 0 : 1); 172 | $tag->setByte("includePlayers", $this->showPlayers ? 1 : 0); 173 | $tag->setFloat("integrity", 100.0); 174 | $tag->setByte("isMovable", 1); 175 | $tag->setByte("isPowered", 0); 176 | $tag->setByte("mirror", 0); 177 | $tag->setByte("removeBlocks", $this->showBlocks ? 0 : 1); 178 | $tag->setByte("rotation", 0); 179 | $tag->setLong("seed", 0); 180 | $tag->setByte("showBoundingBox", $this->showBoundingBox ? 1 : 0); 181 | $tag->setString("structureName", $data->custom_name ?? $this->title ?? $this->getName()); 182 | $tag->setInt("x", (int)$block->x); 183 | $tag->setInt("xStructureOffset", (int)$offset->x); 184 | $tag->setInt("xStructureSize", (int)$size->x); 185 | $tag->setInt("y", (int)$block->y); 186 | $tag->setInt("yStructureOffset", (int)$offset->y); 187 | $tag->setInt("yStructureSize", (int)$size->y); 188 | $tag->setInt("z", (int)$block->z); 189 | $tag->setInt("zStructureOffset", (int)$offset->z); 190 | $tag->setInt("zStructureSize", (int)$size->z); 191 | var_dump($tag->toString()); 192 | 193 | $this->sendTile($player, $block, $tag); 194 | 195 | $this->onFakeBlockDataSend($player); 196 | } 197 | 198 | public function onFakeBlockDataSendSuccess(Player $player): void 199 | { 200 | var_dump($this); 201 | #parent::onFakeBlockDataSendSuccess($player); 202 | } 203 | 204 | public function getTileId(): string 205 | { 206 | return StructureBlockTags::TAG_ID; 207 | } 208 | 209 | public function getName(): string 210 | { 211 | return "Structure Block"; 212 | } 213 | 214 | public function getDefaultSize(): int 215 | { 216 | return 0; 217 | } 218 | 219 | /** 220 | * Returns the Minecraft PE inventory type used to show the inventory window to clients. 221 | * @return int 222 | */ 223 | public function getNetworkType(): int 224 | { 225 | return WindowTypes::STRUCTURE_EDITOR; 226 | } 227 | 228 | public function getBlock(): Block 229 | { 230 | return Block::get(Block::STRUCTURE_BLOCK, $this->mode); 231 | } 232 | } -------------------------------------------------------------------------------- /src/xenialdan/libstructure/packet/StructureBlockUpdatePacket.php: -------------------------------------------------------------------------------- 1 | getBlockPosition($this->x, $this->y, $this->z); 31 | $this->structureEditorData = $this->getStructureEditorData(); 32 | $this->unknownBool = $this->getBool(); 33 | $this->unknownBool2 = $this->getBool(); 34 | } 35 | 36 | protected function encodePayload() 37 | { 38 | $this->putBlockPosition($this->x, $this->y, $this->z); 39 | $this->putStructureEditorData($this->structureEditorData); 40 | $this->putBool($this->unknownBool); 41 | $this->putBool($this->unknownBool2); 42 | } 43 | 44 | public function handle(NetworkSession $session): bool 45 | { 46 | return $session->handleStructureBlockUpdate($this); 47 | } 48 | 49 | protected function getStructureEditorData(): StructureEditorData 50 | { 51 | $result = new StructureEditorData(); 52 | 53 | $result->structureName = $this->getString(); 54 | $result->string2 = $this->getString();//probably load/fileName in load mode 55 | $result->includePlayers = $this->getBool(); 56 | $result->showBoundingBox = $this->getBool(); 57 | $result->mode = $this->getVarInt(); 58 | $result->structureSettings = $this->getStructureSettings1(); 59 | //TODO 1.13 will probably add showInvisibleBlocks (bool) 60 | 61 | return $result; 62 | } 63 | 64 | protected function getStructureSettings1(): StructureSettings 65 | { 66 | $result = new StructureSettings(); 67 | 68 | $result->paletteName = $this->getString(); 69 | $result->ignoreEntities = $this->getBool(); 70 | $result->ignoreBlocks = $this->getBool(); 71 | $this->getBlockPosition($result->sizeX, $result->sizeY, $result->sizeZ);//structure size 72 | $this->getBlockPosition($result->offsetX, $result->offsetY, $result->offsetZ);//structure offset 73 | $result->lastTouchedByPlayerId = $this->getLong(); 74 | $result->rotation = $this->getByte(); 75 | $result->mirror = $this->getByte(); 76 | if (version_compare(ltrim(Server::getInstance()->getVersion(), 'v'), "1.13") === 0) { 77 | $result->integrityValue = $this->getFloat(); 78 | //$result->integritySeed = $this->getUnsignedVarInt();//actually UnsignedInt 79 | $result->integritySeed = intval($this->getRemaining());//hack 80 | } 81 | 82 | return $result; 83 | } 84 | 85 | protected function putStructureEditorData(StructureEditorData $data): void 86 | { 87 | $this->putString($data->structureName); 88 | $this->putString($data->string2);//probably load/fileName in load mode 89 | $this->putBool($data->includePlayers); 90 | $this->putBool($data->showBoundingBox); 91 | $this->putVarInt($data->mode); 92 | $this->putStructureSettings1($data->structureSettings); 93 | //TODO 1.13 will probably add showInvisibleBlocks (bool) 94 | } 95 | 96 | protected function putStructureSettings1(StructureSettings $settings): void 97 | { 98 | $this->putString($settings->paletteName); 99 | $this->putBool($settings->ignoreEntities); 100 | $this->putBool($settings->ignoreBlocks); 101 | $this->putBlockPosition($settings->sizeX, $settings->sizeY, $settings->sizeZ);//structure size 102 | $this->putBlockPosition($settings->offsetX, $settings->offsetY, $settings->offsetZ);//structure offset 103 | $this->putLong($settings->lastTouchedByPlayerId); 104 | $this->putByte($settings->rotation); 105 | $this->putByte($settings->mirror); 106 | if (version_compare(ltrim(Server::getInstance()->getVersion(), 'v'), "1.13") === 0) { 107 | $this->putFloat($settings->integrityValue); 108 | $this->putInt($settings->integritySeed);//hack//actually UnsignedInt 109 | } 110 | } 111 | } -------------------------------------------------------------------------------- /src/xenialdan/libstructure/packet/StructureEditorData.php: -------------------------------------------------------------------------------- 1 | asPosition()); 19 | } 20 | 21 | public function getNetworkType() : int{ 22 | return WindowTypes::STRUCTURE_EDITOR; 23 | } 24 | 25 | public function getName() : string{ 26 | return "Structure Block"; 27 | } 28 | 29 | public function getDefaultSize() : int{ 30 | return 0; 31 | } 32 | 33 | /** 34 | * This override is here for documentation and code completion purposes only. 35 | * @return Position 36 | */ 37 | public function getHolder(){ 38 | return $this->holder; 39 | } 40 | 41 | /** 42 | * @param Player|Player[] $target 43 | */ 44 | public function sendContents($target) : void{ 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /virion.yml: -------------------------------------------------------------------------------- 1 | name: libstructure 2 | version: 0.0.0 3 | antigen: xenialdan\libstructure 4 | api: [3.9] 5 | php: [7.2] 6 | author: XenialDan 7 | --------------------------------------------------------------------------------