selectChunks($radius, $baseX, $baseZ); $middleOffsetX = $scale * ($radius + $offsetX); $middleOffsetZ = $scale * ($radius + $offsetZ); $black = Utils::assumeNotFalse(imagecolorallocate($image, 0, 0, 0)); $yellow = Utils::assumeNotFalse(imagecolorallocate($image, 255, 255, 51)); $red = Utils::assumeNotFalse(imagecolorallocate($image, 255, 0, 0)); $frame = 0; $seen = []; while($iterator->valid()){ $frame++; for($i = 0; $i < $chunksPerStep; ++$i){ $chunkHash = $iterator->current(); if(!isset($seen[$chunkHash])){ $color = $chunkColor; $seen[$chunkHash] = true; }else{ $color = $yellow; } World::getXZ($chunkHash, $chunkX, $chunkZ); $imageX = $middleOffsetX + (($chunkX - $baseX) * $scale); $imageZ = $middleOffsetZ + (($chunkZ - $baseZ) * $scale); imagefilledrectangle($image, $imageX, $imageZ, $imageX + $scale, $imageZ + $scale, $color); imagerectangle($image, $imageX, $imageZ, $imageX + $scale, $imageZ + $scale, $black); $iterator->next(); if(!$iterator->valid()){ break; } } imagearc($image, $middleOffsetX, $middleOffsetZ, $radius * $scale * 2, $radius * $scale * 2, 0, 360, $red); imagepng($image, Path::join($outputFolder, "frame" . str_pad(strval($frame), 5, "0", STR_PAD_LEFT) . ".png")); echo "\rRendered step $frame"; } echo "\n"; } $radius = null; $baseX = 10000 >> Chunk::COORD_BIT_SIZE; $baseZ = 10000 >> Chunk::COORD_BIT_SIZE; $nChunksPerStep = 32; $scale = 10; if(count(getopt("", ["help"])) !== 0){ echo "Required parameters:\n"; echo "--output=path/to/dir: Output folder to put the generated images into (will attempt to create if it doesn't exist)\n"; echo "--radius=N: Radius of chunks to render (default $radius)\n"; echo "\n"; echo "Optional parameters:\n"; echo "--baseX=N: Base X coordinate to use for simulation (default $baseX\n"; echo "--baseZ=N: Base Z coordinate to use for simulation (default $baseZ)\n"; echo "--scale=N: Height/width of square of pixels to use for each chunk (default $scale)\n"; echo "--chunksPerStep=N: Number of chunks to process in each frame (default $nChunksPerStep)\n"; exit(0); } $opts = getopt("", ["radius:", "baseX:", "baseZ:", "scale:", "chunksPerStep:", "output:"]); foreach(["radius", "baseX", "baseZ", "scale", "chunksPerStep"] as $name){ $value = $opts[$name] ?? null; if($value === null){ continue; } if(!is_string($value) || (string) ((int) $value) !== $value){ fwrite(STDERR, "Value for --$name must be an integer\n"); exit(1); } $value = (int) $value; match($name){ "radius" => ($radius = $value), "baseX" => ($baseX = $value), "baseZ" => ($baseZ = $value), "scale" => ($scale = $value), "chunksPerStep" => ($nChunksPerStep = $value) }; } if($radius === null){ fwrite(STDERR, "Please specify a radius using --radius\n"); exit(1); } if($radius < 1){ fwrite(STDERR, "Radius cannot be less than 1\n"); exit(1); } if($scale < 1){ fwrite(STDERR, "Scale cannot be less than 1\n"); exit(1); } if($nChunksPerStep < 1){ fwrite(STDERR, "Chunks per step cannot be less than 1\n"); exit(1); } $outputDirectory = null; if(isset($opts["output"])){ $value = $opts["output"]; if(!is_string($value)){ fwrite(STDERR, "Value for --output be a string\n"); exit(1); } if(!@mkdir($value) && !is_dir($value)){ fwrite(STDERR, "Output directory $value could not be created\n"); exit(1); } $files = scandir($value, SCANDIR_SORT_NONE); if($files !== false && count($files) > 2){ //always returns . and .. fwrite(STDERR, "Output directory $value is not empty\n"); exit(1); } $outputDirectory = Utils::assumeNotFalse(realpath($value), "We just created this directory, we should be able to get its realpath"); } if($outputDirectory === null){ fwrite(STDERR, "Please specify an output directory using --output\n"); exit(1); } $image = newImage($scale, $radius); $green = Utils::assumeNotFalse(imagecolorallocate($image, 0, 220, 0)); render($radius, $baseX, $baseZ, $nChunksPerStep, $scale, $image, $green, 0, 0, $outputDirectory);