Skip to content
Permalink
Browse files

Fix 1.9+ chunk writing, specifically direct palette

  • Loading branch information
timmyRS committed Jan 25, 2020
1 parent d6ce053 commit 5b9ab5fc15d6055482eda2fb04604b8b7459a9ac
Showing with 37 additions and 56 deletions.
  1. +1 −28 plugins/Structure.php
  2. +11 −6 src/Phpcraft.php
  3. +25 −22 src/World/Chunk.php
@@ -3,7 +3,7 @@
* @var Plugin $this
*/
use Phpcraft\
{ChatComponent, ClientConnection, Command\ServerCommandSender, Connection, IntegratedServer, Plugin, World\BlockState, World\Structure};
{ChatComponent, ClientConnection, Connection, IntegratedServer, Plugin, World\Structure};
$this->registerCommand([
"structure",
"loadstructure",
@@ -30,30 +30,3 @@
$client->sendMessage("That's a ".$structure->width." x ".$structure->height." x ".$structure->depth." structure coming right at ya!");
$server->world->apply($structure, $client->pos);
}, "change the world");
$this->registerCommand("debug_structure", function(ClientConnection $con)
{
$blocks = [];
for($i = 0; $i < 256; $i++)
{
$blocks[$i] = BlockState::getById($i, 498);
}
$server = $con->getServer();
assert($server instanceof IntegratedServer);
$server->world->apply(new Structure(16, 1, 16, $blocks), $con->pos);
});
$this->registerCommand("setblock", function(ClientConnection $con)
{
$server = $con->getServer();
assert($server instanceof IntegratedServer);
$server->world->set($con->pos, BlockState::get("gold_block"));
});
$this->registerCommand("palette", function(ServerCommandSender $sender, int $x, int $y, int $z)
{
$server = $sender->getServer();
assert($server instanceof IntegratedServer);
$i = 0;
foreach($server->world->getChunk(floor($x / 16), floor($z / 16))->getSection(floor($y / 16))->getPalette() as $state_fqn => $state)
{
$sender->sendMessage(($i++).": ".$state_fqn);
}
});
@@ -257,17 +257,22 @@ private static function resolveName(string $server, bool $withPort = true): stri
return $server.($withPort ? ":25565" : "");
}

static function binaryStringToBin(string $str): string
{
$bin_str = "";
foreach(str_split($str) as $char)
{
$bin_str .= str_pad(decbin(ord($char)), 8, "0", STR_PAD_LEFT)." ";
}
return rtrim($bin_str);
}

static function binaryStringToHex(string $str): string
{
$hex_str = "";
foreach(str_split($str) as $char)
{
$char = dechex(ord($char));
if(strlen($char) != 2)
{
$char = "0".$char;
}
$hex_str .= $char." ";
$hex_str .= str_pad(dechex(ord($char)), 2, "0", STR_PAD_LEFT)." ";
}
return rtrim($hex_str);
}
@@ -61,8 +61,18 @@ function getSectionsBitMask(): int
return $this->sections_bit_mask;
}

function getSectionAt(int $y): ChunkSection
{
return $this->getSection(floor($y / 16));
}

function getSection(int $index): ChunkSection
{
if($this->sections[$index] === null)
{
$this->sections[$index] = new ChunkSection();
$this->sections_bit_mask |= (1 << $index);
}
return $this->sections[$index];
}

@@ -77,10 +87,15 @@ function setSection(int $index, ChunkSection $section): void
{
$this->sections_bit_mask ^= (1 << $index);
}
$this->save();
$this->flagChanged();
}

private function save(): void
/**
* Flags the chunk as changed, e.g. for the server to re-send to clients.
*
* @return void
*/
function flagChanged(): void
{
$this->heightmap_cache = null;
if($this->world instanceof World)
@@ -138,7 +153,7 @@ function set(int $x, int $y, int $z, ?BlockState $blockState = null): void
}
$this->sections[$section]->blocks[$block] = $blockState;
$this->sections[$section]->palette_cache = null;
$this->save();
$this->flagChanged();
}

function getIndexes(int $x, int $y, int $z): array
@@ -209,27 +224,15 @@ function write(Connection $con): void
$data->writeShort($section->non_air_blocks);
}
$palette = $section->getPalette();
if(count($palette) > 256)
{
$bits_per_block = count(BlockState::all());
}
else if(count($palette) > 16)
{
$bits_per_block = 8;
}
else
{
$bits_per_block = 4;
}
/*$bits_per_block = 4;
$bits_per_block = 4;
while(count($palette) > pow(2, $bits_per_block))
{
if(++$bits_per_block > 8)
{
$bits_per_block = count(BlockState::all());
$bits_per_block = ceil(log(count(BlockState::all()), 2));
break;
}
}*/
}
$data->writeByte($bits_per_block);
if($bits_per_block < 9)
{
@@ -249,20 +252,20 @@ function write(Connection $con): void
{
for($i = 0; $i < 4096; $i++)
{
$bits .= str_pad(decbin($palette[$section->blocks[$i]->__toString()]), $bits_per_block, "0", STR_PAD_LEFT);
$bits .= strrev(str_pad(decbin($palette[$section->blocks[$i]->__toString()]), $bits_per_block, "0", STR_PAD_LEFT));
}
}
else
{
for($i = 0; $i < 4096; $i++)
{
$bits .= str_pad(decbin($section->blocks[$i]->getCompatible($con->protocol_version)
->getId($con->protocol_version)), $bits_per_block, "0", STR_PAD_LEFT);
$bits .= strrev(str_pad(decbin($section->blocks[$i]->getCompatible($con->protocol_version)
->getId($con->protocol_version)), $bits_per_block, "0", STR_PAD_LEFT));
}
}
for($i = 0; $i < $longs; $i++)
{
$data->writeGMP(gmp_init(substr($bits, $i * 64, 64), 2), 8, 64, false, GMP_MSW_FIRST | GMP_LITTLE_ENDIAN); // For some reason the bit order is reversed
$data->writeGMP(gmp_init(strrev(substr($bits, $i * 64, 64)), 2), 8, 64, false, GMP_LSW_FIRST | GMP_BIG_ENDIAN); // For some reason the bit order is reversed
}
}
else

0 comments on commit 5b9ab5f

Please sign in to comment.
You can’t perform that action at this time.