PocketMine-MP 5.33.2 git-919492bdcad8510eb6606439eb77e1c604f1d1ea
Loading...
Searching...
No Matches
RuntimeDataWriter.php
1<?php
2
3/*
4 *
5 * ____ _ _ __ __ _ __ __ ____
6 * | _ \ ___ ___| | _____| |_| \/ (_)_ __ ___ | \/ | _ \
7 * | |_) / _ \ / __| |/ / _ \ __| |\/| | | '_ \ / _ \_____| |\/| | |_) |
8 * | __/ (_) | (__| < __/ |_| | | | | | | | __/_____| | | | __/
9 * |_| \___/ \___|_|\_\___|\__|_| |_|_|_| |_|\___| |_| |_|_|
10 *
11 * This program is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation, either version 3 of the License, or
14 * (at your option) any later version.
15 *
16 * @author PocketMine Team
17 * @link http://www.pocketmine.net/
18 *
19 *
20 */
21
22declare(strict_types=1);
23
24namespace pocketmine\data\runtime;
25
26use pocketmine\block\utils\WallConnectionType;
29use function log;
30use function spl_object_id;
31
33 private int $value = 0;
34 private int $offset = 0;
35
36 public function __construct(
37 private int $maxBits
38 ){}
39
40 public function writeInt(int $bits, int $value) : void{
41 if($this->offset + $bits > $this->maxBits){
42 throw new \InvalidArgumentException("Bit buffer cannot be larger than $this->maxBits bits (already have $this->offset bits)");
43 }
44 if(($value & (~0 << $bits)) !== 0){
45 throw new \InvalidArgumentException("Value $value does not fit into $bits bits");
46 }
47
48 $this->value |= ($value << $this->offset);
49 $this->offset += $bits;
50 }
51
52 public function int(int $bits, int &$value) : void{
53 $this->writeInt($bits, $value);
54 }
55
56 private function writeBoundedIntAuto(int $min, int $max, int $value) : void{
57 if($value < $min || $value > $max){
58 throw new \InvalidArgumentException("Value $value is outside the range $min - $max");
59 }
60 $bits = ((int) log($max - $min, 2)) + 1;
61 $this->writeInt($bits, $value - $min);
62 }
63
64 public function boundedIntAuto(int $min, int $max, int &$value) : void{
65 $this->writeBoundedIntAuto($min, $max, $value);
66 }
67
68 protected function writeBool(bool $value) : void{
69 $this->writeInt(1, $value ? 1 : 0);
70 }
71
72 public function bool(bool &$value) : void{
73 $this->writeBool($value);
74 }
75
76 public function facingExcept(Facing &$facing, Facing $except) : void{
77 $this->enum($facing);
78 }
79
80 public function horizontalAxis(Axis &$axis) : void{
81 $this->writeInt(1, match($axis){
82 Axis::X => 0,
83 Axis::Z => 1,
84 default => throw new \InvalidArgumentException("Invalid horizontal axis $axis->name")
85 });
86 }
87
92 public function wallConnections(array &$connections) : void{
93 $packed = 0;
94 $offset = 0;
95 foreach(Facing::HORIZONTAL as $facing){
96 $packed += match($connections[$facing->value] ?? null){
97 null => 0,
98 WallConnectionType::SHORT => 1,
99 WallConnectionType::TALL => 2,
100 } * (3 ** $offset);
101 $offset++;
102 }
103 $this->writeBoundedIntAuto(0, (3 ** 4) - 1, $packed);
104 }
105
106 public function enum(\UnitEnum &$case) : void{
107 $metadata = RuntimeEnumMetadata::from($case);
108 $this->writeInt($metadata->bits, $metadata->enumToInt($case));
109 }
110
111 public function enumSet(array &$set, array $allCases) : void{
112 foreach($allCases as $case){
113 $this->writeBool(isset($set[spl_object_id($case)]));
114 }
115 }
116
117 public function getValue() : int{ return $this->value; }
118
119 public function getOffset() : int{ return $this->offset; }
120}
boundedIntAuto(int $min, int $max, int &$value)