├── .gitignore └── src └── svile ├── start.php └── structureconverter ├── StructureBlock.php └── utils ├── NamedId.php ├── Utils.php ├── binary └── Binary.php ├── console └── Console.php └── nbt ├── NBT.php └── tag ├── ByteArrayTag.php ├── ByteTag.php ├── CompoundTag.php ├── DoubleTag.php ├── EndTag.php ├── FloatTag.php ├── IntArrayTag.php ├── IntTag.php ├── ListTag.php ├── LongTag.php ├── NamedTag.php ├── ShortTag.php ├── StringTag.php └── Tag.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/* 2 | /structures 3 | /nameIdExporter 4 | /*.json -------------------------------------------------------------------------------- /src/svile/start.php: -------------------------------------------------------------------------------- 1 | 0) { 24 | echo 'You must use PHP >= 7.0' . PHP_EOL; 25 | exit(1); 26 | } 27 | 28 | @define('PATH', realpath(__DIR__ . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR); 29 | 30 | spl_autoload_register(function ($class) { 31 | require_once PATH . 'src' . DIRECTORY_SEPARATOR . str_replace('\\', DIRECTORY_SEPARATOR, $class) . '.php'; 32 | }); 33 | 34 | Console::init(); 35 | Console::input('File absolute path (can be an §a*.nbt§f§r or a §a*.schematic§f§r) : '); 36 | $inputPath = Console::getInput(); 37 | $path = realpath($inputPath); 38 | 39 | if (!is_file($path)) { 40 | Console::error('§cCouldn\'t find the file at: §f§r' . $inputPath); 41 | goto pause; 42 | } 43 | 44 | if (substr($path, -4) == '.nbt') { 45 | StructureBlock::toSchematic($path); 46 | } elseif (substr($path, -10) == '.schematic') { 47 | Console::error('§f*.schematic §cto §f.*nbt §cisn\'t avaible yet'); 48 | } else { 49 | Console::error('§cThe file must be an §f*.nbt§c or a §f*.schematic'); 50 | goto pause; 51 | } 52 | 53 | pause: 54 | Console::log(PHP_EOL . '§f§rPress §lEnter§f§r §fto exit'); 55 | Console::getInput(); 56 | exit(0); 57 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/StructureBlock.php: -------------------------------------------------------------------------------- 1 | readCompressed(file_get_contents($structurePath)); 50 | $nbt = $nbt->getData(); 51 | 52 | if (!(isset($nbt->author, $nbt->blocks, $nbt->entities, $nbt->palette, $nbt->size, $nbt->version) && 53 | $nbt->author instanceof StringTag && $nbt->blocks instanceof ListTag && $nbt->entities instanceof ListTag && 54 | $nbt->palette instanceof ListTag && $nbt->size instanceof ListTag && $nbt->version instanceof IntTag) 55 | ) { 56 | Console::error('§cUnsupported structure'); 57 | return false; 58 | } 59 | 60 | if ($nbt['version'] != 1) { 61 | Console::error('§cUnsupported structure version: §f' . $nbt['version']); 62 | return false; 63 | } 64 | 65 | $w = (int)$nbt['size'][0]; 66 | $h = (int)$nbt['size'][1]; 67 | $l = (int)$nbt['size'][2]; 68 | $whl = $w * $h * $l; 69 | 70 | if ($whl < 1) { 71 | Console::error('§cSize = 0'); 72 | return false; 73 | } 74 | 75 | Console::log(PHP_EOL . '§l§bAuthor: §r§f' . $nbt['author'] . PHP_EOL . '§l§bSize: §r§f W:' . $w . ' H:' . $h . ' L:' . $l . PHP_EOL); 76 | 77 | Console::info('Loading "palette" ...'); 78 | $palette = self::parsePalette($nbt['palette']); 79 | 80 | Console::info('Creating schematic ...'); 81 | $blocks = str_repeat("\x00", $whl); 82 | $data = str_repeat("\x00", $whl); 83 | 84 | foreach ($nbt->blocks as $block) { 85 | $x = (int)$block['pos'][0]; 86 | $y = (int)$block['pos'][1]; 87 | $z = (int)$block['pos'][2]; 88 | $i = $w * $l * $y + $w * $z + $x; 89 | if ($i >= $whl) { 90 | Console::error('§cBlock outside the cuboid, skipping'); 91 | //Should not happen if the StructureBlock's file wasn't modified using an nbt explorer, changing block coords 92 | continue; 93 | } 94 | $state = (int)$block['state']; 95 | $id = $palette[$state] & 0xff; 96 | $meta = $palette[$state] >> 8; 97 | $blocks{$i} = chr($id); 98 | $data{$i} = chr($meta); 99 | } 100 | 101 | $nbt = new NBT(NBT::BIG_ENDIAN); 102 | $nbt->setData(new CompoundTag 103 | ('Schematic', [ 104 | new ByteArrayTag('Biomes', str_repeat("\x01", $w * $l)), 105 | new ByteArrayTag('Blocks', $blocks), 106 | new ByteArrayTag('Data', $data), 107 | (new ListTag('Entities', []))->setTagType(NBT::TAG_Byte), 108 | new ShortTag('Height', $h), 109 | new ShortTag('Length', $l), 110 | new StringTag('Materials', 'Alpha'), 111 | (new ListTag('TileEntities', []))->setTagType(NBT::TAG_Byte), 112 | (new ListTag('TileTicks', []))->setTagType(NBT::TAG_Byte), 113 | new ShortTag('Width', $w) 114 | ])); 115 | $schpath = dirname($structurePath) . '/' . pathinfo($structurePath, PATHINFO_FILENAME) . '.schematic'; 116 | if (file_put_contents($schpath, $nbt->writeCompressed())) { 117 | Console::info('Done, file saved at: §a' . $schpath); 118 | return true; 119 | } else { 120 | Console::error('§cCould not save the file at: §f' . $schpath); 121 | return false; 122 | } 123 | } 124 | 125 | 126 | private static final function parsePalette(ListTag $palette) : \SplFixedArray 127 | { 128 | $cnt = count($palette); 129 | $tmp = array_fill(0, $cnt, 0); 130 | foreach ($palette as $i => $cpt) { 131 | if ($cpt instanceof CompoundTag && is_numeric($i) && is_int(($i += 0)) && $i < $cnt) { 132 | NamedId::getNum($cpt['Name'], array_key_exists('Properties', $cpt) ? self::parseProp($cpt['Properties']) : [], $idmeta); 133 | $tmp[$i] = $idmeta; 134 | } else { 135 | Console::error('§cCorrupted palette'); 136 | } 137 | } 138 | return \SplFixedArray::fromArray($tmp); 139 | } 140 | 141 | 142 | private static final function parseProp(CompoundTag $prop) : array 143 | { 144 | $tmp = []; 145 | foreach ($prop as $p) { 146 | if ($p instanceof NamedTag && !($p instanceof \ArrayAccess)) 147 | $tmp[$p->getName()] = $p->getValue(); 148 | else 149 | Console::error('§cWrong state: §f' . print_r($p, true)); 150 | } 151 | return $tmp; 152 | } 153 | 154 | 155 | public final static function fromSchematic(string $schematicPath) 156 | { 157 | } 158 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/NamedId.php: -------------------------------------------------------------------------------- 1 | [ 46 | 1, 47 | 'stone' => 1, 48 | 'granite' => 1 | 1 << 8, 49 | 'smooth_granite' => 1 | 2 << 8, 50 | 'diorite' => 1 | 3 << 8, 51 | 'smooth_diorite' => 1 | 4 << 8, 52 | 'andesite' => 1 | 5 << 8, 53 | 'smooth_andesite' => 1 | 6 << 8 54 | ] 55 | ]; 56 | self::$palette['grass'] = [ 57 | 2, 58 | 'snowy' => [ 59 | 2, 60 | 'true' => 2, 61 | 'false' => 2 62 | ] 63 | ]; 64 | self::$palette['dirt'] = [ 65 | 3, 66 | 'snowy' => [ 67 | 3, 68 | 'true' => [ 69 | 3, 70 | 'variant' => [ 71 | 3, 72 | 'dirt' => 3, 73 | 'coarse_dirt' => 3 | 1 << 8, 74 | 'podzol' => 3 | 2 << 8 75 | ] 76 | ], 77 | 'false' => [ 78 | 3, 79 | 'variant' => [ 80 | 3, 81 | 'dirt' => 3, 82 | 'coarse_dirt' => 3 | 1 << 8, 83 | 'podzol' => 3 | 2 << 8 84 | ] 85 | ] 86 | ] 87 | ]; 88 | self::$palette['cobblestone'] = [4]; 89 | self::$palette['planks'] = [ 90 | 5, 91 | 'variant' => [ 92 | 5, 93 | 'oak' => 5, 94 | 'spruce' => 5 | 1 << 8, 95 | 'birch' => 5 | 2 << 8, 96 | 'jungle' => 5 | 3 << 8, 97 | 'acacia' => 5 | 4 << 8, 98 | 'dark_oak' => 5 | 5 << 8 99 | ] 100 | ]; 101 | self::$palette['sapling'] = [ 102 | 6, 103 | 'stage' => [ 104 | 6, 105 | '0' => [ 106 | 6, 107 | 'type' => [ 108 | 6, 109 | 'oak' => 6, 110 | 'spruce' => 6 | 1 << 8, 111 | 'birch' => 6 | 2 << 8, 112 | 'jungle' => 6 | 3 << 8, 113 | 'acacia' => 6 | 4 << 8, 114 | 'dark_oak' => 6 | 5 << 8 115 | ] 116 | ], 117 | '1' => [ 118 | 6 | 8 << 8, 119 | 'type' => [ 120 | 6 | 8 << 8, 121 | 'oak' => 6 | 8 << 8, 122 | 'spruce' => 6 | 9 << 8, 123 | 'birch' => 6 | 10 << 8, 124 | 'jungle' => 6 | 11 << 8, 125 | 'acacia' => 6 | 12 << 8, 126 | 'dark_oak' => 6 | 13 << 8 127 | ] 128 | ] 129 | ] 130 | ]; 131 | self::$palette['bedrock'] = [7]; 132 | self::$palette['flowing_water'] = [//not in my list 133 | 8, 134 | 'level' => [ 135 | 8, 136 | '0' => 8, 137 | '1' => 8 | 1 << 8, 138 | '2' => 8 | 2 << 8, 139 | '3' => 8 | 3 << 8, 140 | '4' => 8 | 4 << 8, 141 | '5' => 8 | 5 << 8, 142 | '6' => 8 | 6 << 8, 143 | '7' => 8 | 7 << 8, 144 | '8' => 8 | 8 << 8, 145 | '9' => 8 | 9 << 8, 146 | '10' => 8 | 10 << 8, 147 | '11' => 8 | 11 << 8, 148 | '12' => 8 | 12 << 8, 149 | '13' => 8 | 13 << 8, 150 | '14' => 8 | 14 << 8, 151 | '15' => 8 | 15 << 8 152 | ] 153 | ]; 154 | self::$palette['water'] = [ 155 | 9, 156 | 'level' => [ 157 | 9, 158 | '0' => 9, 159 | '1' => 9 | 1 << 8, 160 | '2' => 9 | 2 << 8, 161 | '3' => 9 | 3 << 8, 162 | '4' => 9 | 4 << 8, 163 | '5' => 9 | 5 << 8, 164 | '6' => 9 | 6 << 8, 165 | '7' => 9 | 7 << 8, 166 | '8' => 9 | 8 << 8, 167 | '9' => 9 | 9 << 8, 168 | '10' => 9 | 10 << 8, 169 | '11' => 9 | 11 << 8, 170 | '12' => 9 | 12 << 8, 171 | '13' => 9 | 13 << 8, 172 | '14' => 9 | 14 << 8, 173 | '15' => 9 | 15 << 8 174 | ] 175 | ]; 176 | self::$palette['flowing_lava'] = [//not in my list 177 | 10, 178 | 'level' => [ 179 | 10, 180 | '0' => 10, 181 | '1' => 10 | 1 << 8, 182 | '2' => 10 | 2 << 8, 183 | '3' => 10 | 3 << 8, 184 | '4' => 10 | 4 << 8, 185 | '5' => 10 | 5 << 8, 186 | '6' => 10 | 6 << 8, 187 | '7' => 10 | 7 << 8, 188 | '8' => 10 | 8 << 8, 189 | '9' => 10 | 9 << 8, 190 | '10' => 10 | 10 << 8, 191 | '11' => 10 | 11 << 8, 192 | '12' => 10 | 12 << 8, 193 | '13' => 10 | 13 << 8, 194 | '14' => 10 | 14 << 8, 195 | '15' => 10 | 15 << 8 196 | ] 197 | ]; 198 | self::$palette['lava'] = [ 199 | 11, 200 | 'level' => [ 201 | 11, 202 | '0' => 11, 203 | '1' => 11 | 1 << 8, 204 | '2' => 11 | 2 << 8, 205 | '3' => 11 | 3 << 8, 206 | '4' => 11 | 4 << 8, 207 | '5' => 11 | 5 << 8, 208 | '6' => 11 | 6 << 8, 209 | '7' => 11 | 7 << 8, 210 | '8' => 11 | 8 << 8, 211 | '9' => 11 | 9 << 8, 212 | '10' => 11 | 10 << 8, 213 | '11' => 11 | 11 << 8, 214 | '12' => 11 | 12 << 8, 215 | '13' => 11 | 13 << 8, 216 | '14' => 11 | 14 << 8, 217 | '15' => 11 | 15 << 8 218 | ] 219 | ]; 220 | self::$palette['sand'] = [ 221 | 12, 222 | 'variant' => [ 223 | 12, 224 | 'sand' => 12, 225 | 'red_sand' => 12 | 1 << 8 226 | ] 227 | ]; 228 | self::$palette['gravel'] = [13]; 229 | self::$palette['gold_ore'] = [14]; 230 | self::$palette['iron_ore'] = [15]; 231 | self::$palette['coal_ore'] = [16]; 232 | self::$palette['log'] = [ 233 | 17, 234 | 'variant' => [ 235 | 17, 236 | 'oak' => [ 237 | 17, 238 | 'axis' => [ 239 | 17, 240 | 'none' => 17 | 12 << 8,//Only bark 241 | 'x' => 17 | 4 << 8,//E-W 242 | 'y' => 17,//UP-DOWN 243 | 'z' => 17 | 8 << 8//N-S 244 | ] 245 | ], 246 | 'spruce' => [ 247 | 17 | 1 << 8, 248 | 'axis' => [ 249 | 17 | 1 << 8, 250 | 'none' => 17 | 13 << 8,//Only bark 251 | 'x' => 17 | 5 << 8,//E-W 252 | 'y' => 17 | 1 << 8,//UP-DOWN 253 | 'z' => 17 | 9 << 8//N-S 254 | ] 255 | ], 256 | 'birch' => [ 257 | 17 | 2 << 8, 258 | 'axis' => [ 259 | 17 | 2 << 8, 260 | 'none' => 17 | 14 << 8,//Only bark 261 | 'x' => 17 | 6 << 8,//E-W 262 | 'y' => 17 | 2 << 8,//UP-DOWN 263 | 'z' => 17 | 10 << 8//N-S 264 | ] 265 | ], 266 | 'jungle' => [ 267 | 17 | 3 << 8, 268 | 'axis' => [ 269 | 17 | 3 << 8, 270 | 'none' => 17 | 15 << 8,//Only bark 271 | 'x' => 17 | 7 << 8,//E-W 272 | 'y' => 17 | 3 << 8,//UP-DOWN 273 | 'z' => 17 | 11 << 8//N-S 274 | ] 275 | ] 276 | ] 277 | ]; 278 | self::$palette['leaves'] = [18]; 279 | self::$palette['sponge'] = [19]; 280 | self::$palette['glass'] = [20]; 281 | self::$palette['lapis_ore'] = [21]; 282 | self::$palette['lapis_block'] = [22]; 283 | self::$palette['dispenser'] = [23]; 284 | self::$palette['sandstone'] = [24]; 285 | self::$palette['noteblock'] = [25]; 286 | self::$palette['bed'] = [26]; 287 | self::$palette['golden_rail'] = [27]; 288 | self::$palette['detector_rail'] = [28]; 289 | self::$palette['sticky_piston'] = [29]; 290 | self::$palette['web'] = [30]; 291 | self::$palette['tallgrass'] = [31]; 292 | self::$palette['deadbush'] = [32]; 293 | self::$palette['piston'] = [33]; 294 | self::$palette['piston_head'] = [34];//not in my list 295 | self::$palette['wool'] = [ 296 | 35, 297 | 'color' => [ 298 | 35, 299 | 'white' => 35, 300 | 'orange' => 35 | 1 << 8, 301 | 'magenta' => 35 | 2 << 8, 302 | 'light_blue' => 35 | 3 << 8, 303 | 'yellow' => 35 | 4 << 8, 304 | 'lime' => 35 | 5 << 8, 305 | 'pink' => 35 | 6 << 8, 306 | 'gray' => 35 | 7 << 8, 307 | 'silver' => 35 | 8 << 8, 308 | 'cyan' => 35 | 9 << 8, 309 | 'purple' => 35 | 10 << 8, 310 | 'blue' => 35 | 11 << 8, 311 | 'brown' => 35 | 12 << 8, 312 | 'green' => 35 | 13 << 8, 313 | 'red' => 35 | 14 << 8, 314 | 'black' => 35 | 15 << 8, 315 | ] 316 | ]; 317 | self::$palette['piston_extension'] = [36];//not in my list 318 | self::$palette['yellow_flower'] = [37]; 319 | self::$palette['red_flower'] = [38]; 320 | self::$palette['brown_mushroom'] = [39]; 321 | self::$palette['red_mushroom'] = [40]; 322 | self::$palette['gold_block'] = [41]; 323 | self::$palette['iron_block'] = [42]; 324 | self::$palette['double_stone_slab'] = [43]; 325 | self::$palette['stone_slab'] = [44]; 326 | self::$palette['brick_block'] = [45]; 327 | self::$palette['tnt'] = [46]; 328 | self::$palette['bookshelf'] = [47]; 329 | self::$palette['mossy_cobblestone'] = [48]; 330 | self::$palette['obsidian'] = [49]; 331 | self::$palette['torch'] = [ 332 | 50 | 5 << 8, 333 | 'facing' => [ 334 | 50 | 5 << 8, 335 | 'east' => 50 | 1 << 8, 336 | 'west' => 50 | 2 << 8, 337 | 'south' => 50 | 3 << 8, 338 | 'north' => 50 | 4 << 8, 339 | 'up' => 50 | 5 << 8 340 | ] 341 | ]; 342 | self::$palette['fire'] = [51]; 343 | self::$palette['mob_spawner'] = [52];//not in my list 344 | self::$palette['oak_stairs'] = [ 345 | 53, 346 | 'half' => [ 347 | 53, 348 | 'top' => [ 349 | 53 | 4 << 8, 350 | 'facing' => [ 351 | 53 | 4 << 8, 352 | 'east' => 53 | 4 << 8, 353 | 'west' => 53 | 5 << 8, 354 | 'south' => 53 | 6 << 8, 355 | 'north' => 53 | 7 << 8 356 | ] 357 | ], 358 | 'bottom' => [ 359 | 53, 360 | 'facing' => [ 361 | 53, 362 | 'east' => 53, 363 | 'west' => 53 | 1 << 8, 364 | 'south' => 53 | 2 << 8, 365 | 'north' => 53 | 3 << 8 366 | ] 367 | ] 368 | ] 369 | ]; 370 | self::$palette['chest'] = [54]; 371 | self::$palette['redstone_wire'] = [55]; 372 | self::$palette['diamond_ore'] = [56]; 373 | self::$palette['diamond_block'] = [57]; 374 | self::$palette['crafting_table'] = [58]; 375 | self::$palette['wheat'] = [59]; 376 | self::$palette['farmland'] = [60]; 377 | self::$palette['furnace'] = [61]; 378 | self::$palette['lit_furnace'] = [62];//not in my list 379 | self::$palette['standing_sign'] = [63]; 380 | self::$palette['wooden_door'] = [64]; 381 | self::$palette['ladder'] = [ 382 | 65 | 2 << 8, 383 | 'facing' => [ 384 | 'north' => 65 | 2 << 8, 385 | 'south' => 65 | 3 << 8, 386 | 'west' => 65 | 4 << 8, 387 | 'east' => 65 | 5 << 8 388 | ] 389 | ]; 390 | self::$palette['rail'] = [66]; 391 | self::$palette['stone_stairs'] = [ 392 | 67, 393 | 'half' => [ 394 | 67, 395 | 'top' => [ 396 | 67 | 4 << 8, 397 | 'facing' => [ 398 | 67 | 4 << 8, 399 | 'east' => 67 | 4 << 8, 400 | 'west' => 67 | 5 << 8, 401 | 'south' => 67 | 6 << 8, 402 | 'north' => 67 | 7 << 8 403 | ] 404 | ], 405 | 'bottom' => [ 406 | 67, 407 | 'facing' => [ 408 | 67, 409 | 'east' => 67, 410 | 'west' => 67 | 1 << 8, 411 | 'south' => 67 | 2 << 8, 412 | 'north' => 67 | 3 << 8 413 | ] 414 | ] 415 | ] 416 | ]; 417 | self::$palette['wall_sign'] = [68]; 418 | self::$palette['lever'] = [69]; 419 | self::$palette['stone_pressure_plate'] = [70]; 420 | self::$palette['iron_door'] = [71]; 421 | self::$palette['wooden_pressure_plate'] = [72]; 422 | self::$palette['redstone_ore'] = [73]; 423 | self::$palette['lit_redstone_ore'] = [74];//not in my list 424 | self::$palette['unlit_redstone_torch'] = [75]; 425 | self::$palette['redstone_torch'] = [76]; 426 | self::$palette['stone_button'] = [77]; 427 | self::$palette['snow_layer'] = [78]; 428 | self::$palette['ice'] = [79]; 429 | self::$palette['snow'] = [80]; 430 | self::$palette['cactus'] = [81]; 431 | self::$palette['clay'] = [82]; 432 | self::$palette['reeds'] = [83]; 433 | self::$palette['jukebox'] = [84]; 434 | self::$palette['fence'] = [85]; 435 | self::$palette['pumpkin'] = [ 436 | 86, 437 | 'facing' => [ 438 | 86, 439 | 'south' => 86, 440 | 'west' => 86 | 1 << 8, 441 | 'north' => 86 | 2 << 8, 442 | 'east' => 86 | 3 << 8, 443 | ] 444 | ]; 445 | self::$palette['netherrack'] = [87]; 446 | self::$palette['soul_sand'] = [88]; 447 | self::$palette['glowstone'] = [89]; 448 | self::$palette['portal'] = [90];//not in my list 449 | self::$palette['lit_pumpkin'] = [ 450 | 91, 451 | 'facing' => [ 452 | 91, 453 | 'south' => 91, 454 | 'west' => 91 | 1 << 8, 455 | 'north' => 91 | 2 << 8, 456 | 'east' => 91 | 3 << 8, 457 | ] 458 | ]; 459 | self::$palette['cake'] = [92]; 460 | self::$palette['unpowered_repeater'] = [93]; 461 | self::$palette['powered_repeater'] = [94];//not in my list 462 | self::$palette['stained_glass'] = [ 463 | 95, 464 | 'color' => [ 465 | 95, 466 | 'white' => 95, 467 | 'orange' => 95 | 1 << 8, 468 | 'magenta' => 95 | 2 << 8, 469 | 'light_blue' => 95 | 3 << 8, 470 | 'yellow' => 95 | 4 << 8, 471 | 'lime' => 95 | 5 << 8, 472 | 'pink' => 95 | 6 << 8, 473 | 'gray' => 95 | 7 << 8, 474 | 'silver' => 95 | 8 << 8, 475 | 'cyan' => 95 | 9 << 8, 476 | 'purple' => 95 | 10 << 8, 477 | 'blue' => 95 | 11 << 8, 478 | 'brown' => 95 | 12 << 8, 479 | 'green' => 95 | 13 << 8, 480 | 'red' => 95 | 14 << 8, 481 | 'black' => 95 | 15 << 8, 482 | ] 483 | ]; 484 | self::$palette['trapdoor'] = [96]; 485 | self::$palette['monster_egg'] = [97]; 486 | self::$palette['stonebrick'] = [98]; 487 | self::$palette['brown_mushroom_block'] = [99]; 488 | self::$palette['red_mushroom_block'] = [100]; 489 | self::$palette['iron_bars'] = [101]; 490 | self::$palette['glass_pane'] = [102]; 491 | self::$palette['melon_block'] = [103]; 492 | self::$palette['pumpkin_stem'] = [104]; 493 | self::$palette['melon_stem'] = [105]; 494 | self::$palette['vine'] = [ 495 | 106 | 2 << 8, 496 | 'facing' => [ 497 | 'south' => 106 | 1 << 8, 498 | 'west' => 106 | 2 << 8, 499 | 'north' => 106 | 4 << 8, 500 | 'east' => 106 | 8 << 8 501 | ] 502 | ]; 503 | self::$palette['fence_gate'] = [107]; 504 | self::$palette['brick_stairs'] = [ 505 | 108, 506 | 'half' => [ 507 | 108, 508 | 'top' => [ 509 | 108 | 4 << 8, 510 | 'facing' => [ 511 | 108 | 4 << 8, 512 | 'east' => 108 | 4 << 8, 513 | 'west' => 108 | 5 << 8, 514 | 'south' => 108 | 6 << 8, 515 | 'north' => 108 | 7 << 8 516 | ] 517 | ], 518 | 'bottom' => [ 519 | 108, 520 | 'facing' => [ 521 | 108, 522 | 'east' => 108, 523 | 'west' => 108 | 1 << 8, 524 | 'south' => 108 | 2 << 8, 525 | 'north' => 108 | 3 << 8 526 | ] 527 | ] 528 | ] 529 | ]; 530 | self::$palette['stone_brick_stairs'] = [ 531 | 109, 532 | 'half' => [ 533 | 109, 534 | 'top' => [ 535 | 109 | 4 << 8, 536 | 'facing' => [ 537 | 109 | 4 << 8, 538 | 'east' => 109 | 4 << 8, 539 | 'west' => 109 | 5 << 8, 540 | 'south' => 109 | 6 << 8, 541 | 'north' => 109 | 7 << 8 542 | ] 543 | ], 544 | 'bottom' => [ 545 | 109, 546 | 'facing' => [ 547 | 109, 548 | 'east' => 109, 549 | 'west' => 109 | 1 << 8, 550 | 'south' => 109 | 2 << 8, 551 | 'north' => 109 | 3 << 8 552 | ] 553 | ] 554 | ] 555 | ]; 556 | self::$palette['mycelium'] = [110]; 557 | self::$palette['waterlily'] = [111]; 558 | self::$palette['nether_brick'] = [112]; 559 | self::$palette['nether_brick_fence'] = [113]; 560 | self::$palette['nether_brick_stairs'] = [ 561 | 114, 562 | 'half' => [ 563 | 114, 564 | 'top' => [ 565 | 114 | 4 << 8, 566 | 'facing' => [ 567 | 114 | 4 << 8, 568 | 'east' => 114 | 4 << 8, 569 | 'west' => 114 | 5 << 8, 570 | 'south' => 114 | 6 << 8, 571 | 'north' => 114 | 7 << 8 572 | ] 573 | ], 574 | 'bottom' => [ 575 | 114, 576 | 'facing' => [ 577 | 114, 578 | 'east' => 114, 579 | 'west' => 114 | 1 << 8, 580 | 'south' => 114 | 2 << 8, 581 | 'north' => 114 | 3 << 8 582 | ] 583 | ] 584 | ] 585 | ]; 586 | self::$palette['nether_wart'] = [115]; 587 | self::$palette['enchanting_table'] = [116]; 588 | self::$palette['brewing_stand'] = [117]; 589 | self::$palette['cauldron'] = [118]; 590 | self::$palette['end_portal'] = [119];//not in my list 591 | self::$palette['end_portal_frame'] = [120]; 592 | self::$palette['end_stone'] = [121]; 593 | self::$palette['dragon_egg'] = [122];//not in my list 594 | self::$palette['redstone_lamp'] = [123]; 595 | self::$palette['lit_redstone_lamp'] = [124]; 596 | self::$palette['double_wooden_slab'] = [125]; 597 | self::$palette['wooden_slab'] = [126]; 598 | self::$palette['cocoa'] = [127]; 599 | self::$palette['sandstone_stairs'] = [ 600 | 128, 601 | 'half' => [ 602 | 128, 603 | 'top' => [ 604 | 128 | 4 << 8, 605 | 'facing' => [ 606 | 128 | 4 << 8, 607 | 'east' => 128 | 4 << 8, 608 | 'west' => 128 | 5 << 8, 609 | 'south' => 128 | 6 << 8, 610 | 'north' => 128 | 7 << 8 611 | ] 612 | ], 613 | 'bottom' => [ 614 | 128, 615 | 'facing' => [ 616 | 128, 617 | 'east' => 128, 618 | 'west' => 128 | 1 << 8, 619 | 'south' => 128 | 2 << 8, 620 | 'north' => 128 | 3 << 8 621 | ] 622 | ] 623 | ] 624 | ]; 625 | self::$palette['emerald_ore'] = [129]; 626 | self::$palette['ender_chest'] = [130]; 627 | self::$palette['tripwire_hook'] = [131]; 628 | self::$palette['tripwire'] = [132];//not in my list 629 | self::$palette['emerald_block'] = [133]; 630 | self::$palette['spruce_stairs'] = [ 631 | 134, 632 | 'half' => [ 633 | 134, 634 | 'top' => [ 635 | 134 | 4 << 8, 636 | 'facing' => [ 637 | 134 | 4 << 8, 638 | 'east' => 134 | 4 << 8, 639 | 'west' => 134 | 5 << 8, 640 | 'south' => 134 | 6 << 8, 641 | 'north' => 134 | 7 << 8 642 | ] 643 | ], 644 | 'bottom' => [ 645 | 134, 646 | 'facing' => [ 647 | 134, 648 | 'east' => 134, 649 | 'west' => 134 | 1 << 8, 650 | 'south' => 134 | 2 << 8, 651 | 'north' => 134 | 3 << 8 652 | ] 653 | ] 654 | ] 655 | ]; 656 | self::$palette['birch_stairs'] = [ 657 | 135, 658 | 'half' => [ 659 | 135, 660 | 'top' => [ 661 | 135 | 4 << 8, 662 | 'facing' => [ 663 | 135 | 4 << 8, 664 | 'east' => 135 | 4 << 8, 665 | 'west' => 135 | 5 << 8, 666 | 'south' => 135 | 6 << 8, 667 | 'north' => 135 | 7 << 8 668 | ] 669 | ], 670 | 'bottom' => [ 671 | 135, 672 | 'facing' => [ 673 | 135, 674 | 'east' => 135, 675 | 'west' => 135 | 1 << 8, 676 | 'south' => 135 | 2 << 8, 677 | 'north' => 135 | 3 << 8 678 | ] 679 | ] 680 | ] 681 | ]; 682 | self::$palette['jungle_stairs'] = [ 683 | 136, 684 | 'half' => [ 685 | 136, 686 | 'top' => [ 687 | 136 | 4 << 8, 688 | 'facing' => [ 689 | 136 | 4 << 8, 690 | 'east' => 136 | 4 << 8, 691 | 'west' => 136 | 5 << 8, 692 | 'south' => 136 | 6 << 8, 693 | 'north' => 136 | 7 << 8 694 | ] 695 | ], 696 | 'bottom' => [ 697 | 136, 698 | 'facing' => [ 699 | 136, 700 | 'east' => 136, 701 | 'west' => 136 | 1 << 8, 702 | 'south' => 136 | 2 << 8, 703 | 'north' => 136 | 3 << 8 704 | ] 705 | ] 706 | ] 707 | ]; 708 | self::$palette['command_block'] = [137]; 709 | self::$palette['beacon'] = [138]; 710 | self::$palette['cobblestone_wall'] = [139]; 711 | self::$palette['flower_pot'] = [140]; 712 | self::$palette['carrots'] = [141]; 713 | self::$palette['potatoes'] = [142]; 714 | self::$palette['wooden_button'] = [143]; 715 | self::$palette['skull'] = [144]; 716 | self::$palette['anvil'] = [145]; 717 | self::$palette['trapped_chest'] = [146]; 718 | self::$palette['light_weighted_pressure_plate'] = [147]; 719 | self::$palette['heavy_weighted_pressure_plate'] = [148]; 720 | self::$palette['unpowered_comparator'] = [149]; 721 | self::$palette['powered_comparator'] = [150];//not in my list 722 | self::$palette['daylight_detector'] = [151]; 723 | self::$palette['redstone_block'] = [152]; 724 | self::$palette['quartz_ore'] = [153]; 725 | self::$palette['hopper'] = [154]; 726 | self::$palette['quartz_block'] = [155]; 727 | self::$palette['quartz_stairs'] = [ 728 | 156, 729 | 'half' => [ 730 | 156, 731 | 'top' => [ 732 | 156 | 4 << 8, 733 | 'facing' => [ 734 | 156 | 4 << 8, 735 | 'east' => 156 | 4 << 8, 736 | 'west' => 156 | 5 << 8, 737 | 'south' => 156 | 6 << 8, 738 | 'north' => 156 | 7 << 8 739 | ] 740 | ], 741 | 'bottom' => [ 742 | 156, 743 | 'facing' => [ 744 | 156, 745 | 'east' => 156, 746 | 'west' => 156 | 1 << 8, 747 | 'south' => 156 | 2 << 8, 748 | 'north' => 156 | 3 << 8 749 | ] 750 | ] 751 | ] 752 | ]; 753 | self::$palette['activator_rail'] = [157]; 754 | self::$palette['dropper'] = [158]; 755 | self::$palette['stained_hardened_clay'] = [ 756 | 159, 757 | 'color' => [ 758 | 159, 759 | 'white' => 159, 760 | 'orange' => 159 | 1 << 8, 761 | 'magenta' => 159 | 2 << 8, 762 | 'light_blue' => 159 | 3 << 8, 763 | 'yellow' => 159 | 4 << 8, 764 | 'lime' => 159 | 5 << 8, 765 | 'pink' => 159 | 6 << 8, 766 | 'gray' => 159 | 7 << 8, 767 | 'silver' => 159 | 8 << 8, 768 | 'cyan' => 159 | 9 << 8, 769 | 'purple' => 159 | 10 << 8, 770 | 'blue' => 159 | 11 << 8, 771 | 'brown' => 159 | 12 << 8, 772 | 'green' => 159 | 13 << 8, 773 | 'red' => 159 | 14 << 8, 774 | 'black' => 159 | 15 << 8, 775 | ] 776 | ]; 777 | self::$palette['stained_glass_pane'] = [ 778 | 160, 779 | 'color' => [ 780 | 160, 781 | 'white' => 160, 782 | 'orange' => 160 | 1 << 8, 783 | 'magenta' => 160 | 2 << 8, 784 | 'light_blue' => 160 | 3 << 8, 785 | 'yellow' => 160 | 4 << 8, 786 | 'lime' => 160 | 5 << 8, 787 | 'pink' => 160 | 6 << 8, 788 | 'gray' => 160 | 7 << 8, 789 | 'silver' => 160 | 8 << 8, 790 | 'cyan' => 160 | 9 << 8, 791 | 'purple' => 160 | 10 << 8, 792 | 'blue' => 160 | 11 << 8, 793 | 'brown' => 160 | 12 << 8, 794 | 'green' => 160 | 13 << 8, 795 | 'red' => 160 | 14 << 8, 796 | 'black' => 160 | 15 << 8, 797 | ] 798 | ]; 799 | self::$palette['leaves2'] = [161]; 800 | self::$palette['log2'] = [162]; 801 | self::$palette['acacia_stairs'] = [ 802 | 163, 803 | 'half' => [ 804 | 163, 805 | 'top' => [ 806 | 163 | 4 << 8, 807 | 'facing' => [ 808 | 163 | 4 << 8, 809 | 'east' => 163 | 4 << 8, 810 | 'west' => 163 | 5 << 8, 811 | 'south' => 163 | 6 << 8, 812 | 'north' => 163 | 7 << 8 813 | ] 814 | ], 815 | 'bottom' => [ 816 | 163, 817 | 'facing' => [ 818 | 163, 819 | 'east' => 163, 820 | 'west' => 163 | 1 << 8, 821 | 'south' => 163 | 2 << 8, 822 | 'north' => 163 | 3 << 8 823 | ] 824 | ] 825 | ] 826 | ]; 827 | self::$palette['dark_oak_stairs'] = [ 828 | 164, 829 | 'half' => [ 830 | 164, 831 | 'top' => [ 832 | 164 | 4 << 8, 833 | 'facing' => [ 834 | 164 | 4 << 8, 835 | 'east' => 164 | 4 << 8, 836 | 'west' => 164 | 5 << 8, 837 | 'south' => 164 | 6 << 8, 838 | 'north' => 164 | 7 << 8 839 | ] 840 | ], 841 | 'bottom' => [ 842 | 164, 843 | 'facing' => [ 844 | 164, 845 | 'east' => 164, 846 | 'west' => 164 | 1 << 8, 847 | 'south' => 164 | 2 << 8, 848 | 'north' => 164 | 3 << 8 849 | ] 850 | ] 851 | ] 852 | ]; 853 | self::$palette['slime'] = [165]; 854 | self::$palette['barrier'] = [166]; 855 | self::$palette['iron_trapdoor'] = [167]; 856 | self::$palette['prismarine'] = [168]; 857 | self::$palette['sea_lantern'] = [169]; 858 | self::$palette['hay_block'] = [170]; 859 | self::$palette['carpet'] = [ 860 | 171, 861 | 'color' => [ 862 | 171, 863 | 'white' => 171, 864 | 'orange' => 171 | 1 << 8, 865 | 'magenta' => 171 | 2 << 8, 866 | 'light_blue' => 171 | 3 << 8, 867 | 'yellow' => 171 | 4 << 8, 868 | 'lime' => 171 | 5 << 8, 869 | 'pink' => 171 | 6 << 8, 870 | 'gray' => 171 | 7 << 8, 871 | 'silver' => 171 | 8 << 8, 872 | 'cyan' => 171 | 9 << 8, 873 | 'purple' => 171 | 10 << 8, 874 | 'blue' => 171 | 11 << 8, 875 | 'brown' => 171 | 12 << 8, 876 | 'green' => 171 | 13 << 8, 877 | 'red' => 171 | 14 << 8, 878 | 'black' => 171 | 15 << 8, 879 | ] 880 | ]; 881 | self::$palette['hardened_clay'] = [172]; 882 | self::$palette['coal_block'] = [173]; 883 | self::$palette['packed_ice'] = [174]; 884 | self::$palette['double_plant'] = [175]; 885 | self::$palette['standing_banner'] = [176]; 886 | self::$palette['wall_banner'] = [177]; 887 | self::$palette['daylight_detector_inverted'] = [178]; 888 | self::$palette['red_sandstone'] = [179]; 889 | self::$palette['red_sandstone_stairs'] = [ 890 | 180, 891 | 'half' => [ 892 | 180, 893 | 'top' => [ 894 | 180 | 4 << 8, 895 | 'facing' => [ 896 | 180 | 4 << 8, 897 | 'east' => 180 | 4 << 8, 898 | 'west' => 180 | 5 << 8, 899 | 'south' => 180 | 6 << 8, 900 | 'north' => 180 | 7 << 8 901 | ] 902 | ], 903 | 'bottom' => [ 904 | 180, 905 | 'facing' => [ 906 | 180, 907 | 'east' => 180, 908 | 'west' => 180 | 1 << 8, 909 | 'south' => 180 | 2 << 8, 910 | 'north' => 180 | 3 << 8 911 | ] 912 | ] 913 | ] 914 | ]; 915 | self::$palette['double_stone_slab2'] = [181]; 916 | self::$palette['stone_slab2'] = [182]; 917 | self::$palette['spruce_fence_gate'] = [183]; 918 | self::$palette['birch_fence_gate'] = [184]; 919 | self::$palette['jungle_fence_gate'] = [185]; 920 | self::$palette['dark_oak_fence_gate'] = [186]; 921 | self::$palette['acacia_fence_gate'] = [187]; 922 | self::$palette['spruce_fence'] = [188]; 923 | self::$palette['birch_fence'] = [189]; 924 | self::$palette['jungle_fence'] = [190]; 925 | self::$palette['dark_oak_fence'] = [191]; 926 | self::$palette['acacia_fence'] = [192]; 927 | self::$palette['spruce_door'] = [193]; 928 | self::$palette['birch_door'] = [194]; 929 | self::$palette['jungle_door'] = [195]; 930 | self::$palette['acacia_door'] = [196]; 931 | self::$palette['dark_oak_door'] = [197]; 932 | self::$palette['end_rod'] = [198]; 933 | self::$palette['chorus_plant'] = [199]; 934 | self::$palette['chorus_flower'] = [200]; 935 | self::$palette['purpur_block'] = [201]; 936 | self::$palette['purpur_pillar'] = [202]; 937 | self::$palette['purpur_stairs'] = [ 938 | 203, 939 | 'half' => [ 940 | 203, 941 | 'top' => [ 942 | 203 | 4 << 8, 943 | 'facing' => [ 944 | 203 | 4 << 8, 945 | 'east' => 203 | 4 << 8, 946 | 'west' => 203 | 5 << 8, 947 | 'south' => 203 | 6 << 8, 948 | 'north' => 203 | 7 << 8 949 | ] 950 | ], 951 | 'bottom' => [ 952 | 203, 953 | 'facing' => [ 954 | 203, 955 | 'east' => 203, 956 | 'west' => 203 | 1 << 8, 957 | 'south' => 203 | 2 << 8, 958 | 'north' => 203 | 3 << 8 959 | ] 960 | ] 961 | ] 962 | ]; 963 | self::$palette['purpur_double_slab'] = [204]; 964 | self::$palette['purpur_slab'] = [205]; 965 | self::$palette['end_bricks'] = [206]; 966 | self::$palette['beetroots'] = [207]; 967 | self::$palette['grass_path'] = [208]; 968 | self::$palette['end_gateway'] = [209];//not in my list 969 | self::$palette['repeating_command_block'] = [210];//not in my list 970 | self::$palette['chain_command_block'] = [211];//not in my list 971 | self::$palette['frosted_ice'] = [212];//not in my list 972 | self::$palette['magma'] = [213]; 973 | self::$palette['nether_wart_block'] = [214]; 974 | self::$palette['red_nether_brick'] = [215];//not in my list 975 | self::$palette['bone_block'] = [216]; 976 | self::$palette['structure_void'] = [217];//not in my list 977 | self::$palette['observer'] = [218];//not in my list 978 | self::$palette['white_shulker_box'] = [219];//not in my list 979 | self::$palette['orange_shulker_box'] = [220];//not in my list 980 | self::$palette['magenta_shulker_box'] = [221];//not in my list 981 | self::$palette['light_blue_shulker_box'] = [222];//not in my list 982 | self::$palette['yellow_shulker_box'] = [223];//not in my list 983 | self::$palette['lime_shulker_box'] = [224];//not in my list 984 | self::$palette['pink_shulker_box'] = [225];//not in my list 985 | self::$palette['gray_shulker_box'] = [226];//not in my list 986 | self::$palette['light_gray_shulker_box'] = [227];//not in my list 987 | self::$palette['cyan_shulker_box'] = [228];//not in my list 988 | self::$palette['purple_shulker_box'] = [229];//not in my list 989 | self::$palette['blue_shulker_box'] = [230];//not in my list 990 | self::$palette['brown_shulker_box'] = [231];//not in my list 991 | self::$palette['green_shulker_box'] = [232];//not in my list 992 | self::$palette['red_shulker_box'] = [233];//not in my list 993 | self::$palette['black_shulker_box'] = [234];//not in my list 994 | self::$palette['structure_block'] = [255];//not in my list 995 | } 996 | 997 | 998 | private final static function initIdPalette() 999 | { 1000 | self::$idPalette = new \SplFixedArray(256); 1001 | 1002 | self::$idPalette[0] = ['air']; 1003 | //self::$idPalette[1] = []; 1004 | } 1005 | 1006 | 1007 | /** 1008 | * @param string $name 1009 | * @param array $prop 1010 | * @param $idmeta 1011 | * @return bool 1012 | */ 1013 | public final static function getNum(string $name, array $prop, &$idmeta) 1014 | { 1015 | if (self::$palette === null) 1016 | self::initPalette(); 1017 | 1018 | $name = str_replace('minecraft:', '', strtolower($name)); 1019 | 1020 | if (!array_key_exists($name, self::$palette)) { 1021 | $idmeta = 0; 1022 | return false; 1023 | } 1024 | 1025 | $arr = self::$palette[$name]; 1026 | 1027 | $idmeta = $arr[0]; 1028 | 1029 | //MESS starts here, now it's your problem :) 1030 | if (count($prop) > 0 && count($arr) > 1) { 1031 | $test = false; 1032 | while (is_array($arr) || !is_numeric($arr)) { 1033 | foreach (array_keys($arr) as $key) { 1034 | $test = false; 1035 | if (is_numeric($key)) 1036 | continue; 1037 | if (array_key_exists($key, $prop)) { 1038 | $arr = $arr[$key]; 1039 | if (array_key_exists($prop[$key], $arr)) { 1040 | $arr = $arr[$prop[$key]]; 1041 | $test = true; 1042 | } 1043 | break; 1044 | } 1045 | } 1046 | if ($test == false) { 1047 | $idmeta = $arr[0]; 1048 | return false; 1049 | break; 1050 | } 1051 | } 1052 | $idmeta = $arr; 1053 | return true; 1054 | } else { 1055 | return true; 1056 | } 1057 | } 1058 | 1059 | 1060 | /** 1061 | * @param int $id 1062 | * @param int $meta 1063 | * @param $name 1064 | * @param $prop 1065 | * @return bool 1066 | */ 1067 | public final static function get(int $id, int $meta, &$name, &$prop) 1068 | { 1069 | if (self::$idPalette === null) 1070 | self::initIdPalette(); 1071 | 1072 | return false; 1073 | } 1074 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/Utils.php: -------------------------------------------------------------------------------- 1 | win 25 | * MacOS => mac 26 | * iOS => ios 27 | * Android => android 28 | * Linux => Linux 29 | * BSD => bsd 30 | * Other => other 31 | * 32 | * @return string 33 | */ 34 | public static function getOS() 35 | { 36 | $uname = php_uname('s'); 37 | if (stripos($uname, 'Darwin') !== false) { 38 | if (strpos(php_uname('m'), 'iP') === 0) { 39 | $os = 'ios'; 40 | } else { 41 | $os = 'mac'; 42 | } 43 | } elseif (stripos($uname, 'Win') !== false or $uname === 'Msys') { 44 | $os = 'win'; 45 | } elseif (stripos($uname, 'Linux') !== false) { 46 | if (@file_exists('/system/build.prop')) { 47 | $os = 'android'; 48 | } else { 49 | $os = 'linux'; 50 | } 51 | } elseif (stripos($uname, 'BSD') !== false or $uname === 'DragonFly') { 52 | $os = 'bsd'; 53 | } else { 54 | $os = 'other'; 55 | } 56 | return $os; 57 | } 58 | 59 | 60 | public static function getURL($page, $timeout = 10, array $extraHeaders = []) 61 | { 62 | $ch = curl_init($page); 63 | curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge(['User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'], $extraHeaders)); 64 | curl_setopt($ch, CURLOPT_AUTOREFERER, true); 65 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 66 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); 67 | curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); 68 | curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1); 69 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 70 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 71 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int)$timeout); 72 | curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout); 73 | $ret = curl_exec($ch); 74 | curl_close($ch); 75 | 76 | return $ret; 77 | } 78 | 79 | 80 | public static function postURL($page, $args, $timeout = 10, array $extraHeaders = []) 81 | { 82 | $ch = curl_init($page); 83 | curl_setopt($ch, CURLOPT_POST, 1); 84 | curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 85 | curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); 86 | curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); 87 | curl_setopt($ch, CURLOPT_FRESH_CONNECT, 1); 88 | curl_setopt($ch, CURLOPT_POSTFIELDS, $args); 89 | curl_setopt($ch, CURLOPT_AUTOREFERER, true); 90 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 91 | curl_setopt($ch, CURLOPT_HTTPHEADER, array_merge(['User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'], $extraHeaders)); 92 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 93 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (int)$timeout); 94 | curl_setopt($ch, CURLOPT_TIMEOUT, (int)$timeout); 95 | $ret = curl_exec($ch); 96 | curl_close($ch); 97 | 98 | return $ret; 99 | } 100 | 101 | 102 | /** 103 | * Gets the External IP using an external service 104 | * 105 | * @return string|false 106 | */ 107 | public static function getIP() 108 | { 109 | $ip = trim(strip_tags(Utils::getURL('http://checkip.dyndns.org/'))); 110 | if (preg_match('#Current IP Address\: ([0-9a-fA-F\:\.]*)#', $ip, $matches) > 0) { 111 | return $matches[1]; 112 | } else { 113 | $ip = Utils::getURL('http://www.checkip.org/'); 114 | if (preg_match('#">([0-9a-fA-F\:\.]*)#', $ip, $matches) > 0) { 115 | return $matches[1]; 116 | } else { 117 | $ip = Utils::getURL('http://checkmyip.org/'); 118 | if (preg_match('#Your IP address is ([0-9a-fA-F\:\.]*)#', $ip, $matches) > 0) { 119 | return $matches[1]; 120 | } else { 121 | $ip = trim(Utils::getURL('http://ifconfig.me/ip')); 122 | if ($ip != '') { 123 | return $ip; 124 | } else { 125 | return false; 126 | } 127 | } 128 | } 129 | } 130 | } 131 | 132 | 133 | /** 134 | * http://stackoverflow.com/questions/1057572/how-can-i-get-a-hex-dump-of-a-string-in-php 135 | * 136 | * @param string $string 137 | * @param array $options 138 | * @return array|string 139 | */ 140 | public static function HexDump(string $string = '', array $options = []) 141 | { 142 | $eol = isset($options['eol']) ? $options['eol'] : PHP_EOL; 143 | $bytes_per_line = @$options['bytes_per_line'] ? $options['bytes_per_line'] : 16; 144 | $pad_char = isset($options['pad_char']) ? $options['pad_char'] : '.'; 145 | 146 | $text_lines = str_split($string, $bytes_per_line); 147 | $hex_lines = str_split(bin2hex($string), $bytes_per_line * 2); 148 | 149 | $offset = 0; 150 | $output = []; 151 | $bytes_per_line_div_2 = (int)($bytes_per_line / 2); 152 | foreach ($hex_lines as $i => $hex_line) { 153 | $text_line = $text_lines[$i]; 154 | $output [] = 155 | '§b' . sprintf('%08X', $offset) . ' §f§r' . 156 | str_pad( 157 | strlen($text_line) > $bytes_per_line_div_2 158 | ? 159 | implode(' ', str_split(substr($hex_line, 0, $bytes_per_line), 2)) . ' ' . 160 | implode(' ', str_split(substr($hex_line, $bytes_per_line), 2)) 161 | : 162 | implode(' ', str_split($hex_line, 2)) 163 | , $bytes_per_line * 3) . 164 | ' §a|' . preg_replace('/[^\x20-\x7E]/', $pad_char, $text_line) . '|§f§r'; 165 | $offset += $bytes_per_line; 166 | } 167 | $output [] = sprintf('%08X', strlen($string)); 168 | return @$options['want_array'] ? $output : join($eol, $output) . $eol . $eol; 169 | } 170 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/binary/Binary.php: -------------------------------------------------------------------------------- 1 | > 56; 122 | } else { 123 | return $b << 24 >> 24; 124 | } 125 | } else { 126 | return $b; 127 | } 128 | } 129 | 130 | 131 | /** 132 | * Writes an unsigned/signed byte 133 | * 134 | * @param $c 135 | * 136 | * @return string 137 | */ 138 | public static function writeByte($c) 139 | { 140 | return chr($c); 141 | } 142 | 143 | 144 | /** 145 | * Reads a 16-bit unsigned big-endian number 146 | * 147 | * @param $str 148 | * 149 | * @return int 150 | */ 151 | public static function readShort($str) 152 | { 153 | return unpack('n', $str)[1]; 154 | } 155 | 156 | 157 | /** 158 | * Reads a 16-bit signed big-endian number 159 | * 160 | * @param $str 161 | * 162 | * @return int 163 | */ 164 | public static function readSignedShort($str) 165 | { 166 | if (PHP_INT_SIZE === 8) { 167 | return unpack('n', $str)[1] << 48 >> 48; 168 | } else { 169 | return unpack('n', $str)[1] << 16 >> 16; 170 | } 171 | } 172 | 173 | 174 | /** 175 | * Writes a 16-bit signed/unsigned big-endian number 176 | * 177 | * @param $value 178 | * 179 | * @return string 180 | */ 181 | public static function writeShort($value) 182 | { 183 | return pack('n', $value); 184 | } 185 | 186 | 187 | /** 188 | * Reads a 16-bit signed/unsigned little-endian number 189 | * 190 | * @param $str 191 | * @param bool $signed 192 | * 193 | * @return int 194 | */ 195 | public static function readLShort($str, $signed = true) 196 | { 197 | $unpacked = unpack('v', $str)[1]; 198 | 199 | if ($signed) { 200 | if (PHP_INT_SIZE === 8) { 201 | return $unpacked << 48 >> 48; 202 | } else { 203 | return $unpacked << 16 >> 16; 204 | } 205 | } else { 206 | return $unpacked; 207 | } 208 | } 209 | 210 | 211 | /** 212 | * Writes a 16-bit signed/unsigned little-endian number 213 | * 214 | * @param $value 215 | * 216 | * @return string 217 | */ 218 | public static function writeLShort($value) 219 | { 220 | return pack('v', $value); 221 | } 222 | 223 | 224 | public static function readInt($str) 225 | { 226 | if (PHP_INT_SIZE === 8) { 227 | return unpack('N', $str)[1] << 32 >> 32; 228 | } else { 229 | return unpack('N', $str)[1]; 230 | } 231 | } 232 | 233 | 234 | public static function writeInt($value) 235 | { 236 | return pack('N', $value); 237 | } 238 | 239 | 240 | public static function readLInt($str) 241 | { 242 | if (PHP_INT_SIZE === 8) { 243 | return unpack('V', $str)[1] << 32 >> 32; 244 | } else { 245 | return unpack('V', $str)[1]; 246 | } 247 | } 248 | 249 | 250 | public static function writeLInt($value) 251 | { 252 | return pack('V', $value); 253 | } 254 | 255 | 256 | public static function readFloat($str) 257 | { 258 | return ENDIANNESS === self::BIG_ENDIAN ? unpack('f', $str)[1] : unpack('f', strrev($str))[1]; 259 | } 260 | 261 | 262 | public static function writeFloat($value) 263 | { 264 | return ENDIANNESS === self::BIG_ENDIAN ? pack('f', $value) : strrev(pack('f', $value)); 265 | } 266 | 267 | 268 | public static function readLFloat($str) 269 | { 270 | return ENDIANNESS === self::BIG_ENDIAN ? unpack('f', strrev($str))[1] : unpack('f', $str)[1]; 271 | } 272 | 273 | 274 | public static function writeLFloat($value) 275 | { 276 | return ENDIANNESS === self::BIG_ENDIAN ? strrev(pack('f', $value)) : pack('f', $value); 277 | } 278 | 279 | 280 | public static function printFloat($value) 281 | { 282 | return preg_replace("/(\\.\\d+?)0+$/", '$1', sprintf('%F', $value)); 283 | } 284 | 285 | 286 | public static function readDouble($str) 287 | { 288 | return ENDIANNESS === self::BIG_ENDIAN ? unpack('d', $str)[1] : unpack('d', strrev($str))[1]; 289 | } 290 | 291 | 292 | public static function writeDouble($value) 293 | { 294 | return ENDIANNESS === self::BIG_ENDIAN ? pack('d', $value) : strrev(pack('d', $value)); 295 | } 296 | 297 | 298 | public static function readLDouble($str) 299 | { 300 | return ENDIANNESS === self::BIG_ENDIAN ? unpack('d', strrev($str))[1] : unpack('d', $str)[1]; 301 | } 302 | 303 | 304 | public static function writeLDouble($value) 305 | { 306 | return ENDIANNESS === self::BIG_ENDIAN ? strrev(pack('d', $value)) : pack('d', $value); 307 | } 308 | 309 | 310 | public static function readLong($x) 311 | { 312 | if (PHP_INT_SIZE === 8) { 313 | $int = unpack('N*', $x); 314 | return ($int[1] << 32) | $int[2]; 315 | } else { 316 | $value = '0'; 317 | for ($i = 0; $i < 8; $i += 2) { 318 | $value = bcmul($value, '65536', 0); 319 | $value = bcadd($value, self::readShort(substr($x, $i, 2)), 0); 320 | } 321 | 322 | if (bccomp($value, '9223372036854775807') == 1) { 323 | $value = bcadd($value, '-18446744073709551616'); 324 | } 325 | 326 | return $value; 327 | } 328 | } 329 | 330 | 331 | public static function writeLong($value) 332 | { 333 | if (PHP_INT_SIZE === 8) { 334 | return pack('NN', $value >> 32, $value & 0xFFFFFFFF); 335 | } else { 336 | $x = ''; 337 | 338 | if (bccomp($value, '0') == -1) { 339 | $value = bcadd($value, '18446744073709551616'); 340 | } 341 | 342 | $x .= self::writeShort(bcmod(bcdiv($value, '281474976710656'), '65536')); 343 | $x .= self::writeShort(bcmod(bcdiv($value, '4294967296'), '65536')); 344 | $x .= self::writeShort(bcmod(bcdiv($value, '65536'), '65536')); 345 | $x .= self::writeShort(bcmod($value, '65536')); 346 | 347 | return $x; 348 | } 349 | } 350 | 351 | 352 | public static function readLLong($str) 353 | { 354 | return self::readLong(strrev($str)); 355 | } 356 | 357 | 358 | public static function writeLLong($value) 359 | { 360 | return strrev(self::writeLong($value)); 361 | } 362 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/console/Console.php: -------------------------------------------------------------------------------- 1 | 8) { 209 | self::$COLOR_BLACK = $colors >= 256 ? `tput setaf 16` : `tput setaf 0`; 210 | self::$COLOR_DARK_BLUE = $colors >= 256 ? `tput setaf 19` : `tput setaf 4`; 211 | self::$COLOR_DARK_GREEN = $colors >= 256 ? `tput setaf 34` : `tput setaf 2`; 212 | self::$COLOR_DARK_AQUA = $colors >= 256 ? `tput setaf 37` : `tput setaf 6`; 213 | self::$COLOR_DARK_RED = $colors >= 256 ? `tput setaf 124` : `tput setaf 1`; 214 | self::$COLOR_PURPLE = $colors >= 256 ? `tput setaf 127` : `tput setaf 5`; 215 | self::$COLOR_GOLD = $colors >= 256 ? `tput setaf 214` : `tput setaf 3`; 216 | self::$COLOR_GRAY = $colors >= 256 ? `tput setaf 145` : `tput setaf 7`; 217 | self::$COLOR_DARK_GRAY = $colors >= 256 ? `tput setaf 59` : `tput setaf 8`; 218 | self::$COLOR_BLUE = $colors >= 256 ? `tput setaf 63` : `tput setaf 12`; 219 | self::$COLOR_GREEN = $colors >= 256 ? `tput setaf 83` : `tput setaf 10`; 220 | self::$COLOR_AQUA = $colors >= 256 ? `tput setaf 87` : `tput setaf 14`; 221 | self::$COLOR_RED = $colors >= 256 ? `tput setaf 203` : `tput setaf 9`; 222 | self::$COLOR_LIGHT_PURPLE = $colors >= 256 ? `tput setaf 207` : `tput setaf 13`; 223 | self::$COLOR_YELLOW = $colors >= 256 ? `tput setaf 227` : `tput setaf 11`; 224 | self::$COLOR_WHITE = $colors >= 256 ? `tput setaf 231` : `tput setaf 15`; 225 | } else { 226 | self::$COLOR_BLACK = self::$COLOR_DARK_GRAY = `tput setaf 0`; 227 | self::$COLOR_RED = self::$COLOR_DARK_RED = `tput setaf 1`; 228 | self::$COLOR_GREEN = self::$COLOR_DARK_GREEN = `tput setaf 2`; 229 | self::$COLOR_YELLOW = self::$COLOR_GOLD = `tput setaf 3`; 230 | self::$COLOR_BLUE = self::$COLOR_DARK_BLUE = `tput setaf 4`; 231 | self::$COLOR_LIGHT_PURPLE = self::$COLOR_PURPLE = `tput setaf 5`; 232 | self::$COLOR_AQUA = self::$COLOR_DARK_AQUA = `tput setaf 6`; 233 | self::$COLOR_GRAY = self::$COLOR_WHITE = `tput setaf 7`; 234 | } 235 | self::$FORMAT_OBFUSCATED = `tput smacs`; 236 | self::$FORMAT_BOLD = `tput bold`; 237 | self::$FORMAT_ITALIC = `tput sitm`; 238 | self::$FORMAT_UNDERLINE = `tput smul`; 239 | self::$FORMAT_STRIKETHROUGH = "\x1b[9m"; //`tput `; 240 | self::$FORMAT_RESET = `tput sgr0`; 241 | } else { 242 | self::$COLOR_BLACK = self::$COLOR_DARK_GRAY = ''; 243 | self::$COLOR_RED = self::$COLOR_DARK_RED = ''; 244 | self::$COLOR_GREEN = self::$COLOR_DARK_GREEN = ''; 245 | self::$COLOR_YELLOW = self::$COLOR_GOLD = ''; 246 | self::$COLOR_BLUE = self::$COLOR_DARK_BLUE = ''; 247 | self::$COLOR_LIGHT_PURPLE = self::$COLOR_PURPLE = ''; 248 | self::$COLOR_AQUA = self::$COLOR_DARK_AQUA = ''; 249 | self::$COLOR_GRAY = self::$COLOR_WHITE = ''; 250 | self::$FORMAT_OBFUSCATED = ''; 251 | self::$FORMAT_BOLD = ''; 252 | self::$FORMAT_ITALIC = ''; 253 | self::$FORMAT_UNDERLINE = ''; 254 | self::$FORMAT_STRIKETHROUGH = ''; 255 | self::$FORMAT_RESET = ''; 256 | } 257 | } 258 | 259 | 260 | public static function init() 261 | { 262 | switch (Utils::getOS()) { 263 | case 'linux': 264 | case 'mac': 265 | case 'bsd': 266 | self::setEscapeCodes(); 267 | break; 268 | 269 | case 'win': 270 | self::setFallbackEscapeCodes(); 271 | break; 272 | case 'android': 273 | self::setFallbackEscapeCodes(); 274 | self::$FORMAT_ITALIC = '';//I can't see this on android 275 | break; 276 | } 277 | } 278 | 279 | 280 | public static function getInput($default = null) 281 | { 282 | $input = trim(fgets(STDIN)); 283 | return $input === '' ? $default : $input; 284 | } 285 | 286 | 287 | public static function log($msg = '') 288 | { 289 | echo self::toANSI('§f§r' . $msg . '§f§r' . PHP_EOL); 290 | } 291 | 292 | 293 | public static function info($msg = '', $cr = false) 294 | { 295 | if ($cr) 296 | $str = self::toANSI("\r" . '§b§l[' . date('H:i:s') . '] §f§r' . $msg . '§f§r'); 297 | else 298 | $str = self::toANSI('§b§l[' . date('H:i:s') . '] §f§r' . $msg . '§f§r' . PHP_EOL); 299 | 300 | echo $str; 301 | } 302 | 303 | 304 | public static function error($msg = '') 305 | { 306 | echo self::toANSI('§c§l[ERROR] §f§r' . $msg . '§f§r' . PHP_EOL); 307 | } 308 | 309 | 310 | public static function notice($msg = '') 311 | { 312 | echo self::toANSI('§d§l[NOTICE] §f§r' . $msg . '§f§r' . PHP_EOL); 313 | } 314 | 315 | 316 | public static function usage($msg = '') 317 | { 318 | echo self::toANSI('§c§l[USAGE] ' . '§f§r' . $msg . '§f§r' . PHP_EOL); 319 | } 320 | 321 | 322 | public static function input($msg = '', $eol = false) 323 | { 324 | $msg = self::toANSI('§e§l[INPUT] ' . '§f§r' . $msg . '§f§r'); 325 | echo $eol ? $msg . PHP_EOL : $msg; 326 | } 327 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/NBT.php: -------------------------------------------------------------------------------- 1 | getName() !== $tag2->getName() or $tag1->getCount() !== $tag2->getCount()) { 65 | return false; 66 | } 67 | 68 | foreach ($tag1 as $k => $v) { 69 | if (!($v instanceof Tag)) { 70 | continue; 71 | } 72 | 73 | if (!isset($tag2->{$k}) or !($tag2->{$k} instanceof $v)) { 74 | return false; 75 | } 76 | 77 | if ($v instanceof CompoundTag) { 78 | if (!self::matchTree($v, $tag2->{$k})) { 79 | return false; 80 | } 81 | } elseif ($v instanceof ListTag) { 82 | if (!self::matchList($v, $tag2->{$k})) { 83 | return false; 84 | } 85 | } else { 86 | if ($v->getValue() !== $tag2->{$k}->getValue()) { 87 | return false; 88 | } 89 | } 90 | } 91 | 92 | return true; 93 | } 94 | 95 | 96 | public static function matchTree(CompoundTag $tag1, CompoundTag $tag2) 97 | { 98 | if ($tag1->getName() !== $tag2->getName() or $tag1->getCount() !== $tag2->getCount()) { 99 | return false; 100 | } 101 | 102 | foreach ($tag1 as $k => $v) { 103 | if (!($v instanceof Tag)) { 104 | continue; 105 | } 106 | 107 | if (!isset($tag2->{$k}) or !($tag2->{$k} instanceof $v)) { 108 | return false; 109 | } 110 | 111 | if ($v instanceof CompoundTag) { 112 | if (!self::matchTree($v, $tag2->{$k})) { 113 | return false; 114 | } 115 | } elseif ($v instanceof ListTag) { 116 | if (!self::matchList($v, $tag2->{$k})) { 117 | return false; 118 | } 119 | } else { 120 | if ($v->getValue() !== $tag2->{$k}->getValue()) { 121 | return false; 122 | } 123 | } 124 | } 125 | 126 | return true; 127 | } 128 | 129 | 130 | public static function combineCompoundTags(CompoundTag $tag1, CompoundTag $tag2, bool $override = false) : CompoundTag 131 | { 132 | $tag1 = clone $tag1; 133 | foreach ($tag2 as $k => $v) { 134 | if (!($v instanceof Tag)) { 135 | continue; 136 | } 137 | if (!isset($tag1->{$k}) or (isset($tag1->{$k}) and $override)) { 138 | $tag1->{$k} = clone $v; 139 | } 140 | } 141 | return $tag1; 142 | } 143 | 144 | 145 | public static function parseJSON($data, &$offset = 0) 146 | { 147 | $len = strlen($data); 148 | for (; $offset < $len; ++$offset) { 149 | $c = $data{$offset}; 150 | if ($c === "{") { 151 | ++$offset; 152 | $data = self::parseCompound($data, $offset); 153 | return new CompoundTag("", $data); 154 | } elseif ($c !== " " and $c !== "\r" and $c !== "\n" and $c !== "\t") { 155 | throw new \Exception("Syntax error: unexpected '$c' at offset $offset"); 156 | } 157 | } 158 | 159 | return null; 160 | } 161 | 162 | 163 | private static function parseList($str, &$offset = 0) 164 | { 165 | $len = strlen($str); 166 | 167 | 168 | $key = 0; 169 | $value = null; 170 | 171 | $data = []; 172 | 173 | for (; $offset < $len; ++$offset) { 174 | if ($str{$offset - 1} === "]") { 175 | break; 176 | } elseif ($str{$offset} === "]") { 177 | ++$offset; 178 | break; 179 | } 180 | 181 | $value = self::readValue($str, $offset, $type); 182 | 183 | switch ($type) { 184 | case NBT::TAG_Byte: 185 | $data[$key] = new ByteTag($key, $value); 186 | break; 187 | case NBT::TAG_Short: 188 | $data[$key] = new ShortTag($key, $value); 189 | break; 190 | case NBT::TAG_Int: 191 | $data[$key] = new IntTag($key, $value); 192 | break; 193 | case NBT::TAG_Long: 194 | $data[$key] = new LongTag($key, $value); 195 | break; 196 | case NBT::TAG_Float: 197 | $data[$key] = new FloatTag($key, $value); 198 | break; 199 | case NBT::TAG_Double: 200 | $data[$key] = new DoubleTag($key, $value); 201 | break; 202 | case NBT::TAG_ByteArray: 203 | $data[$key] = new ByteArrayTag($key, $value); 204 | break; 205 | case NBT::TAG_String: 206 | $data[$key] = new StringTag($key, $value); 207 | break; 208 | case NBT::TAG_List: 209 | $data[$key] = new ListTag($key, $value); 210 | break; 211 | case NBT::TAG_Compound: 212 | $data[$key] = new CompoundTag($key, $value); 213 | break; 214 | case NBT::TAG_IntArray: 215 | $data[$key] = new IntArrayTag($key, $value); 216 | break; 217 | } 218 | 219 | $key++; 220 | } 221 | 222 | return $data; 223 | } 224 | 225 | 226 | private static function parseCompound($str, &$offset = 0) 227 | { 228 | $len = strlen($str); 229 | 230 | $data = []; 231 | 232 | for (; $offset < $len; ++$offset) { 233 | if ($str{$offset - 1} === "}") { 234 | break; 235 | } elseif ($str{$offset} === "}") { 236 | ++$offset; 237 | break; 238 | } 239 | 240 | $key = self::readKey($str, $offset); 241 | $value = self::readValue($str, $offset, $type); 242 | 243 | switch ($type) { 244 | case NBT::TAG_Byte: 245 | $data[$key] = new ByteTag($key, $value); 246 | break; 247 | case NBT::TAG_Short: 248 | $data[$key] = new ShortTag($key, $value); 249 | break; 250 | case NBT::TAG_Int: 251 | $data[$key] = new IntTag($key, $value); 252 | break; 253 | case NBT::TAG_Long: 254 | $data[$key] = new LongTag($key, $value); 255 | break; 256 | case NBT::TAG_Float: 257 | $data[$key] = new FloatTag($key, $value); 258 | break; 259 | case NBT::TAG_Double: 260 | $data[$key] = new DoubleTag($key, $value); 261 | break; 262 | case NBT::TAG_ByteArray: 263 | $data[$key] = new ByteArrayTag($key, $value); 264 | break; 265 | case NBT::TAG_String: 266 | $data[$key] = new StringTag($key, $value); 267 | break; 268 | case NBT::TAG_List: 269 | $data[$key] = new ListTag($key, $value); 270 | break; 271 | case NBT::TAG_Compound: 272 | $data[$key] = new CompoundTag($key, $value); 273 | break; 274 | case NBT::TAG_IntArray: 275 | $data[$key] = new IntArrayTag($key, $value); 276 | break; 277 | } 278 | } 279 | 280 | return $data; 281 | } 282 | 283 | 284 | private static function readValue($data, &$offset, &$type = null) 285 | { 286 | $value = ""; 287 | $type = null; 288 | $inQuotes = false; 289 | 290 | $len = strlen($data); 291 | for (; $offset < $len; ++$offset) { 292 | $c = $data{$offset}; 293 | 294 | if (!$inQuotes and ($c === " " or $c === "\r" or $c === "\n" or $c === "\t" or $c === "," or $c === "}" or $c === "]")) { 295 | if ($c === "," or $c === "}" or $c === "]") { 296 | break; 297 | } 298 | } elseif ($c === '"') { 299 | $inQuotes = !$inQuotes; 300 | if ($type === null) { 301 | $type = self::TAG_String; 302 | } elseif ($inQuotes) { 303 | throw new \Exception("Syntax error: invalid quote at offset $offset"); 304 | } 305 | } elseif ($c === "\\") { 306 | $value .= isset($data{$offset + 1}) ? $data{$offset + 1} : ""; 307 | ++$offset; 308 | } elseif ($c === "{" and !$inQuotes) { 309 | if ($value !== "") { 310 | throw new \Exception("Syntax error: invalid compound start at offset $offset"); 311 | } 312 | ++$offset; 313 | $value = self::parseCompound($data, $offset); 314 | $type = self::TAG_Compound; 315 | break; 316 | } elseif ($c === "[" and !$inQuotes) { 317 | if ($value !== "") { 318 | throw new \Exception("Syntax error: invalid list start at offset $offset"); 319 | } 320 | ++$offset; 321 | $value = self::parseList($data, $offset); 322 | $type = self::TAG_List; 323 | break; 324 | } else { 325 | $value .= $c; 326 | } 327 | } 328 | 329 | if ($value === "") { 330 | throw new \Exception("Syntax error: invalid empty value at offset $offset"); 331 | } 332 | 333 | if ($type === null and strlen($value) > 0) { 334 | $value = trim($value); 335 | $last = strtolower(substr($value, -1)); 336 | $part = substr($value, 0, -1); 337 | 338 | if ($last !== "b" and $last !== "s" and $last !== "l" and $last !== "f" and $last !== "d") { 339 | $part = $value; 340 | $last = null; 341 | } 342 | 343 | if ($last !== "f" and $last !== "d" and ((string)((int)$part)) === $part) { 344 | if ($last === "b") { 345 | $type = self::TAG_Byte; 346 | } elseif ($last === "s") { 347 | $type = self::TAG_Short; 348 | } elseif ($last === "l") { 349 | $type = self::TAG_Long; 350 | } else { 351 | $type = self::TAG_Int; 352 | } 353 | $value = (int)$part; 354 | } elseif (is_numeric($part)) { 355 | if ($last === "f" or $last === "d" or strpos($part, ".") !== false) { 356 | if ($last === "f") { 357 | $type = self::TAG_Float; 358 | } elseif ($last === "d") { 359 | $type = self::TAG_Double; 360 | } else { 361 | $type = self::TAG_Float; 362 | } 363 | $value = (float)$part; 364 | } else { 365 | if ($last === "l") { 366 | $type = self::TAG_Long; 367 | } else { 368 | $type = self::TAG_Int; 369 | } 370 | 371 | $value = $part; 372 | } 373 | } else { 374 | $type = self::TAG_String; 375 | } 376 | } 377 | 378 | return $value; 379 | } 380 | 381 | 382 | private static function readKey($data, &$offset) 383 | { 384 | $key = ""; 385 | 386 | $len = strlen($data); 387 | for (; $offset < $len; ++$offset) { 388 | $c = $data{$offset}; 389 | 390 | if ($c === ":") { 391 | ++$offset; 392 | break; 393 | } elseif ($c !== " " and $c !== "\r" and $c !== "\n" and $c !== "\t") { 394 | $key .= $c; 395 | } 396 | } 397 | 398 | if ($key === "") { 399 | throw new \Exception("Syntax error: invalid empty key at offset $offset"); 400 | } 401 | 402 | return $key; 403 | } 404 | 405 | 406 | public function get($len) 407 | { 408 | if ($len < 0) { 409 | $this->offset = strlen($this->buffer) - 1; 410 | return ""; 411 | } elseif ($len === true) { 412 | return substr($this->buffer, $this->offset); 413 | } 414 | 415 | return $len === 1 ? $this->buffer{$this->offset++} : substr($this->buffer, ($this->offset += $len) - $len, $len); 416 | } 417 | 418 | 419 | public function put($v) 420 | { 421 | $this->buffer .= $v; 422 | } 423 | 424 | 425 | public function feof() 426 | { 427 | return !isset($this->buffer{$this->offset}); 428 | } 429 | 430 | 431 | public function __construct($endianness = self::LITTLE_ENDIAN) 432 | { 433 | $this->offset = 0; 434 | $this->endianness = $endianness & 0x01; 435 | } 436 | 437 | 438 | public function read($buffer, $doMultiple = false) 439 | { 440 | $this->offset = 0; 441 | $this->buffer = $buffer; 442 | $this->data = $this->readTag(); 443 | if ($doMultiple and $this->offset < strlen($this->buffer)) { 444 | $this->data = [$this->data]; 445 | do { 446 | $this->data[] = $this->readTag(); 447 | } while ($this->offset < strlen($this->buffer)); 448 | } 449 | $this->buffer = ""; 450 | } 451 | 452 | 453 | public function readCompressed($buffer, $compression = ZLIB_ENCODING_GZIP) 454 | { 455 | $this->read(zlib_decode($buffer)); 456 | } 457 | 458 | 459 | /** 460 | * @return string|bool 461 | */ 462 | public function write() 463 | { 464 | $this->offset = 0; 465 | $this->buffer = ""; 466 | 467 | if ($this->data instanceof CompoundTag) { 468 | $this->writeTag($this->data); 469 | 470 | return $this->buffer; 471 | } elseif (is_array($this->data)) { 472 | foreach ($this->data as $tag) { 473 | $this->writeTag($tag); 474 | } 475 | return $this->buffer; 476 | } 477 | 478 | return false; 479 | } 480 | 481 | 482 | public function writeCompressed($compression = ZLIB_ENCODING_GZIP, $level = 7) 483 | { 484 | if (($write = $this->write()) !== false) { 485 | return zlib_encode($write, $compression, $level); 486 | } 487 | 488 | return false; 489 | } 490 | 491 | 492 | public function readTag() 493 | { 494 | switch ($this->getByte()) { 495 | case NBT::TAG_Byte: 496 | $tag = new ByteTag($this->getString()); 497 | $tag->read($this); 498 | break; 499 | case NBT::TAG_Short: 500 | $tag = new ShortTag($this->getString()); 501 | $tag->read($this); 502 | break; 503 | case NBT::TAG_Int: 504 | $tag = new IntTag($this->getString()); 505 | $tag->read($this); 506 | break; 507 | case NBT::TAG_Long: 508 | $tag = new LongTag($this->getString()); 509 | $tag->read($this); 510 | break; 511 | case NBT::TAG_Float: 512 | $tag = new FloatTag($this->getString()); 513 | $tag->read($this); 514 | break; 515 | case NBT::TAG_Double: 516 | $tag = new DoubleTag($this->getString()); 517 | $tag->read($this); 518 | break; 519 | case NBT::TAG_ByteArray: 520 | $tag = new ByteArrayTag($this->getString()); 521 | $tag->read($this); 522 | break; 523 | case NBT::TAG_String: 524 | $tag = new StringTag($this->getString()); 525 | $tag->read($this); 526 | break; 527 | case NBT::TAG_List: 528 | $tag = new ListTag($this->getString()); 529 | $tag->read($this); 530 | break; 531 | case NBT::TAG_Compound: 532 | $tag = new CompoundTag($this->getString()); 533 | $tag->read($this); 534 | break; 535 | case NBT::TAG_IntArray: 536 | $tag = new IntArrayTag($this->getString()); 537 | $tag->read($this); 538 | break; 539 | 540 | case NBT::TAG_End: //No named tag 541 | default: 542 | $tag = new EndTag; 543 | break; 544 | } 545 | return $tag; 546 | } 547 | 548 | 549 | public function writeTag(Tag $tag) 550 | { 551 | $this->putByte($tag->getType()); 552 | if ($tag instanceof NamedTAG) { 553 | $this->putString($tag->getName()); 554 | } 555 | $tag->write($this); 556 | } 557 | 558 | 559 | public function getByte() 560 | { 561 | return Binary::readByte($this->get(1)); 562 | } 563 | 564 | 565 | public function putByte($v) 566 | { 567 | $this->buffer .= Binary::writeByte($v); 568 | } 569 | 570 | 571 | public function getShort() 572 | { 573 | return $this->endianness === self::BIG_ENDIAN ? Binary::readShort($this->get(2)) : Binary::readLShort($this->get(2)); 574 | } 575 | 576 | 577 | public function putShort($v) 578 | { 579 | $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeShort($v) : Binary::writeLShort($v); 580 | } 581 | 582 | 583 | public function getInt() 584 | { 585 | return $this->endianness === self::BIG_ENDIAN ? Binary::readInt($this->get(4)) : Binary::readLInt($this->get(4)); 586 | } 587 | 588 | 589 | public function putInt($v) 590 | { 591 | $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeInt($v) : Binary::writeLInt($v); 592 | } 593 | 594 | 595 | public function getLong() 596 | { 597 | return $this->endianness === self::BIG_ENDIAN ? Binary::readLong($this->get(8)) : Binary::readLLong($this->get(8)); 598 | } 599 | 600 | 601 | public function putLong($v) 602 | { 603 | $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeLong($v) : Binary::writeLLong($v); 604 | } 605 | 606 | 607 | public function getFloat() 608 | { 609 | return $this->endianness === self::BIG_ENDIAN ? Binary::readFloat($this->get(4)) : Binary::readLFloat($this->get(4)); 610 | } 611 | 612 | 613 | public function putFloat($v) 614 | { 615 | $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeFloat($v) : Binary::writeLFloat($v); 616 | } 617 | 618 | 619 | public function getDouble() 620 | { 621 | return $this->endianness === self::BIG_ENDIAN ? Binary::readDouble($this->get(8)) : Binary::readLDouble($this->get(8)); 622 | } 623 | 624 | 625 | public function putDouble($v) 626 | { 627 | $this->buffer .= $this->endianness === self::BIG_ENDIAN ? Binary::writeDouble($v) : Binary::writeLDouble($v); 628 | } 629 | 630 | 631 | public function getString() 632 | { 633 | return $this->get($this->getShort()); 634 | } 635 | 636 | 637 | public function putString($v) 638 | { 639 | $this->putShort(strlen($v)); 640 | $this->buffer .= $v; 641 | } 642 | 643 | 644 | public function getArray() 645 | { 646 | $data = []; 647 | self::toArray($data, $this->data); 648 | } 649 | 650 | 651 | private static function toArray(array &$data, Tag $tag) 652 | { 653 | /** @var CompoundTag[]|ListTag[]|IntArrayTag[] $tag */ 654 | foreach ($tag as $key => $value) { 655 | if ($value instanceof CompoundTag or $value instanceof ListTag or $value instanceof IntArrayTag) { 656 | $data[$key] = []; 657 | self::toArray($data[$key], $value); 658 | } else { 659 | $data[$key] = $value->getValue(); 660 | } 661 | } 662 | } 663 | 664 | 665 | public static function fromArrayGuesser($key, $value) 666 | { 667 | if (is_int($value)) { 668 | return new IntTag($key, $value); 669 | } elseif (is_float($value)) { 670 | return new FloatTag($key, $value); 671 | } elseif (is_string($value)) { 672 | return new StringTag($key, $value); 673 | } elseif (is_bool($value)) { 674 | return new ByteTag($key, $value ? 1 : 0); 675 | } 676 | 677 | return null; 678 | } 679 | 680 | 681 | private static function fromArray(Tag $tag, array $data, callable $guesser) 682 | { 683 | foreach ($data as $key => $value) { 684 | if (is_array($value)) { 685 | $isNumeric = true; 686 | $isIntArray = true; 687 | foreach ($value as $k => $v) { 688 | if (!is_numeric($k)) { 689 | $isNumeric = false; 690 | break; 691 | } elseif (!is_int($v)) { 692 | $isIntArray = false; 693 | } 694 | } 695 | $tag{$key} = $isNumeric ? ($isIntArray ? new IntArrayTag($key, []) : new ListTag($key, [])) : new CompoundTag($key, []); 696 | self::fromArray($tag->{$key}, $value, $guesser); 697 | } else { 698 | $v = call_user_func($guesser, $key, $value); 699 | if ($v instanceof Tag) { 700 | $tag{$key} = $v; 701 | } 702 | } 703 | } 704 | } 705 | 706 | 707 | public function setArray(array $data, callable $guesser = null) 708 | { 709 | $this->data = new CompoundTag("", []); 710 | self::fromArray($this->data, $data, $guesser === null ? [self::class, "fromArrayGuesser"] : $guesser); 711 | } 712 | 713 | 714 | /** 715 | * @return CompoundTag|array 716 | */ 717 | public function getData() 718 | { 719 | return $this->data; 720 | } 721 | 722 | 723 | /** 724 | * @param CompoundTag|array $data 725 | */ 726 | public function setData($data) 727 | { 728 | $this->data = $data; 729 | } 730 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/ByteArrayTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->get($nbt->getInt()); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putInt(strlen($this->value)); 41 | $nbt->put($this->value); 42 | } 43 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/ByteTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->getByte(); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putByte($this->value); 41 | } 42 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/CompoundTag.php: -------------------------------------------------------------------------------- 1 | __name = $name; 33 | foreach ($value as $tag) { 34 | $this->{$tag->getName()} = $tag; 35 | } 36 | } 37 | 38 | 39 | public function getCount() 40 | { 41 | $count = 0; 42 | foreach ($this as $tag) { 43 | if ($tag instanceof Tag) { 44 | ++$count; 45 | } 46 | } 47 | 48 | return $count; 49 | } 50 | 51 | 52 | public function offsetExists($offset) 53 | { 54 | return isset($this->{$offset}) and $this->{$offset} instanceof Tag; 55 | } 56 | 57 | 58 | public function offsetGet($offset) 59 | { 60 | if (isset($this->{$offset}) and $this->{$offset} instanceof Tag) { 61 | if ($this->{$offset} instanceof \ArrayAccess) { 62 | return $this->{$offset}; 63 | } else { 64 | return $this->{$offset}->getValue(); 65 | } 66 | } 67 | 68 | return null; 69 | } 70 | 71 | 72 | public function offsetSet($offset, $value) 73 | { 74 | if ($value instanceof Tag) { 75 | $this->{$offset} = $value; 76 | } elseif (isset($this->{$offset}) and $this->{$offset} instanceof Tag) { 77 | $this->{$offset}->setValue($value); 78 | } 79 | } 80 | 81 | 82 | public function offsetUnset($offset) 83 | { 84 | unset($this->{$offset}); 85 | } 86 | 87 | 88 | public function getType() 89 | { 90 | return NBT::TAG_Compound; 91 | } 92 | 93 | 94 | public function read(NBT $nbt) 95 | { 96 | $this->value = []; 97 | do { 98 | $tag = $nbt->readTag(); 99 | if ($tag instanceof NamedTag and $tag->getName() !== "") { 100 | $this->{$tag->getName()} = $tag; 101 | } 102 | } while (!($tag instanceof EndTag) and !$nbt->feof()); 103 | } 104 | 105 | 106 | public function write(NBT $nbt) 107 | { 108 | foreach ($this as $tag) { 109 | if ($tag instanceof Tag and !($tag instanceof EndTag)) { 110 | $nbt->writeTag($tag); 111 | } 112 | } 113 | $nbt->writeTag(new EndTag()); 114 | } 115 | 116 | 117 | public function __toString() 118 | { 119 | $str = get_class($this) . "{\n"; 120 | foreach ($this as $tag) { 121 | if ($tag instanceof Tag) { 122 | $str .= get_class($tag) . ":" . $tag->__toString() . "\n"; 123 | } 124 | } 125 | return $str . "}"; 126 | } 127 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/DoubleTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->getDouble(); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putDouble($this->value); 41 | } 42 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/EndTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->getFloat(); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putFloat($this->value); 41 | } 42 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/IntArrayTag.php: -------------------------------------------------------------------------------- 1 | getInt(); 35 | $this->value = array_values(unpack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", $nbt->get($size * 4))); 36 | } 37 | 38 | 39 | public function write(NBT $nbt) 40 | { 41 | $nbt->putInt(count($this->value)); 42 | $nbt->put(pack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", ...$this->value)); 43 | } 44 | 45 | 46 | public function __toString() 47 | { 48 | $str = get_class($this) . "{\n"; 49 | $str .= implode(", ", $this->value); 50 | return $str . "}"; 51 | } 52 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/IntTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->getInt(); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putInt($this->value); 41 | } 42 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/ListTag.php: -------------------------------------------------------------------------------- 1 | __name = $name; 33 | foreach ($value as $k => $v) { 34 | $this->{$k} = $v; 35 | } 36 | } 37 | 38 | 39 | public function &getValue() 40 | { 41 | $value = []; 42 | foreach ($this as $k => $v) { 43 | if ($v instanceof Tag) { 44 | $value[$k] = $v; 45 | } 46 | } 47 | 48 | return $value; 49 | } 50 | 51 | 52 | public function getCount() 53 | { 54 | $count = 0; 55 | foreach ($this as $tag) { 56 | if ($tag instanceof Tag) { 57 | ++$count; 58 | } 59 | } 60 | 61 | return $count; 62 | } 63 | 64 | 65 | public function offsetExists($offset) 66 | { 67 | return isset($this->{$offset}); 68 | } 69 | 70 | 71 | public function offsetGet($offset) 72 | { 73 | if (isset($this->{$offset}) and $this->{$offset} instanceof Tag) { 74 | if ($this->{$offset} instanceof \ArrayAccess) { 75 | return $this->{$offset}; 76 | } else { 77 | return $this->{$offset}->getValue(); 78 | } 79 | } 80 | 81 | return null; 82 | } 83 | 84 | 85 | public function offsetSet($offset, $value) 86 | { 87 | if ($value instanceof Tag) { 88 | $this->{$offset} = $value; 89 | } elseif ($this->{$offset} instanceof Tag) { 90 | $this->{$offset}->setValue($value); 91 | } 92 | } 93 | 94 | 95 | public function offsetUnset($offset) 96 | { 97 | unset($this->{$offset}); 98 | } 99 | 100 | 101 | public function count($mode = COUNT_NORMAL) 102 | { 103 | for ($i = 0; true; $i++) { 104 | if (!isset($this->{$i})) { 105 | return $i; 106 | } 107 | if ($mode === COUNT_RECURSIVE) { 108 | if ($this->{$i} instanceof \Countable) { 109 | $i += count($this->{$i}); 110 | } 111 | } 112 | } 113 | 114 | return $i; 115 | } 116 | 117 | 118 | public function getType() 119 | { 120 | return NBT::TAG_List; 121 | } 122 | 123 | 124 | public function setTagType($type) 125 | { 126 | $this->tagType = $type; 127 | return $this; 128 | } 129 | 130 | 131 | public function getTagType() 132 | { 133 | return $this->tagType; 134 | } 135 | 136 | 137 | public function read(NBT $nbt) 138 | { 139 | $this->value = []; 140 | $this->tagType = $nbt->getByte(); 141 | $size = $nbt->getInt(); 142 | for ($i = 0; $i < $size and !$nbt->feof(); ++$i) { 143 | switch ($this->tagType) { 144 | case NBT::TAG_Byte: 145 | $tag = new ByteTag(""); 146 | $tag->read($nbt); 147 | $this->{$i} = $tag; 148 | break; 149 | case NBT::TAG_Short: 150 | $tag = new ShortTag(""); 151 | $tag->read($nbt); 152 | $this->{$i} = $tag; 153 | break; 154 | case NBT::TAG_Int: 155 | $tag = new IntTag(""); 156 | $tag->read($nbt); 157 | $this->{$i} = $tag; 158 | break; 159 | case NBT::TAG_Long: 160 | $tag = new LongTag(""); 161 | $tag->read($nbt); 162 | $this->{$i} = $tag; 163 | break; 164 | case NBT::TAG_Float: 165 | $tag = new FloatTag(""); 166 | $tag->read($nbt); 167 | $this->{$i} = $tag; 168 | break; 169 | case NBT::TAG_Double: 170 | $tag = new DoubleTag(""); 171 | $tag->read($nbt); 172 | $this->{$i} = $tag; 173 | break; 174 | case NBT::TAG_ByteArray: 175 | $tag = new ByteArrayTag(""); 176 | $tag->read($nbt); 177 | $this->{$i} = $tag; 178 | break; 179 | case NBT::TAG_String: 180 | $tag = new StringTag(""); 181 | $tag->read($nbt); 182 | $this->{$i} = $tag; 183 | break; 184 | case NBT::TAG_List: 185 | $tag = new TagEnum(""); 186 | $tag->read($nbt); 187 | $this->{$i} = $tag; 188 | break; 189 | case NBT::TAG_Compound: 190 | $tag = new CompoundTag(""); 191 | $tag->read($nbt); 192 | $this->{$i} = $tag; 193 | break; 194 | case NBT::TAG_IntArray: 195 | $tag = new IntArrayTag(""); 196 | $tag->read($nbt); 197 | $this->{$i} = $tag; 198 | break; 199 | } 200 | } 201 | } 202 | 203 | 204 | public function write(NBT $nbt) 205 | { 206 | if (!isset($this->tagType)) { 207 | $id = null; 208 | foreach ($this as $tag) { 209 | if ($tag instanceof Tag) { 210 | if (!isset($id)) { 211 | $id = $tag->getType(); 212 | } elseif ($id !== $tag->getType()) { 213 | return false; 214 | } 215 | } 216 | } 217 | $this->tagType = $id; 218 | } 219 | 220 | $nbt->putByte($this->tagType); 221 | 222 | /** @var Tag[] $tags */ 223 | $tags = []; 224 | foreach ($this as $tag) { 225 | if ($tag instanceof Tag) { 226 | $tags[] = $tag; 227 | } 228 | } 229 | $nbt->putInt(count($tags)); 230 | foreach ($tags as $tag) { 231 | $tag->write($nbt); 232 | } 233 | } 234 | 235 | 236 | public function __toString() 237 | { 238 | $str = get_class($this) . "{\n"; 239 | foreach ($this as $tag) { 240 | if ($tag instanceof Tag) { 241 | $str .= get_class($tag) . ":" . $tag->__toString() . "\n"; 242 | } 243 | } 244 | return $str . "}"; 245 | } 246 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/LongTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->getLong(); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putLong($this->value); 41 | } 42 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/NamedTag.php: -------------------------------------------------------------------------------- 1 | __name = ($name === null or $name === false) ? "" : $name; 32 | if ($value !== null) { 33 | $this->value = $value; 34 | } 35 | } 36 | 37 | 38 | public function getName() 39 | { 40 | return $this->__name; 41 | } 42 | 43 | 44 | public function setName($name) 45 | { 46 | $this->__name = $name; 47 | } 48 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/ShortTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->getShort(); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putShort($this->value); 41 | } 42 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/StringTag.php: -------------------------------------------------------------------------------- 1 | value = $nbt->get($nbt->getShort()); 35 | } 36 | 37 | 38 | public function write(NBT $nbt) 39 | { 40 | $nbt->putShort(strlen($this->value)); 41 | $nbt->put($this->value); 42 | } 43 | } -------------------------------------------------------------------------------- /src/svile/structureconverter/utils/nbt/tag/Tag.php: -------------------------------------------------------------------------------- 1 | value; 32 | } 33 | 34 | 35 | public abstract function getType(); 36 | 37 | 38 | public function setValue($value) 39 | { 40 | $this->value = $value; 41 | } 42 | 43 | 44 | abstract public function write(NBT $nbt); 45 | 46 | 47 | abstract public function read(NBT $nbt); 48 | 49 | 50 | public function __toString() 51 | { 52 | return (string)$this->value; 53 | } 54 | } --------------------------------------------------------------------------------