Improved Falling blocks physics, entity kill, chunk unserialize, fixed flat generator color, fixed nbt tags __toString(), fixed explosion offsets, fixed increased player interaction range in creative

This commit is contained in:
Shoghi Cervantes 2015-05-13 12:18:59 +02:00
parent f3bdef7513
commit b1edfd7631
14 changed files with 84 additions and 52 deletions

View File

@ -1813,7 +1813,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
if($packet->face >= 0 and $packet->face <= 5){ //Use Block, place if($packet->face >= 0 and $packet->face <= 5){ //Use Block, place
$this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false); $this->setDataFlag(self::DATA_FLAGS, self::DATA_FLAG_ACTION, false);
if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 10) or $this->isSpectator()){ if(!$this->canInteract($blockVector->add(0.5, 0.5, 0.5), 13) or $this->isSpectator()){
}elseif($this->isCreative()){ }elseif($this->isCreative()){
$item = $this->inventory->getItemInHand(); $item = $this->inventory->getItemInHand();
@ -2084,7 +2084,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
$oldItem = clone $item; $oldItem = clone $item;
if($this->canInteract($vector->add(0.5, 0.5, 0.5), 10) and $this->level->useBreakOn($vector, $item, $this) === true){ if($this->canInteract($vector->add(0.5, 0.5, 0.5), 13) and $this->level->useBreakOn($vector, $item, $this) === true){
if($this->isSurvival()){ if($this->isSurvival()){
if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){ if(!$item->equals($oldItem, true) or $item->getCount() !== $oldItem->getCount()){
$this->inventory->setItemInHand($item, $this); $this->inventory->setItemInHand($item, $this);
@ -2754,7 +2754,7 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
} }
public function kill(){ public function kill(){
if(!$this->isAlive() or $this->spawned === false){ if(!$this->spawned){
return; return;
} }
@ -2863,10 +2863,6 @@ class Player extends Human implements CommandSender, InventoryHolder, IPlayer{
} }
if(!$this->isAlive()){
return;
}
Entity::kill(); Entity::kill();
$this->server->getPluginManager()->callEvent($ev = new PlayerDeathEvent($this, $this->getDrops(), new TranslationContainer($message, $params))); $this->server->getPluginManager()->callEvent($ev = new PlayerDeathEvent($this, $this->getDrops(), new TranslationContainer($message, $params)));

View File

@ -47,7 +47,7 @@ abstract class Fallable extends Solid{
$fall = Entity::createEntity("FallingSand", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [ $fall = Entity::createEntity("FallingSand", $this->getLevel()->getChunk($this->x >> 4, $this->z >> 4), new Compound("", [
"Pos" => new Enum("Pos", [ "Pos" => new Enum("Pos", [
new Double("", $this->x + 0.5), new Double("", $this->x + 0.5),
new Double("", $this->y + 0.5), new Double("", $this->y),
new Double("", $this->z + 0.5) new Double("", $this->z + 0.5)
]), ]),
"Motion" => new Enum("Motion", [ "Motion" => new Enum("Motion", [

View File

@ -24,6 +24,7 @@
*/ */
namespace pocketmine\entity; namespace pocketmine\entity;
use pocketmine\block\Block;
use pocketmine\block\Water; use pocketmine\block\Water;
use pocketmine\event\entity\EntityDamageEvent; use pocketmine\event\entity\EntityDamageEvent;
use pocketmine\event\entity\EntityDespawnEvent; use pocketmine\event\entity\EntityDespawnEvent;
@ -568,13 +569,14 @@ abstract class Entity extends Location implements Metadatable{
* @param int $amount * @param int $amount
*/ */
public function setHealth($amount){ public function setHealth($amount){
$amount = (int) $amount;
if($amount === $this->health){ if($amount === $this->health){
return; return;
} }
if($amount <= 0){ if($amount <= 0){
if($this->isAlive()){
$this->health = 0; $this->health = 0;
if(!$this->isAlive()){
$this->kill(); $this->kill();
} }
}elseif($amount <= $this->getMaxHealth() or $amount < $this->health){ }elseif($amount <= $this->getMaxHealth() or $amount < $this->health){
@ -617,23 +619,21 @@ abstract class Entity extends Location implements Metadatable{
} }
protected function checkObstruction($x, $y, $z){ protected function checkObstruction($x, $y, $z){
$i = Math::floorFloat($x); $i = (int) $x;
$j = Math::floorFloat($y); $j = (int) $y;
$k = Math::floorFloat($z); $k = (int) $z;
$diffX = $x - $i; $diffX = $x - $i;
$diffY = $y - $j; $diffY = $y - $j;
$diffZ = $z - $k; $diffZ = $z - $k;
$v = new Vector3($i, $j, $k); if(Block::$solid[$this->level->getBlockIdAt($i, $j, $k)]){
$flag = !Block::$solid[$this->level->getBlockIdAt($i - 1, $j, $k)];
if($this->level->isFullBlock($v)){ $flag1 = !Block::$solid[$this->level->getBlockIdAt($i + 1, $j, $k)];
$flag = !$this->level->isFullBlock($v->setComponents($i - 1, $j, $k)); $flag2 = !Block::$solid[$this->level->getBlockIdAt($i, $j - 1, $k)];
$flag1 = !$this->level->isFullBlock($v->setComponents($i + 1, $j, $k)); $flag3 = !Block::$solid[$this->level->getBlockIdAt($i, $j + 1, $k)];
$flag2 = !$this->level->isFullBlock($v->setComponents($i, $j - 1, $k)); $flag4 = !Block::$solid[$this->level->getBlockIdAt($i, $j, $k - 1)];
$flag3 = !$this->level->isFullBlock($v->setComponents($i, $j + 1, $k)); $flag5 = !Block::$solid[$this->level->getBlockIdAt($i, $j, $k + 1)];
$flag4 = !$this->level->isFullBlock($v->setComponents($i, $j, $k - 1));
$flag5 = !$this->level->isFullBlock($v->setComponents($i, $j, $k + 1));
$direction = -1; $direction = -1;
$limit = 9999; $limit = 9999;
@ -701,10 +701,9 @@ abstract class Entity extends Location implements Metadatable{
if($direction === 5){ if($direction === 5){
$this->motionY = $force; $this->motionY = $force;
}
return true; return true;
}
} }
return false; return false;
@ -1385,9 +1384,6 @@ abstract class Entity extends Location implements Metadatable{
} }
public function kill(){ public function kill(){
if(!$this->isAlive()){
return;
}
$this->setHealth(0); $this->setHealth(0);
$this->scheduleUpdate(); $this->scheduleUpdate();
} }

View File

@ -95,8 +95,10 @@ class FallingSand extends Entity{
$hasUpdate = $this->entityBaseTick($tickDiff); $hasUpdate = $this->entityBaseTick($tickDiff);
if($this->isAlive()){ if($this->isAlive()){
$pos = (new Vector3($this->x - 0.5, $this->y, $this->z - 0.5))->floor();
if($this->ticksLived === 1){ if($this->ticksLived === 1){
$block = $this->level->getBlock($pos = (new Vector3($this->x - 0.5, $this->y - 0.5, $this->z - 0.5))->floor()); $block = $this->level->getBlock($pos);
if($block->getId() !== $this->blockId){ if($block->getId() !== $this->blockId){
$this->kill(); $this->kill();
return true; return true;
@ -114,7 +116,7 @@ class FallingSand extends Entity{
$this->motionY *= 1 - $this->drag; $this->motionY *= 1 - $this->drag;
$this->motionZ *= $friction; $this->motionZ *= $friction;
$pos = (new Vector3($this->x, $this->y, $this->z))->floor(); $pos = (new Vector3($this->x - 0.5, $this->y, $this->z - 0.5))->floor();
if($this->onGround){ if($this->onGround){
$this->kill(); $this->kill();

View File

@ -83,7 +83,7 @@ class Item extends Entity{
} }
public function onUpdate($currentTick){ public function onUpdate($currentTick){
if($this->closed !== false){ if($this->closed){
return false; return false;
} }
@ -102,7 +102,7 @@ class Item extends Entity{
$this->motionY -= $this->gravity; $this->motionY -= $this->gravity;
$this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z); $this->checkObstruction($this->x, $this->y, $this->z);
$this->move($this->motionX, $this->motionY, $this->motionZ); $this->move($this->motionX, $this->motionY, $this->motionZ);
$friction = 1 - $this->drag; $friction = 1 - $this->drag;

View File

@ -130,7 +130,7 @@ class Explosion{
public function explodeB(){ public function explodeB(){
$send = []; $send = [];
$source = (new Vector3($this->source->x, $this->source->y, $this->source->z))->round(); $source = (new Vector3($this->source->x, $this->source->y, $this->source->z))->floor();
$yield = (1 / $this->size) * 100; $yield = (1 / $this->size) * 100;
if($this->what instanceof Entity){ if($this->what instanceof Entity){

View File

@ -953,12 +953,12 @@ class Level implements ChunkManager, Metadatable{
* @return AxisAlignedBB[] * @return AxisAlignedBB[]
*/ */
public function getCollisionCubes(Entity $entity, AxisAlignedBB $bb, $entities = true){ public function getCollisionCubes(Entity $entity, AxisAlignedBB $bb, $entities = true){
$minX = Math::floorFloat($bb->minX); $minX = (int) $bb->minX;
$minY = Math::floorFloat($bb->minY); $minY = (int) $bb->minY;
$minZ = Math::floorFloat($bb->minZ); $minZ = (int) $bb->minZ;
$maxX = Math::ceilFloat($bb->maxX); $maxX = (int) ($bb->maxX + 1);
$maxY = Math::ceilFloat($bb->maxY); $maxY = (int) ($bb->maxY + 1);
$maxZ = Math::ceilFloat($bb->maxZ); $maxZ = (int) ($bb->maxZ + 1);
$collides = []; $collides = [];
$v = $this->temporalVector; $v = $this->temporalVector;

View File

@ -66,6 +66,8 @@ abstract class BaseFullChunk implements FullChunk{
protected $hasChanged = false; protected $hasChanged = false;
private $isInit = false;
/** /**
* @param LevelProvider $provider * @param LevelProvider $provider
* @param int $x * @param int $x
@ -106,7 +108,7 @@ abstract class BaseFullChunk implements FullChunk{
} }
public function initChunk(){ public function initChunk(){
if($this->getProvider() instanceof LevelProvider and $this->NBTentities !== null){ if($this->getProvider() instanceof LevelProvider and !$this->isInit and $this->NBTentities !== null){
$this->getProvider()->getLevel()->timings->syncChunkLoadEntitiesTimer->startTiming(); $this->getProvider()->getLevel()->timings->syncChunkLoadEntitiesTimer->startTiming();
foreach($this->NBTentities as $nbt){ foreach($this->NBTentities as $nbt){
if($nbt instanceof Compound){ if($nbt instanceof Compound){
@ -154,8 +156,8 @@ abstract class BaseFullChunk implements FullChunk{
$this->NBTentities = null; $this->NBTentities = null;
$this->NBTtiles = null; $this->NBTtiles = null;
$this->hasChanged = false;
$this->isInit = true;
} }
if(!$this->isLightPopulated() and $this->isPopulated()){ if(!$this->isLightPopulated() and $this->isPopulated()){
@ -280,14 +282,14 @@ abstract class BaseFullChunk implements FullChunk{
public function addEntity(Entity $entity){ public function addEntity(Entity $entity){
$this->entities[$entity->getId()] = $entity; $this->entities[$entity->getId()] = $entity;
if(!($entity instanceof Player)){ if(!($entity instanceof Player) and $this->isInit){
$this->hasChanged = true; $this->hasChanged = true;
} }
} }
public function removeEntity(Entity $entity){ public function removeEntity(Entity $entity){
unset($this->entities[$entity->getId()]); unset($this->entities[$entity->getId()]);
if(!($entity instanceof Player)){ if(!($entity instanceof Player) and $this->isInit){
$this->hasChanged = true; $this->hasChanged = true;
} }
} }
@ -298,14 +300,18 @@ abstract class BaseFullChunk implements FullChunk{
$this->tileList[$index]->close(); $this->tileList[$index]->close();
} }
$this->tileList[$index] = $tile; $this->tileList[$index] = $tile;
if($this->isInit){
$this->hasChanged = true; $this->hasChanged = true;
} }
}
public function removeTile(Tile $tile){ public function removeTile(Tile $tile){
unset($this->tiles[$tile->getId()]); unset($this->tiles[$tile->getId()]);
unset($this->tileList[(($tile->z & 0x0f) << 12) | (($tile->x & 0x0f) << 8) | ($tile->y & 0xff)]); unset($this->tileList[(($tile->z & 0x0f) << 12) | (($tile->x & 0x0f) << 8) | ($tile->y & 0xff)]);
if($this->isInit){
$this->hasChanged = true; $this->hasChanged = true;
} }
}
public function getEntities(){ public function getEntities(){
return $this->entities; return $this->entities;

View File

@ -247,7 +247,7 @@ class Chunk extends BaseFullChunk{
if($provider instanceof LevelDB){ if($provider instanceof LevelDB){
$nbt = new NBT(NBT::LITTLE_ENDIAN); $nbt = new NBT(NBT::LITTLE_ENDIAN);
$entityData = $provider->getDatabase()->get(substr($data, 0, 8) . "\x32"); $entityData = $provider->getDatabase()->get(substr($data, 0, 8) . LevelDB::ENTRY_ENTITIES);
if($entityData !== false and strlen($entityData) > 0){ if($entityData !== false and strlen($entityData) > 0){
$nbt->read($entityData, true); $nbt->read($entityData, true);
$entities = $nbt->getData(); $entities = $nbt->getData();
@ -255,7 +255,7 @@ class Chunk extends BaseFullChunk{
$entities = [$entities]; $entities = [$entities];
} }
} }
$tileData = $provider->getDatabase()->get(substr($data, 0, 8) . "\x31"); $tileData = $provider->getDatabase()->get(substr($data, 0, 8) . LevelDB::ENTRY_TILES);
if($tileData !== false and strlen($tileData) > 0){ if($tileData !== false and strlen($tileData) > 0){
$nbt->read($tileData, true); $nbt->read($tileData, true);
$tiles = $nbt->getData(); $tiles = $nbt->getData();
@ -302,9 +302,9 @@ class Chunk extends BaseFullChunk{
} }
if(count($entities) > 0){ if(count($entities) > 0){
$provider->getDatabase()->put($chunkIndex . "\x32", implode($entities)); $provider->getDatabase()->put($chunkIndex . LevelDB::ENTRY_ENTITIES, implode($entities));
}else{ }else{
$provider->getDatabase()->delete($chunkIndex . "\x32"); $provider->getDatabase()->delete($chunkIndex . LevelDB::ENTRY_ENTITIES);
} }
@ -318,9 +318,9 @@ class Chunk extends BaseFullChunk{
} }
if(count($tiles) > 0){ if(count($tiles) > 0){
$provider->getDatabase()->put($chunkIndex . "\x31", implode($tiles)); $provider->getDatabase()->put($chunkIndex . LevelDB::ENTRY_TILES, implode($tiles));
}else{ }else{
$provider->getDatabase()->delete($chunkIndex . "\x31"); $provider->getDatabase()->delete($chunkIndex . LevelDB::ENTRY_TILES);
} }

View File

@ -32,6 +32,7 @@ use pocketmine\block\RedstoneOre;
use pocketmine\item\Item; use pocketmine\item\Item;
use pocketmine\level\ChunkManager; use pocketmine\level\ChunkManager;
use pocketmine\level\format\FullChunk; use pocketmine\level\format\FullChunk;
use pocketmine\level\generator\biome\Biome;
use pocketmine\level\generator\populator\Ore; use pocketmine\level\generator\populator\Ore;
use pocketmine\level\generator\populator\Populator; use pocketmine\level\generator\populator\Populator;
use pocketmine\math\Vector3; use pocketmine\math\Vector3;
@ -110,10 +111,15 @@ class Flat extends Generator{
$this->chunk = clone $this->level->getChunk($chunkX, $chunkZ); $this->chunk = clone $this->level->getChunk($chunkX, $chunkZ);
$this->chunk->setGenerated(); $this->chunk->setGenerated();
$c = Biome::getBiome($biome)->getColor();
$R = $c >> 16;
$G = ($c >> 8) & 0xff;
$B = $c & 0xff;
for($Z = 0; $Z < 16; ++$Z){ for($Z = 0; $Z < 16; ++$Z){
for($X = 0; $X < 16; ++$X){ for($X = 0; $X < 16; ++$X){
$this->chunk->setBiomeId($X, $Z, $biome); $this->chunk->setBiomeId($X, $Z, $biome);
$this->chunk->setBiomeColor($X, $Z, $R, $G, $B);
for($y = 0; $y < 128; ++$y){ for($y = 0; $y < 128; ++$y){
$this->chunk->setBlock($X, $y, $Z, ...$this->structure[$y]); $this->chunk->setBlock($X, $y, $Z, ...$this->structure[$y]);
} }

View File

@ -88,4 +88,14 @@ class Compound extends NamedTag implements \ArrayAccess{
} }
$nbt->writeTag(new End); $nbt->writeTag(new End);
} }
public function __toString(){
$str = get_class($this) . "{\n";
foreach($this as $tag){
if($tag instanceof Tag){
$str .= get_class($tag) . ":" . $tag->__toString() . "\n";
}
}
return $str . "}";
}
} }

View File

@ -197,4 +197,14 @@ class Enum extends NamedTag implements \ArrayAccess, \Countable{
$tag->write($nbt); $tag->write($nbt);
} }
} }
public function __toString(){
$str = get_class($this) . "{\n";
foreach($this as $tag){
if($tag instanceof Tag){
$str .= get_class($tag) . ":" . $tag->__toString() . "\n";
}
}
return $str . "}";
}
} }

View File

@ -44,4 +44,10 @@ class IntArray extends NamedTag{
$nbt->putInt(count($this->value)); $nbt->putInt(count($this->value));
$nbt->put(pack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", ...$this->value)); $nbt->put(pack($nbt->endianness === NBT::LITTLE_ENDIAN ? "V*" : "N*", ...$this->value));
} }
public function __toString(){
$str = get_class($this) . "{\n";
$str .= implode(", ", $this->value);
return $str . "}";
}
} }

View File

@ -44,7 +44,7 @@ abstract class Tag extends \stdClass{
abstract public function read(NBT $nbt); abstract public function read(NBT $nbt);
public final function __toString(){ public function __toString(){
return (string) $this->value; return (string) $this->value;
} }
} }