mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-05-14 09:49:50 +00:00
Finally, physics
This commit is contained in:
parent
933a28537b
commit
03d7127e33
@ -42,8 +42,8 @@ class Air extends Transparent{
|
||||
|
||||
}
|
||||
|
||||
public function collidesWithBB(AxisAlignedBB $bb, &$list = array()){
|
||||
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(0, 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
}
|
@ -426,6 +426,7 @@ abstract class Block extends Position implements Metadatable{
|
||||
public $x = 0;
|
||||
public $y = 0;
|
||||
public $z = 0;
|
||||
public $frictionFactor = 0.6;
|
||||
|
||||
public static function init(){
|
||||
if(count(self::$list) === 0){
|
||||
@ -720,7 +721,17 @@ abstract class Block extends Position implements Metadatable{
|
||||
* @param Block[] $list
|
||||
*/
|
||||
public function collidesWithBB(AxisAlignedBB $bb, &$list = array()){
|
||||
$bb2 = new AxisAlignedBB(
|
||||
$bb2 = $this->getBoundingBox();
|
||||
if($bb2->intersectsWith($bb)){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return AxisAlignedBB
|
||||
*/
|
||||
public function getBoundingBox(){
|
||||
return new AxisAlignedBB(
|
||||
$this->x,
|
||||
$this->y,
|
||||
$this->z,
|
||||
@ -728,9 +739,6 @@ abstract class Block extends Position implements Metadatable{
|
||||
$this->y + 1,
|
||||
$this->z + 1
|
||||
);
|
||||
if($bb2->intersectsWith($bb)){
|
||||
$list[] = $bb2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,7 @@
|
||||
namespace pocketmine\entity;
|
||||
|
||||
use pocketmine\item\Item;
|
||||
use pocketmine\math\Vector3;
|
||||
use pocketmine\nbt\tag\Byte;
|
||||
use pocketmine\nbt\tag\Compound;
|
||||
use pocketmine\nbt\tag\Short;
|
||||
@ -32,7 +33,6 @@ use pocketmine\Player;
|
||||
|
||||
class DroppedItem extends Entity{
|
||||
|
||||
protected $age = 0;
|
||||
protected $owner = null;
|
||||
protected $thrower = null;
|
||||
protected $pickupDelay = 0;
|
||||
@ -65,6 +65,41 @@ class DroppedItem extends Entity{
|
||||
$this->item = Item::get($this->namedtag->Item["id"], $this->namedtag->Item["Damage"], min(64, $this->namedtag->Item["Count"]));
|
||||
}
|
||||
|
||||
public function onUpdate(){
|
||||
$this->entityBaseTick();
|
||||
//TODO: manage pickupDelay
|
||||
|
||||
$this->motionY -= $this->gravity;
|
||||
$this->inBlock = $this->checkObstruction($this->x, ($this->boundingBox->minY + $this->boundingBox->maxY) / 2, $this->z);
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
if($this->onGround){
|
||||
$friction = $this->getLevel()->getBlock(new Vector3($this->getFloorX(), $this->getFloorY() - 1, $this->getFloorZ()))->frictionFactor * $friction;
|
||||
}
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionY *= 1 - $this->drag;
|
||||
$this->motionZ *= $friction;
|
||||
|
||||
if($this->onGround){
|
||||
$this->motionY *= -0.5;
|
||||
}
|
||||
|
||||
if(abs($this->motionX) < 0.01){
|
||||
$this->motionX = 0;
|
||||
}
|
||||
if(abs($this->motionZ) < 0.01){
|
||||
$this->motionZ = 0;
|
||||
}
|
||||
|
||||
//TODO: update age in base entity tick
|
||||
//TODO: kill entity if it's old enough
|
||||
$this->updateMovement();
|
||||
//$this->server->broadcastMessage("{$this->ticksLived}: ".round($this->x, 2).",".round($this->y, 2).",".round($this->z, 2));
|
||||
}
|
||||
|
||||
public function attack($damage, $source = "generic"){
|
||||
|
||||
}
|
||||
|
@ -78,6 +78,9 @@ abstract class Entity extends Position implements Metadatable{
|
||||
public $motionX;
|
||||
public $motionY;
|
||||
public $motionZ;
|
||||
public $lastMotionX;
|
||||
public $lastMotionY;
|
||||
public $lastMotionZ;
|
||||
|
||||
public $yaw;
|
||||
public $pitch;
|
||||
@ -87,9 +90,11 @@ abstract class Entity extends Position implements Metadatable{
|
||||
/** @var AxisAlignedBB */
|
||||
public $boundingBox;
|
||||
public $onGround;
|
||||
public $inBlock = false;
|
||||
public $positionChanged;
|
||||
public $motionChanged;
|
||||
public $dead;
|
||||
protected $age = 0;
|
||||
|
||||
public $height;
|
||||
public $width;
|
||||
@ -106,7 +111,7 @@ abstract class Entity extends Position implements Metadatable{
|
||||
public $fireTicks;
|
||||
public $airTicks;
|
||||
public $namedtag;
|
||||
|
||||
protected $isStatic = false;
|
||||
protected $isColliding = false;
|
||||
|
||||
protected $inWater;
|
||||
@ -271,24 +276,97 @@ abstract class Entity extends Position implements Metadatable{
|
||||
$this->health = (int) min($this->health, $this->maxHealth);
|
||||
}
|
||||
|
||||
public function onUpdate(){
|
||||
if($this->closed !== false){
|
||||
protected function checkObstruction($x, $y, $z){
|
||||
$i = (int) $x;
|
||||
$j = (int) $y;
|
||||
$k = (int) $z;
|
||||
|
||||
$diffX = $x - $i;
|
||||
$diffY = $y - $j;
|
||||
$diffZ = $z - $k;
|
||||
|
||||
$start = microtime(true);
|
||||
$list = $this->getLevel()->getCollisionBlocks($this->boundingBox);
|
||||
|
||||
if(count($list) === 0 and $this->getLevel()->isFullBlock(new Vector3($i, $j, $k))){
|
||||
return false;
|
||||
}else{
|
||||
$flag = !$this->getLevel()->isFullBlock(new Vector3($i - 1, $j, $k));
|
||||
$flag1 = !$this->getLevel()->isFullBlock(new Vector3($i + 1, $j, $k));
|
||||
//$flag2 = !$this->getLevel()->isFullBlock(new Vector3($i, $j - 1, $k));
|
||||
$flag3 = !$this->getLevel()->isFullBlock(new Vector3($i, $j + 1, $k));
|
||||
$flag4 = !$this->getLevel()->isFullBlock(new Vector3($i, $j, $k - 1));
|
||||
$flag5 = !$this->getLevel()->isFullBlock(new Vector3($i, $j, $k + 1));
|
||||
|
||||
$direction = 3; //UP!
|
||||
$limit = 9999;
|
||||
|
||||
if($flag){
|
||||
$limit = $diffX;
|
||||
$direction = 0;
|
||||
}
|
||||
|
||||
if($flag1 and 1 - $diffX < $limit){
|
||||
$limit = 1 - $diffX;
|
||||
$direction = 1;
|
||||
}
|
||||
|
||||
if($flag3 and 1 - $diffY < $limit){
|
||||
$limit = 1 - $diffY;
|
||||
$direction = 3;
|
||||
}
|
||||
|
||||
if($flag4 and $diffZ < $limit){
|
||||
$limit = $diffZ;
|
||||
$direction = 4;
|
||||
}
|
||||
|
||||
if($flag5 and 1 - $diffZ < $limit){
|
||||
$direction = 5;
|
||||
}
|
||||
|
||||
$force = lcg_value() * 0.2 + 0.1;
|
||||
|
||||
if($direction === 0){
|
||||
$this->motionX = -$force;
|
||||
return true;
|
||||
}
|
||||
|
||||
if($direction === 1){
|
||||
$this->motionX = $force;
|
||||
return true;
|
||||
}
|
||||
|
||||
//No direction 2
|
||||
|
||||
if($direction === 3){
|
||||
$this->motionY = $force;
|
||||
return true;
|
||||
}
|
||||
|
||||
if($direction === 4){
|
||||
$this->motionZ = -$force;
|
||||
return true;
|
||||
}
|
||||
|
||||
if($direction === 5){
|
||||
$this->motionY = $force;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public function entityBaseTick(){
|
||||
//TODO: check vehicles
|
||||
$hasUpdate = false;
|
||||
$timeNow = microtime(true);
|
||||
$ticksOffset = min(20, max(1, floor(($timeNow - $this->lastUpdate) * 20))); //Simulate min one tic and max 20
|
||||
$this->ticksLived += $ticksOffset;
|
||||
if(!($this instanceof Player)){
|
||||
for($tick = 0; $tick < $ticksOffset; ++$tick){
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
if($this->motionX == 0 and $this->motionY == 0 and $this->motionZ == 0){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->lastX = $this->x;
|
||||
$this->lastY = $this->y;
|
||||
$this->lastZ = $this->z;
|
||||
$this->lastMotionX = $this->motionX;
|
||||
$this->lastPitch = $this->pitch;
|
||||
$this->lastYaw = $this->yaw;
|
||||
|
||||
if($this->handleWaterMovement()){
|
||||
$this->fallDistance = 0;
|
||||
@ -298,8 +376,12 @@ abstract class Entity extends Position implements Metadatable{
|
||||
$this->inWater = false;
|
||||
}
|
||||
|
||||
if($this->y < -64){
|
||||
$this->kill();
|
||||
}
|
||||
|
||||
if($this->fireTicks > 0){
|
||||
if($this->fireProof === true){
|
||||
if($this->fireProof){
|
||||
$this->fireTicks -= 4;
|
||||
if($this->fireTicks < 0){
|
||||
$this->fireTicks = 0;
|
||||
@ -310,18 +392,21 @@ abstract class Entity extends Position implements Metadatable{
|
||||
}
|
||||
--$this->fireTicks;
|
||||
}
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
if($this->handleLavaMovement()){
|
||||
$this->attack(4, "lava");
|
||||
$this->setOnFire(15);
|
||||
$hasUpdate = true;
|
||||
$this->fallDistance *= 0.5;
|
||||
}
|
||||
|
||||
if($this->y < -64){
|
||||
$this->kill();
|
||||
++$this->age;
|
||||
++$this->ticksLived;
|
||||
}
|
||||
|
||||
public function updateMovement(){
|
||||
if($this->x !== $this->lastX or $this->y !== $this->lastY or $this->z !== $this->lastZ or $this->yaw !== $this->lastYaw or $this->pitch !== $this->lastPitch){
|
||||
$this->lastX = $this->x;
|
||||
$this->lastY = $this->y;
|
||||
@ -351,7 +436,7 @@ abstract class Entity extends Position implements Metadatable{
|
||||
$this->server->broadcastPacket($this->hasSpawned, $pk);
|
||||
}
|
||||
|
||||
if($this->motionChanged === true){
|
||||
if(!($this instanceof Player) and ($this->lastMotionX != $this->motionX or $this->lastMotionY != $this->motionY or $this->lastMotionZ != $this->motionZ)){
|
||||
$this->motionChanged = false;
|
||||
|
||||
$pk = new SetEntityMotionPacket;
|
||||
@ -361,10 +446,18 @@ abstract class Entity extends Position implements Metadatable{
|
||||
$pk->speedZ = $this->motionZ;
|
||||
$this->server->broadcastPacket($this->hasSpawned, $pk);
|
||||
}
|
||||
}
|
||||
|
||||
$this->lastUpdate = $timeNow;
|
||||
public function onUpdate(){
|
||||
if($this->closed !== false){
|
||||
return false;
|
||||
}
|
||||
|
||||
return !($this instanceof Player) and ($this->motionX != 0 or $this->motionY == 0 or $this->motionZ == 0 or $hasUpdate);
|
||||
$hasUpdate = $this->entityBaseTick();
|
||||
$this->updateMovement();
|
||||
//if($this->isStatic())
|
||||
return true;
|
||||
//return !($this instanceof Player);
|
||||
}
|
||||
|
||||
public final function scheduleUpdate(){
|
||||
@ -605,7 +698,7 @@ abstract class Entity extends Position implements Metadatable{
|
||||
$cy = $dy;
|
||||
$cz = $dz;
|
||||
$dx = $movX;
|
||||
$dy = 0.05;
|
||||
$dy = 0;
|
||||
$dz = $movZ;
|
||||
$oldBB = clone $this->boundingBox;
|
||||
$list = $this->getLevel()->getCollisionCubes($this, $this->boundingBox->getOffsetBoundingBox($movX, $dy, $movZ));
|
||||
@ -648,7 +741,7 @@ abstract class Entity extends Position implements Metadatable{
|
||||
}
|
||||
|
||||
if($movY != $dy){
|
||||
$dy = -0.05;
|
||||
$dy = 0;
|
||||
foreach($list as $bb){
|
||||
$dy = $bb->calculateYOffset($this->boundingBox, $dy);
|
||||
}
|
||||
@ -667,25 +760,20 @@ abstract class Entity extends Position implements Metadatable{
|
||||
$this->x = ($this->boundingBox->minX + $this->boundingBox->maxX) / 2;
|
||||
$this->y = $this->boundingBox->minY + $this->height;
|
||||
$this->z = ($this->boundingBox->minZ + $this->boundingBox->maxZ) / 2;
|
||||
|
||||
$this->onGround = $movY != $dy and $movY < 0;
|
||||
$this->updateFallState($dy, $this->onGround);
|
||||
|
||||
if($movX != $dx){
|
||||
$this->motionX = 0;
|
||||
}else{
|
||||
$this->motionX -= $this->motionX * $this->drag;
|
||||
}
|
||||
|
||||
if($movY != $dy){
|
||||
$this->motionY = 0;
|
||||
}else{
|
||||
$this->motionY -= $this->motionY * $this->drag;
|
||||
}
|
||||
|
||||
if($movZ != $dz){
|
||||
$this->motionZ = 0;
|
||||
}else{
|
||||
$this->motionY -= $this->motionY * $this->drag;
|
||||
}
|
||||
|
||||
//$this->boundingBox->addCoord($dx, $dy, $dz);
|
||||
|
@ -511,6 +511,34 @@ class Level{
|
||||
return Block::get($b[0], $b[1], new Position($pos->x, $pos->y, $pos->z, $this));
|
||||
}
|
||||
|
||||
public function getCollisionBlocks(AxisAlignedBB $bb){
|
||||
$minX = floor($bb->minX);
|
||||
$minY = floor($bb->minY);
|
||||
$minZ = floor($bb->minZ);
|
||||
$maxX = floor($bb->maxX + 1);
|
||||
$maxY = floor($bb->maxY + 1);
|
||||
$maxZ = floor($bb->maxZ + 1);
|
||||
|
||||
$collides = [];
|
||||
|
||||
for($z = $minZ; $z < $maxZ; ++$z){
|
||||
for($x = $minX; $x < $maxX; ++$x){
|
||||
if($this->isChunkLoaded($x >> 4, $z >> 4)){
|
||||
for($y = $minY - 1; $y < $maxY; ++$y){
|
||||
$this->getBlock(new Vector3($x, $y, $z))->collidesWithBB($bb, $collides);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $collides;
|
||||
}
|
||||
|
||||
public function isFullBlock(Vector3 $pos){
|
||||
$bb = $this->getBlock($pos)->getBoundingBox();
|
||||
return $bb instanceof AxisAlignedBB and $bb->getAverageEdgeLength() >= 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Entity $entity
|
||||
* @param AxisAlignedBB $bb
|
||||
@ -537,9 +565,10 @@ class Level{
|
||||
}
|
||||
}
|
||||
|
||||
foreach($entity->getNearbyEntities($bb->expand(0.25, 0.25, 0.25)) as $ent){
|
||||
//TODO: fix this
|
||||
/*foreach($entity->getNearbyEntities($bb->expand(0.25, 0.25, 0.25)) as $ent){
|
||||
$collides[] = $ent->boundingBox;
|
||||
}
|
||||
}*/
|
||||
|
||||
return $collides;
|
||||
}
|
||||
@ -647,22 +676,27 @@ class Level{
|
||||
return $ret;
|
||||
}
|
||||
|
||||
public function dropItem(Vector3 $pos, Item $item){
|
||||
/**
|
||||
* @param Vector3 $source
|
||||
* @param Item $item
|
||||
* @param float $force
|
||||
*/
|
||||
public function dropItem(Vector3 $source, Item $item, $force = 1.0){
|
||||
if($item->getID() !== Item::AIR and $item->getCount() > 0){
|
||||
$itemEntity = new DroppedItem($this, new Compound("", [
|
||||
"Pos" => new Enum("Pos", [
|
||||
new Double("", $pos->getX()),
|
||||
new Double("", $pos->getY()),
|
||||
new Double("", $pos->getZ())
|
||||
new Double("", $source->getX()),
|
||||
new Double("", $source->getY()),
|
||||
new Double("", $source->getZ())
|
||||
]),
|
||||
//TODO: add random motion with physics
|
||||
"Motion" => new Enum("Motion", [
|
||||
new Double("", 0),
|
||||
new Double("", 0.05),
|
||||
new Double("", 0)
|
||||
new Double("", (lcg_value() * 0.2 - 0.1) * $force),
|
||||
new Double("", 0.2 * $force),
|
||||
new Double("", (lcg_value() * 0.2 - 0.1) * $force)
|
||||
]),
|
||||
"Rotation" => new Enum("Rotation", [
|
||||
new Float("", 0),
|
||||
new Float("", lcg_value() * 360),
|
||||
new Float("", 0)
|
||||
]),
|
||||
"Health" => new Short("Health", 5),
|
||||
@ -730,7 +764,7 @@ class Level{
|
||||
|
||||
if(!($player instanceof Player) or ($player->getGamemode() & 0x01) === 0){
|
||||
foreach($target->getDrops($item) as $drop){
|
||||
$this->dropItem($vector->add(0.5, 0.5, 0.5), Item::get($drop[0], $drop[1], $drop[2]));
|
||||
$this->dropItem($vector->add(0.5, 0.5, 0.5), Item::get($drop[0], $drop[1], $drop[2]), 5);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
Loading…
x
Reference in New Issue
Block a user