Skip to content

Commit 24268c5

Browse files
committed
add block-/entity support for version 1.12+
1 parent 29074c9 commit 24268c5

File tree

8 files changed

+403
-15
lines changed

8 files changed

+403
-15
lines changed

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@ vendor/
33
.idea/
44
tests/files/
55
create_versions_folder.php
6-
src/Versions/v1139
76
src/Versions/v1241
87
src/Versions/v1343
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
namespace Aternos\Hawk\Versions\v1139;
4+
5+
use Aternos\Hawk\BlockChunk;
6+
use Aternos\Hawk\McCoordinates2D;
7+
use Aternos\Hawk\McCoordinates3D;
8+
use Aternos\Hawk\Section;
9+
use Aternos\Nbt\Tag\CompoundTag;
10+
use Aternos\Nbt\Tag\Tag;
11+
use Exception;
12+
13+
class BlockChunkV1139 extends BlockChunk
14+
{
15+
/**
16+
* @param CompoundTag $tag
17+
* @param McCoordinates2D $coordinates
18+
* @param int $version
19+
* @return Section|null
20+
*/
21+
public function newSectionFromTag(CompoundTag $tag, McCoordinates2D $coordinates, int $version): ?Section
22+
{
23+
return SectionV1139::newFromTag($tag, $coordinates, $version);
24+
}
25+
26+
/**
27+
* @param McCoordinates3D $coordinates
28+
* @param int $version
29+
* @return Section
30+
*/
31+
public function newEmptySection(McCoordinates3D $coordinates, int $version): Section
32+
{
33+
return SectionV1139::newEmpty($coordinates, $version);
34+
}
35+
}

src/Versions/v1139/DataV1139.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
<?php
2+
3+
namespace Aternos\Hawk\Versions\v1139;
4+
5+
use Aternos\Hawk\Data;
6+
use Aternos\Hawk\DataBlock;
7+
use Aternos\Hawk\Section;
8+
use Aternos\Nbt\Tag\LongArrayTag;
9+
10+
class DataV1139 extends Data
11+
{
12+
/**
13+
* @param $tag
14+
* @param $bitLength
15+
* @param $bitmask
16+
* @param $paletteBlocks
17+
* @param $sectionY
18+
* @return void
19+
*/
20+
public function readInts($tag, $bitLength, $bitmask, $paletteBlocks, $sectionY): void
21+
{
22+
//file_put_contents("LongArrayTag_15_2.txt", $tag); //only for AbstractTest.php
23+
$numberOfBlocks = floor(static::INTEGER_SIZE / $bitLength); // Number of blocks per int64
24+
$counter = 0; //breakpoint for DataTest.php
25+
$fraction = 0;
26+
$fractioned = false;
27+
foreach ($tag as $key => $int64) {
28+
//$debugDataBlocks = []; //only for AbstractTest.php, Breakpoint with condition $int64 !== 0
29+
for ($blockCounter = 0; $blockCounter < $numberOfBlocks && $counter < Section::BLOCKS_PER_SECTION; $blockCounter++, $counter++) {
30+
$intBitLength = $this->getBitLength($int64);
31+
//check for fractions
32+
if ($intBitLength < $bitLength) {
33+
$fractioned = true;
34+
$fraction = $int64;
35+
}
36+
if ($fractioned === true) {
37+
// combine both fractions
38+
$fractionBitLength = $this->getBitLength($fraction);
39+
$diff = $bitLength - $fractionBitLength;
40+
$dummyRef = $int64 >> (64 - ($diff));
41+
$dummyRef <<= $fractionBitLength;
42+
$ref = $dummyRef & $fraction;
43+
$fractioned = false;
44+
$fraction = 0;
45+
} else {
46+
// Get the last $bitLength bits of int64 which equal the index of the palette block in the palette
47+
$ref = $int64 & $bitmask;
48+
}
49+
50+
$this->dataBlocks[] = new DataBlock($ref, $paletteBlocks[$ref]);
51+
//$debugDataBlocks[] = new DataBlock($ref, $paletteBlocks[$ref]); //only for AbstractTest.php
52+
53+
// Shifts $bitLength bits to the right -> cut off last index
54+
$int64 = $int64 >> $bitLength;
55+
$int64 &= 0x7FFFFFFFFFFFFFFF;
56+
}
57+
}
58+
}
59+
60+
/**
61+
* @param int $bitLength
62+
* @param int $section
63+
* @return LongArrayTag
64+
*/
65+
public function writeInts(int $bitLength, int $section): LongArrayTag
66+
{
67+
$data = new LongArrayTag();
68+
// Number of blocks that fit into an int
69+
$numberOfBlocks = ceil(static::INTEGER_SIZE / $bitLength);
70+
$dataArrayLength = ceil(Section::BLOCKS_PER_SECTION * $bitLength / static::INTEGER_SIZE);
71+
$blockCounter = 0; // Counts to max amount of blocks in section
72+
$offset = 0;
73+
$fraction = 0; // Part of a block int that overflows
74+
for ($i = 0; $i < $dataArrayLength; $i++) {
75+
$int64 = 0; // New compressed int64 filled with 0's
76+
for ($j = 0; $j < $numberOfBlocks && $blockCounter < Section::BLOCKS_PER_SECTION; $j++, $blockCounter++) {
77+
$int64Length = $this->getBitLength($int64); // Current bit length of $int64
78+
$bitLengthDiff = static::INTEGER_SIZE - $int64Length;
79+
$ref = $this->dataBlocks[$blockCounter]->getId();
80+
if ($bitLengthDiff < $bitLength) {
81+
$fraction = $ref >> $bitLengthDiff; // Datablock ref bit shifted by $bitLengthDiff to get the overflow bit(s)
82+
$bitmask = $this->getBitMask($bitLengthDiff);
83+
$fillUp = $ref & $bitmask; // Get the bit(s) that fill(s) the gap
84+
$fillUp <<= $int64Length; // Shift the bit(s) to the left most position
85+
$int64 |= $fillUp; // Add the bit(s) to $int64
86+
}
87+
if ($fraction !== 0) {
88+
$int64 = $fraction;
89+
$offset = $this->getBitLength($fraction);
90+
$fraction = 0;
91+
} else {
92+
// Building int64 from right to left.
93+
// Left shift $ref to the next zeroed position.
94+
$shiftedRef = $ref << ($j * $bitLength + $offset);
95+
// Write $shiftedRef into int64
96+
$int64 |= $shiftedRef;
97+
}
98+
}
99+
$data[] = $int64;
100+
}
101+
return $data;
102+
}
103+
104+
}

src/Versions/v1139/SectionV1139.php

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
<?php
2+
3+
namespace Aternos\Hawk\Versions\v1139;
4+
5+
use Aternos\Hawk\Data;
6+
use Aternos\Hawk\DataBlock;
7+
use Aternos\Hawk\McCoordinates2D;
8+
use Aternos\Hawk\McCoordinates3D;
9+
use Aternos\Hawk\Palette;
10+
use Aternos\Hawk\PaletteBlock;
11+
use Aternos\Hawk\Section;
12+
use Aternos\Nbt\Tag\ByteTag;
13+
use Aternos\Nbt\Tag\CompoundTag;
14+
use Aternos\Nbt\Tag\ListTag;
15+
16+
class SectionV1139 extends Section
17+
{
18+
protected Palette $palette;
19+
20+
protected Data $data;
21+
22+
/**
23+
* Overloaded with new and newFromTag
24+
*/
25+
protected function __construct()
26+
{
27+
parent::__construct();
28+
}
29+
30+
/**
31+
* @inheritDoc
32+
*/
33+
public static function newEmpty(McCoordinates3D $coordinates, int $version): Section
34+
{
35+
$section = new static();
36+
$section->coordinates = $coordinates;
37+
$section->version = $version;
38+
39+
$paletteBlocks[] = PaletteBlock::new();
40+
$section->palette = static::newPalette($paletteBlocks);
41+
42+
43+
$dataBlocks = [];
44+
$dataBlock = new DataBlock(0, $paletteBlocks[0]);
45+
for ($i = 0; $i < static::BLOCKS_PER_SECTION; $i++) {
46+
$dataBlocks[] = $dataBlock;
47+
}
48+
49+
$section->data = static::newData($dataBlocks);
50+
return $section;
51+
}
52+
53+
/**
54+
* @inheritDoc
55+
*/
56+
public static function newFromTag(CompoundTag $tag, McCoordinates2D $coordinates, int $version): ?Section
57+
{
58+
$section = new static();
59+
$section->tag = $tag;
60+
$section->version = $version;
61+
$section->coordinates = new McCoordinates3D($coordinates->x, $tag->getByte("Y")->getValue(), $coordinates->z);
62+
$paletteTag = $tag->getList($section->paletteTagName);
63+
if ($paletteTag === null) {
64+
return null;
65+
}
66+
$section->palette = $section->newPaletteFromTag($paletteTag);
67+
$section->data = $section->newDataFromTag($section, $tag, $section->coordinates->y);
68+
return $section;
69+
}
70+
71+
/**
72+
* @param array $dataBlocks
73+
* @return Data
74+
*/
75+
protected static function newData(array $dataBlocks): Data
76+
{
77+
return DataV1139::new($dataBlocks);
78+
}
79+
80+
/**
81+
* @param Section $section
82+
* @param CompoundTag $tag
83+
* @param int $sectionY
84+
* @return Data
85+
*/
86+
protected static function newDataFromTag(Section $section, CompoundTag $tag, int $sectionY): Data
87+
{
88+
return DataV1139::newFromTag($tag->getLongArray($section->dataTagName), $section->palette, $section->version, $sectionY);
89+
}
90+
91+
/**
92+
* @param array $paletteBlocks
93+
* @return Palette
94+
*/
95+
protected static function newPalette(array $paletteBlocks): Palette
96+
{
97+
return Palette::new($paletteBlocks);
98+
}
99+
100+
/**
101+
* @param ListTag $paletteTag
102+
* @return Palette
103+
*/
104+
protected static function newPaletteFromTag(ListTag $paletteTag): Palette
105+
{
106+
return Palette::newFromTag($paletteTag);
107+
}
108+
109+
/**
110+
* @inheritDoc
111+
*/
112+
public function getBlock(McCoordinates3D $coordinates): DataBlock
113+
{
114+
$index = $this->calcDataBlocksIndex(Section::getBlockCoordinates($coordinates));
115+
116+
// If section is empty
117+
if (isset($this->palette) && $this->getPalette()->getLength() === 1 && $this->getPalette()->getPaletteBlocks()[0]->getName() === "minecraft:air") {
118+
return new DataBlock(0, $this->getPalette()->getPaletteBlocks()[0]);
119+
}
120+
return $this->getData()->getDataBlock($index);
121+
}
122+
123+
/**
124+
* @inheritDoc
125+
*/
126+
public function replaceBlock(McCoordinates3D $coordinates, string $blockName = "minecraft:stone"): void
127+
{
128+
$index = $this->calcDataBlocksIndex(Section::getBlockCoordinates($coordinates));
129+
$dataBlock = $this->createDataBlock($blockName);
130+
$this->getData()->setDataBlock($index, $dataBlock);
131+
}
132+
133+
/**
134+
* @inheritDoc
135+
*/
136+
public function createTag(): CompoundTag
137+
{
138+
$section = new CompoundTag();
139+
$section->set("Y", (new ByteTag())->setValue($this->coordinates->y));
140+
$section->set($this->dataTagName, $this->data->createTag($this->getPalette()->getLength(), $this->coordinates->y));
141+
$section->set($this->paletteTagName, $this->palette->createTag());
142+
return $section;
143+
}
144+
145+
/**
146+
* @return Palette
147+
*/
148+
public function getPalette(): Palette
149+
{
150+
return $this->palette;
151+
}
152+
153+
/**
154+
* @return Data
155+
*/
156+
public function getData(): Data
157+
{
158+
return $this->data;
159+
}
160+
161+
/**
162+
* @param string $name
163+
* @param array $properties
164+
* @return PaletteBlock
165+
*/
166+
public function createPaletteBlock(string $name = "minecraft:air", array $properties = []): PaletteBlock
167+
{
168+
$paletteBlock = PaletteBlock::new($name, $properties);
169+
$this->getPalette()->addPaletteBlock($paletteBlock);
170+
return $paletteBlock;
171+
}
172+
173+
/**
174+
* @param string $blockName
175+
* @return DataBlock
176+
*/
177+
public function createDataBlock(string $blockName = "minecraft:stone"): DataBlock
178+
{
179+
$paletteBlock = $this->getPalette()->findPaletteBlock($blockName);
180+
if ($paletteBlock === null) {
181+
$paletteBlock = $this->createPaletteBlock($blockName);
182+
}
183+
$arraySearch = array_search($paletteBlock, $this->palette->getPaletteBlocks());
184+
185+
return new DataBlock($arraySearch, $this->getPalette()->getPaletteBlocks()[$arraySearch]);
186+
}
187+
}

0 commit comments

Comments
 (0)