try it
This commit is contained in:
parent
34df95d508
commit
c6b6eb6827
1 changed files with 232 additions and 187 deletions
|
|
@ -18,197 +18,242 @@
|
|||
* @link https://mcper.cn
|
||||
*
|
||||
*/
|
||||
|
||||
namespace pocketmine\entity;
|
||||
|
||||
use pocketmine\block\Block;
|
||||
use pocketmine\block\Rail;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
use pocketmine\network\protocol\PlayerActionPacket;
|
||||
use pocketmine\network\protocol\AddEntityPacket;
|
||||
use pocketmine\Player;
|
||||
use pocketmine\event\entity\EntityDamageEvent;
|
||||
use pocketmine\network\protocol\EntityEventPacket;
|
||||
use pocketmine\math\Math;
|
||||
use pocketmine\item\Item as ItemItem;
|
||||
|
||||
class Minecart extends Vehicle{
|
||||
const NETWORK_ID = 84;
|
||||
class Minecart extends Vehicle
|
||||
{
|
||||
|
||||
const TYPE_NORMAL = 1;
|
||||
const TYPE_CHEST = 2;
|
||||
const TYPE_HOPPER = 3;
|
||||
const TYPE_TNT = 4;
|
||||
const NETWORK_ID = 84;
|
||||
|
||||
public $height = 0.9;
|
||||
public $width = 1.1;
|
||||
public $height = 0.9;
|
||||
public $width = 1.1;
|
||||
|
||||
public $drag = 0.1;
|
||||
public $gravity = 0.5;
|
||||
public $drag = 0.1;
|
||||
public $gravity = 0.5;
|
||||
|
||||
public $isMoving = false;
|
||||
public $moveSpeed = 0.4;
|
||||
public $isMoving = false;
|
||||
public $moveSpeed = 0.4;
|
||||
|
||||
public function initEntity(){
|
||||
$this->setMaxHealth(1);
|
||||
$this->setHealth($this->getMaxHealth());
|
||||
parent::initEntity();
|
||||
}
|
||||
public $isFreeMoving = false;
|
||||
public $isLinked = false;
|
||||
public $oldPosition = null;
|
||||
public $hasDropped = false;
|
||||
|
||||
public function getName() : string{
|
||||
return "Minecart";
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function initEntity()
|
||||
{
|
||||
$this->setMaxHealth(1);
|
||||
$this->setHealth($this->getMaxHealth());
|
||||
parent::initEntity();
|
||||
}
|
||||
|
||||
public function getType() : int{
|
||||
return self::TYPE_NORMAL;
|
||||
}
|
||||
|
||||
public function onUpdate($currentTick){
|
||||
if($this->closed !== false){
|
||||
return false;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @return unknown
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
return "Minecart";
|
||||
}
|
||||
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
$this->timings->startTiming();
|
||||
/**
|
||||
*
|
||||
* @param unknown $currentTick
|
||||
* @return unknown
|
||||
*/
|
||||
public function onUpdate($currentTick)
|
||||
{
|
||||
if ($this->closed !== false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$hasUpdate = false;
|
||||
//parent::onUpdate($currentTick);
|
||||
$this->lastUpdate = $currentTick;
|
||||
|
||||
if($this->isAlive()){
|
||||
$movingType = $this->getLevel()->getServer()->minecartMovingType;
|
||||
if($movingType == -1) return false;
|
||||
elseif($movingType == 0){
|
||||
$p = $this->getLinkedEntity();
|
||||
if($p instanceof Player){
|
||||
$this->motionX = -sin($p->getYaw() / 180 * M_PI);
|
||||
$this->motionZ = cos($p->getYaw() / 180 * M_PI);
|
||||
}
|
||||
$target = $this->getLevel()->getBlock($this->add($this->motionX, 0, $this->motionZ)->round());
|
||||
$target2 = $this->getLevel()->getBlock($this->add($this->motionX, 0, $this->motionZ)->floor());
|
||||
if($target->getId() != ItemItem::AIR or $target2->getId() != ItemItem::AIR) $this->motionY = $this->gravity * 3;
|
||||
else $this->motionY -= $this->gravity;
|
||||
$this->timings->startTiming();
|
||||
|
||||
if($this->checkObstruction($this->x, $this->y, $this->z)){
|
||||
$hasUpdate = true;
|
||||
}
|
||||
$hasUpdate = false;
|
||||
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
$this->updateMovement();
|
||||
// if Minecart item is droped
|
||||
if ($this->isLinked || $this->isAlive()) {
|
||||
$this->motionY -= $this->gravity;
|
||||
|
||||
$friction = 1 - $this->drag;
|
||||
if ($this->checkObstruction($this->x, $this->y, $this->z)) {
|
||||
$hasUpdate = true;
|
||||
}
|
||||
|
||||
if($this->onGround and (abs($this->motionX) > 0.00001 or abs($this->motionZ) > 0.00001)){
|
||||
$friction = $this->getLevel()->getBlock($this->temporalVector->setComponents((int) floor($this->x), (int) floor($this->y - 1), (int) floor($this->z) - 1))->getFrictionFactor() * $friction;
|
||||
}
|
||||
$this->move($this->motionX, $this->motionY, $this->motionZ);
|
||||
$this->updateMovement();
|
||||
|
||||
$this->motionX *= $friction;
|
||||
$this->motionY *= 1 - $this->drag;
|
||||
$this->motionZ *= $friction;
|
||||
$friction = 1 - $this->drag;
|
||||
|
||||
if($this->onGround){
|
||||
$this->motionY *= -0.5;
|
||||
}
|
||||
}elseif($movingType == 1){
|
||||
$p = $this->getLinkedEntity();
|
||||
if($p instanceof Player){
|
||||
$rail = $this->getNearestRail();
|
||||
if($rail !== null){
|
||||
$this->setPosition($rail);
|
||||
$motX = -sin($p->getYaw() / 180 * M_PI);
|
||||
$motZ = cos($p->getYaw() / 180 * M_PI);
|
||||
if($motX < 0) $motX = -0.5;
|
||||
elseif($motX > 0) $motX = 0.5;
|
||||
if($motZ < 0) $motZ = -0.5;
|
||||
elseif($motZ > 0) $motZ = 0.5;
|
||||
$block = $this->getLevel()->getBlock($this->add($motX, 0, $motZ)->round());
|
||||
if($block instanceof Rail){
|
||||
if($block->check($rail)){
|
||||
if($block->y > $rail->y) $motY = 1.0;
|
||||
else $motY = 0;
|
||||
$f = sqrt(($motX ** 2) + ($motZ ** 2));
|
||||
$this->yaw = (-atan2($motX, $motZ) * 180 / M_PI);
|
||||
$this->pitch = (-atan2($f, $motY) * 180 / M_PI);
|
||||
$this->move($motX, $motY, $motZ);
|
||||
}
|
||||
}
|
||||
$this->updateMovement();
|
||||
}
|
||||
}
|
||||
$hasUpdate = true;
|
||||
}
|
||||
}
|
||||
if ($this->onGround and (abs($this->motionX) > 0.00001 or abs($this->motionZ) > 0.00001)) {
|
||||
$friction = $this->getLevel()->getBlock($this->temporalVector->setComponents((int) floor($this->x), (int) floor($this->y - 1), (int) floor($this->z) - 1))->getFrictionFactor() * $friction;
|
||||
}
|
||||
|
||||
$this->timings->stopTiming();
|
||||
$this->motionX *= $friction;
|
||||
$this->motionY *= 1 - $this->drag;
|
||||
$this->motionZ *= $friction;
|
||||
|
||||
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
|
||||
}
|
||||
if ($this->onGround) {
|
||||
$this->motionY *= -0.5;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Rail
|
||||
*/
|
||||
public function getNearestRail(){
|
||||
$minX = Math::floorFloat($this->boundingBox->minX);
|
||||
$minY = Math::floorFloat($this->boundingBox->minY);
|
||||
$minZ = Math::floorFloat($this->boundingBox->minZ);
|
||||
$maxX = Math::ceilFloat($this->boundingBox->maxX);
|
||||
$maxY = Math::ceilFloat($this->boundingBox->maxY);
|
||||
$maxZ = Math::ceilFloat($this->boundingBox->maxZ);
|
||||
if ($this->isFreeMoving) {
|
||||
$this->motionX = 0;
|
||||
$this->motionZ = 0;
|
||||
$this->isFreeMoving = false;
|
||||
}
|
||||
} else {
|
||||
if ($this->isLinked == false) {
|
||||
parent::onUpdate($currentTick);
|
||||
}
|
||||
}
|
||||
|
||||
$rails = [];
|
||||
$this->timings->stopTiming();
|
||||
|
||||
for($z = $minZ; $z <= $maxZ; ++$z){
|
||||
for($x = $minX; $x <= $maxX; ++$x){
|
||||
for($y = $minY; $y <= $maxY; ++$y){
|
||||
$block = $this->level->getBlock($this->temporalVector->setComponents($x, $y, $z));
|
||||
if(in_array($block->getId(), [Block::RAIL, Block::ACTIVATOR_RAIL, Block::DETECTOR_RAIL, Block::POWERED_RAIL])) $rails[] = $block;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $hasUpdate or !$this->onGround or abs($this->motionX) > 0.00001 or abs($this->motionY) > 0.00001 or abs($this->motionZ) > 0.00001;
|
||||
}
|
||||
|
||||
$minDistance = PHP_INT_MAX;
|
||||
$nearestRail = null;
|
||||
foreach($rails as $rail){
|
||||
$dis = $this->distance($rail);
|
||||
if($dis < $minDistance){
|
||||
$nearestRail = $rail;
|
||||
$minDistance = $dis;
|
||||
}
|
||||
}
|
||||
return $nearestRail;
|
||||
}
|
||||
|
||||
public function spawnTo(Player $player){
|
||||
$pk = new AddEntityPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->type = Minecart::NETWORK_ID;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
$pk->speedX = 0;
|
||||
$pk->speedY = 0;
|
||||
$pk->speedZ = 0;
|
||||
$pk->yaw = 0;
|
||||
$pk->pitch = 0;
|
||||
$pk->metadata = $this->dataProperties;
|
||||
$player->dataPacket($pk);
|
||||
/**
|
||||
*
|
||||
* @param Player $player
|
||||
*/
|
||||
public function spawnTo(Player $player)
|
||||
{
|
||||
$pk = new AddEntityPacket();
|
||||
$pk->eid = $this->getId();
|
||||
$pk->type = Minecart::NETWORK_ID;
|
||||
$pk->x = $this->x;
|
||||
$pk->y = $this->y;
|
||||
$pk->z = $this->z;
|
||||
$pk->speedX = 0;
|
||||
$pk->speedY = 0;
|
||||
$pk->speedZ = 0;
|
||||
$pk->yaw = 0;
|
||||
$pk->pitch = 0;
|
||||
$pk->metadata = $this->dataProperties;
|
||||
$player->dataPacket($pk);
|
||||
|
||||
parent::spawnTo($player);
|
||||
}
|
||||
parent::spawnTo($player);
|
||||
}
|
||||
|
||||
/*public function attack($damage, EntityDamageEvent $source){
|
||||
parent::attack($damage, $source);
|
||||
|
||||
if(!$source->isCancelled()){
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->event = EntityEventPacket::HURT_ANIMATION;
|
||||
foreach($this->getLevel()->getPlayers() as $player){
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param unknown $damage
|
||||
* @param EntityDamageEvent $source
|
||||
*/
|
||||
public function attack($damage, EntityDamageEvent $source)
|
||||
{
|
||||
parent::attack($damage, $source);
|
||||
|
||||
public function getSaveId(){
|
||||
$class = new \ReflectionClass(static::class);
|
||||
return $class->getShortName();
|
||||
}*/
|
||||
if (!$source->isCancelled()) {
|
||||
$pk = new EntityEventPacket();
|
||||
$pk->eid = $this->id;
|
||||
$pk->event = EntityEventPacket::HURT_ANIMATION;
|
||||
foreach ($this->getLevel()->getPlayers() as $player) {
|
||||
$player->dataPacket($pk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function kill()
|
||||
{
|
||||
parent::kill();
|
||||
|
||||
foreach ($this->getDrops() as $item) {
|
||||
$this->getLevel()->dropItem($this, $item);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return unknown
|
||||
*/
|
||||
public function getDrops()
|
||||
{
|
||||
if ($this->hasDropped == false) {
|
||||
$this->hasDropped = true;
|
||||
return [ItemItem::get(ItemItem::MINECART, 0, 1)];
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @return unknown
|
||||
*/
|
||||
public function getSaveId()
|
||||
{
|
||||
$class = new \ReflectionClass(static::class);
|
||||
return $class->getShortName();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param Player $player
|
||||
* @param unknown $playerAction
|
||||
* @return unknown
|
||||
*/
|
||||
public function onPlayerAction(Player $player, $playerAction)
|
||||
{
|
||||
if ($playerAction == 1) {
|
||||
//pressed move button
|
||||
$this->isLinked = true;
|
||||
$this->isMoving = true;
|
||||
$this->isFreeMoving = true;
|
||||
$this->setHealth($this->getMaxHealth());
|
||||
$player->linkEntity($this);
|
||||
} elseif (in_array($playerAction, array(2, 3)) || $playerAction == PlayerActionPacket::ACTION_JUMP) {
|
||||
//touched
|
||||
$this->isLinked = false;
|
||||
$this->isMoving = false;
|
||||
$this->isFreeMoving = false;
|
||||
$this->setLinked(0, $player);
|
||||
$player->setLinked(0, $this);
|
||||
return $this;
|
||||
} elseif ($playerAction == 157) {
|
||||
//playerMove
|
||||
$this->isFreeMoving = true;
|
||||
// try to get the bottom blockId, as Vector
|
||||
$position = $this->getPosition();
|
||||
$blockTemp = $this->level->getBlock($position);
|
||||
if (in_array($blockTemp->getId(), array(27, 28, 66, 126))) {
|
||||
//we are on rail
|
||||
$connected = $blockTemp->check($blockTemp);
|
||||
if (count($connected) >= 1) {
|
||||
foreach ($connected as $newPosition) {
|
||||
if ($this->oldPosition != $newPosition || count($connected) == 1) {
|
||||
$this->oldPosition = $position->add(0, 0, 0);
|
||||
$this->setPosition($newPosition);
|
||||
return $newPosition;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue